main.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #!/usr/bin/env node
  2. "use strict";
  3. var _a;
  4. Object.defineProperty(exports, "__esModule", { value: true });
  5. const fs = require("fs");
  6. const path = require("path");
  7. const commandLineUsage = require("command-line-usage");
  8. const exampleConfig = require("../config.example.json");
  9. const command_1 = require("./command");
  10. const loggers_1 = require("./loggers");
  11. const koishi_1 = require("./koishi");
  12. const twitter_1 = require("./twitter");
  13. const logger = loggers_1.getLogger();
  14. const sections = [
  15. {
  16. header: 'GoCQHTTP Twitter Bot',
  17. content: 'The QQ Bot that forwards twitters.',
  18. },
  19. {
  20. header: 'Synopsis',
  21. content: [
  22. '$ twitter-bot {underline config.json}',
  23. '$ twitter-bot {bold --help}',
  24. ],
  25. },
  26. {
  27. header: 'Documentation',
  28. content: [
  29. 'Project home: {underline https://github.com/CL-Jeremy/mirai-twitter-bot}',
  30. 'Example config: {underline https://git.io/JJ0jN}',
  31. ],
  32. },
  33. ];
  34. const usage = commandLineUsage(sections);
  35. const args = process.argv.slice(2);
  36. if (args.length === 0 || args[0] === 'help' || args[0] === '-h' || args[0] === '--help') {
  37. console.log(usage);
  38. process.exit(0);
  39. }
  40. const configPath = args[0];
  41. let config;
  42. try {
  43. config = JSON.parse(fs.readFileSync(path.resolve(configPath), 'utf8'));
  44. }
  45. catch (e) {
  46. console.log('Failed to parse config file: ', configPath);
  47. console.log(usage);
  48. process.exit(1);
  49. }
  50. const requiredFields = [
  51. 'twitter_consumer_key', 'twitter_consumer_secret', 'twitter_access_token_key', 'twitter_access_token_secret',
  52. 'cq_bot_qq', ...(config.mode || exampleConfig.mode) === 0 ? ['playwright_ws_spec_endpoint'] : [],
  53. ];
  54. const warningFields = [
  55. 'cq_ws_host', 'cq_ws_port', 'cq_access_token',
  56. ...((_a = config.redis) !== null && _a !== void 0 ? _a : exampleConfig.redis) ? ['redis_host', 'redis_port', 'redis_expire_time'] : [],
  57. ];
  58. const optionalFields = [
  59. 'lockfile', 'work_interval', 'webshot_delay', 'loglevel', 'mode', 'resume_on_start', 'redis',
  60. ].concat(warningFields);
  61. if (requiredFields.some((value) => config[value] === undefined)) {
  62. console.log(`${requiredFields.join(', ')} are required`);
  63. process.exit(1);
  64. }
  65. optionalFields.forEach(key => {
  66. if (config[key] === undefined || typeof (config[key]) !== typeof (exampleConfig[key])) {
  67. if (warningFields.includes(key))
  68. logger.warn(`${key} is undefined, use ${exampleConfig[key] || 'empty string'} as default`);
  69. config[key] = exampleConfig[key];
  70. }
  71. });
  72. loggers_1.setLogLevels(config.loglevel);
  73. let lock;
  74. if (fs.existsSync(path.resolve(config.lockfile))) {
  75. try {
  76. lock = JSON.parse(fs.readFileSync(path.resolve(config.lockfile), 'utf8'));
  77. }
  78. catch (err) {
  79. logger.error(`Failed to parse lockfile ${config.lockfile}: `, err);
  80. lock = {
  81. workon: 0,
  82. feed: [],
  83. threads: {},
  84. };
  85. }
  86. fs.access(path.resolve(config.lockfile), fs.constants.W_OK, err => {
  87. if (err) {
  88. logger.fatal(`cannot write lockfile ${path.resolve(config.lockfile)}, permission denied`);
  89. process.exit(1);
  90. }
  91. });
  92. }
  93. else {
  94. lock = {
  95. workon: 0,
  96. feed: [],
  97. threads: {},
  98. };
  99. try {
  100. fs.writeFileSync(path.resolve(config.lockfile), JSON.stringify(lock));
  101. }
  102. catch (err) {
  103. logger.fatal(`cannot write lockfile ${path.resolve(config.lockfile)}, permission denied`);
  104. process.exit(1);
  105. }
  106. }
  107. if (!config.resume_on_start) {
  108. Object.keys(lock.threads).forEach(key => {
  109. lock.threads[key].offset = '-1';
  110. });
  111. }
  112. const qq = new koishi_1.default({
  113. access_token: config.cq_access_token,
  114. host: config.cq_ws_host,
  115. port: config.cq_ws_port,
  116. bot_id: config.cq_bot_qq,
  117. list: (c, a, cb) => command_1.list(c, a, cb, lock),
  118. sub: (c, a, cb) => command_1.sub(c, a, cb, lock, config.lockfile),
  119. unsub: (c, a, cb) => command_1.unsub(c, a, cb, lock, config.lockfile),
  120. });
  121. const worker = new twitter_1.default({
  122. consumerKey: config.twitter_consumer_key,
  123. consumerSecret: config.twitter_consumer_secret,
  124. accessTokenKey: config.twitter_access_token_key,
  125. accessTokenSecret: config.twitter_access_token_secret,
  126. lock,
  127. lockfile: config.lockfile,
  128. workInterval: config.work_interval,
  129. bot: qq,
  130. webshotDelay: config.webshot_delay,
  131. mode: config.mode,
  132. wsUrl: config.playwright_ws_spec_endpoint,
  133. redis: !config.redis ? undefined : {
  134. redisHost: config.redis_host,
  135. redisPort: config.redis_port,
  136. redisExpireTime: config.redis_expire_time,
  137. },
  138. });
  139. worker.launch();
  140. qq.connect();
  141. //# sourceMappingURL=main.js.map