main.ts 4.2 KB

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