qq.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import * as CQWebsocket from 'cq-websocket';
  2. import * as log4js from 'log4js';
  3. import command from './helper';
  4. const logger = log4js.getLogger('cq-websocket');
  5. logger.level = 'info';
  6. interface IQQProps {
  7. access_token: string;
  8. host: string;
  9. port: number;
  10. list(chat: IChat, args: string[]): string;
  11. sub(chat: IChat, args: string[]): string;
  12. unsub(chat: IChat, args: string[]): string;
  13. }
  14. export default class {
  15. private botInfo;
  16. public bot: CQWebsocket;
  17. private retryInterval = 1000;
  18. private initWebsocket = () => {
  19. this.bot = new CQWebsocket(this.botInfo);
  20. this.bot.on('socket.connect', () => {
  21. logger.info('websocket connected');
  22. this.retryInterval = 1000;
  23. });
  24. this.bot.on('socket.close', () => {
  25. logger.error('websocket closed');
  26. this.reconnect();
  27. });
  28. this.bot.on('socket.error', () => {
  29. logger.error('websocket connect error');
  30. this.reconnect();
  31. });
  32. this.bot.on('message', (e, context) => {
  33. e.cancel();
  34. const chat: IChat = {
  35. chatType: context.message_type,
  36. chatID: 0,
  37. };
  38. switch (context.message_type) {
  39. case ChatType.Private:
  40. chat.chatID = context.user_id;
  41. break;
  42. case ChatType.Group:
  43. chat.chatID = context.group_id;
  44. break;
  45. case ChatType.Discuss:
  46. chat.chatID = context.discuss_id;
  47. }
  48. const cmdObj = command(context.raw_message);
  49. switch (cmdObj.cmd) {
  50. case 'twitter_sub':
  51. case 'twitter_subscribe':
  52. return this.botInfo.sub(chat, cmdObj.args);
  53. case 'twitter_unsub':
  54. case 'twitter_unsubscribe':
  55. return this.botInfo.unsub(chat, cmdObj.args);
  56. case 'ping':
  57. case 'twitter':
  58. return this.botInfo.list(chat, cmdObj.args);
  59. case 'help':
  60. return `推特搬运机器人:
  61. /twitter - 查询当前聊天中的订阅
  62. /twitter_subscribe [链接] - 订阅 Twitter 搬运
  63. /twitter_unsubscribe [链接] - 退订 Twitter 搬运`;
  64. }
  65. });
  66. }
  67. public connect = () => {
  68. this.initWebsocket();
  69. logger.warn('connecting to websocket...');
  70. this.bot.connect();
  71. }
  72. private reconnect = () => {
  73. this.retryInterval *= 2;
  74. if (this.retryInterval > 300000) this.retryInterval = 300000;
  75. logger.info(`retrying in ${this.retryInterval / 1000}s...`);
  76. setTimeout(() => {
  77. logger.warn('reconnecting to websocket...');
  78. this.connect();
  79. }, this.retryInterval);
  80. }
  81. constructor(opt: IQQProps) {
  82. logger.info(`init cqwebsocket for ${opt.host}:${opt.port}, with access_token ${opt.access_token}`);
  83. this.botInfo = {
  84. access_token: opt.access_token,
  85. enableAPI: true,
  86. enableEvent: true,
  87. host: opt.host,
  88. port: opt.port,
  89. };
  90. }
  91. }