main.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #!/usr/bin/env node
  2. import * as commandLineUsage from 'command-line-usage';
  3. import * as fs from 'fs';
  4. import * as path from 'path';
  5. import { list, sub, unsub } from './command';
  6. import { getLogger, setLogLevels } from './loggers';
  7. import QQBot from './mirai';
  8. import Worker from './twitter';
  9. const logger = getLogger();
  10. const sections = [
  11. {
  12. header: 'MiraiTS Twitter Bot',
  13. content: 'The QQ Bot that forwards twitters.',
  14. },
  15. {
  16. header: 'Synopsis',
  17. content: [
  18. '$ mirai-twitter-bot {underline config.json}',
  19. '$ mirai-twitter-bot {bold --help}',
  20. ],
  21. },
  22. {
  23. header: 'Documentation',
  24. content: [
  25. 'Project home: {underline https://github.com/CL-Jeremy/mirai-twitter-bot}',
  26. 'Example config: {underline https://git.io/JJ0jN}',
  27. ],
  28. },
  29. ];
  30. const usage = commandLineUsage(sections);
  31. const args = process.argv.slice(2);
  32. if (args.length === 0 || args[0] === 'help' || args[0] === '-h' || args[0] === '--help') {
  33. console.log(usage);
  34. process.exit(0);
  35. }
  36. const configPath = args[0];
  37. let config;
  38. try {
  39. config = require(path.resolve(configPath));
  40. } catch (e) {
  41. console.log('Failed to parse config file: ', configPath);
  42. console.log(usage);
  43. process.exit(1);
  44. }
  45. if (config.twitter_consumer_key === undefined ||
  46. config.twitter_consumer_secret === undefined ||
  47. config.twitter_access_token_key === undefined ||
  48. config.twitter_access_token_secret === undefined) {
  49. console.log('twitter_consumer_key twitter_consumer_secret twitter_access_token_key twitter_access_token_secret are required');
  50. process.exit(1);
  51. }
  52. if (config.mirai_http_host === undefined) {
  53. config.mirai_http_host = '127.0.0.1';
  54. logger.warn('mirai_http_host is undefined, use 127.0.0.1 as default');
  55. }
  56. if (config.mirai_http_port === undefined) {
  57. config.mirai_http_port = 8080;
  58. logger.warn('mirai_http_port is undefined, use 8080 as default');
  59. }
  60. if (config.mirai_access_token === undefined) {
  61. config.mirai_access_token = '';
  62. logger.warn('mirai_access_token is undefined, use empty string as default');
  63. }
  64. if (config.lockfile === undefined) {
  65. config.lockfile = 'subscriber.lock';
  66. }
  67. if (config.work_interval === undefined) {
  68. config.work_interval = 60;
  69. }
  70. if (config.webshot_delay === undefined) {
  71. config.webshot_delay = 10000;
  72. }
  73. if (config.loglevel === undefined) {
  74. config.loglevel = 'info';
  75. }
  76. if (typeof config.mode !== 'number') {
  77. config.mode = 0;
  78. }
  79. if (typeof config.resume_on_start !== 'boolean') {
  80. config.resume_on_start = false;
  81. }
  82. setLogLevels(config.loglevel);
  83. let lock: ILock;
  84. if (fs.existsSync(path.resolve(config.lockfile))) {
  85. try {
  86. lock = JSON.parse(fs.readFileSync(path.resolve(config.lockfile), 'utf8'));
  87. } catch (err) {
  88. logger.error(`Failed to parse lockfile ${config.lockfile}: `, err);
  89. lock = {
  90. workon: 0,
  91. feed: [],
  92. threads: {},
  93. };
  94. }
  95. fs.access(path.resolve(config.lockfile), fs.constants.W_OK, err => {
  96. if (err) {
  97. logger.fatal(`cannot write lockfile ${path.resolve(config.lockfile)}, permission denied`);
  98. process.exit(1);
  99. }
  100. });
  101. } else {
  102. lock = {
  103. workon: 0,
  104. feed: [],
  105. threads: {},
  106. };
  107. try {
  108. fs.writeFileSync(path.resolve(config.lockfile), JSON.stringify(lock));
  109. } catch (err) {
  110. logger.fatal(`cannot write lockfile ${path.resolve(config.lockfile)}, permission denied`);
  111. process.exit(1);
  112. }
  113. }
  114. if (!config.resume_on_start) {
  115. Object.keys(lock.threads).forEach(key => {
  116. lock.threads[key].offset = '-1';
  117. });
  118. }
  119. const qq = new QQBot({
  120. access_token: config.mirai_access_token,
  121. host: config.mirai_http_host,
  122. port: config.mirai_http_port,
  123. bot_id: config.mirai_bot_qq,
  124. list: (c, a) => list(c, a, lock),
  125. sub: (c, a) => sub(c, a, lock, config.lockfile),
  126. unsub: (c, a) => unsub(c, a, lock, config.lockfile),
  127. });
  128. const worker = new Worker({
  129. consumer_key: config.twitter_consumer_key,
  130. consumer_secret: config.twitter_consumer_secret,
  131. access_token_key: config.twitter_access_token_key,
  132. access_token_secret: config.twitter_access_token_secret,
  133. lock,
  134. lockfile: config.lockfile,
  135. workInterval: config.work_interval,
  136. bot: qq,
  137. webshotDelay: config.webshot_delay,
  138. mode: config.mode,
  139. });
  140. worker.launch();
  141. qq.connect();