Bläddra i källkod

:construction: add qq websocket

LI JIAHAO 6 år sedan
förälder
incheckning
d6bf4bc99d
8 ändrade filer med 253 tillägg och 8 borttagningar
  1. 23 0
      dist/command.js
  2. 5 3
      dist/main.js
  3. 84 0
      dist/qq.js
  4. 2 2
      package.json
  5. 24 0
      src/command.ts
  6. 3 3
      src/main.ts
  7. 10 0
      src/model.d.ts
  8. 102 0
      src/qq.ts

+ 23 - 0
dist/command.js

@@ -0,0 +1,23 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+function default_1(message) {
+    message = message.trim();
+    message = message.replace('\\\\', '\\0x5c');
+    message = message.replace('\\\"', '\\0x22');
+    message = message.replace('\\\'', '\\0x27');
+    let strs = message.match(/'[\s\S]*?'|"[\s\S]*?"|\S*\[CQ:[\s\S]*?\]\S*|\S+/mg);
+    const cmd = strs.length ? strs[0].length ? strs[0].substring(0, 1) === '/' ? strs[0].substring(1) : '' : '' : '';
+    const args = strs.slice(1).map(arg => {
+        arg = arg.replace(/^["']+|["']+$/g, '');
+        arg = arg.replace('\\0x27', '\\\'');
+        arg = arg.replace('\\0x22', '\\\"');
+        arg = arg.replace('\\0x5c', '\\\\');
+        return arg;
+    });
+    return {
+        cmd,
+        args,
+    };
+}
+exports.default = default_1;
+;

+ 5 - 3
bin/main.js → dist/main.js

@@ -1,7 +1,9 @@
 #!/usr/bin/env node
-const commandLineUsage = require('command-line-usage');
-const log4js = require('log4js');
-const path = require('path');
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const commandLineUsage = require("command-line-usage");
+const log4js = require("log4js");
+const path = require("path");
 const logger = log4js.getLogger();
 logger.level = 'info';
 const sections = [

+ 84 - 0
dist/qq.js

@@ -0,0 +1,84 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const CQWebsocket = require("cq-websocket");
+const log4js = require("log4js");
+const command_1 = require("./command");
+const logger = log4js.getLogger('cq-websocket');
+logger.level = 'info';
+function default_1(opt) {
+    this.bot = new CQWebsocket({
+        access_token: opt.access_token,
+        enableAPI: true,
+        enableEvent: true,
+        host: opt.host,
+        port: opt.port,
+    });
+    let retryInterval = 1000;
+    this.bot.on('socket.connect', () => {
+        logger.info('websocket connected');
+        retryInterval = 1000;
+    });
+    const connect = () => {
+        logger.warn('connecting to websocket...');
+        this.bot.connect();
+    };
+    const reconnect = () => {
+        retryInterval *= 2;
+        if (retryInterval > 300000)
+            retryInterval = 300000;
+        logger.info(`retrying in ${retryInterval / 1000}s...`);
+        setTimeout(() => {
+            logger.warn('reconnecting to websocket...');
+            connect();
+        }, retryInterval);
+    };
+    this.bot.on('socket.close', () => {
+        logger.error('websocket closed');
+        reconnect();
+    });
+    this.bot.on('socket.error', () => {
+        logger.error('websocket connect error');
+        reconnect();
+    });
+    this.bot.on('message', (e, context) => {
+        e.cancel();
+        const chat = {
+            chatType: context.message_type,
+            chatID: 0,
+        };
+        switch (context.message_type) {
+            case ChatType.Private:
+                chat.chatID = context.user_id;
+                break;
+            case ChatType.Group:
+                chat.chatID = context.group_id;
+                break;
+            case ChatType.Discuss:
+                chat.chatID = context.discuss_id;
+                break;
+        }
+        let cmdObj = command_1.default(context.raw_message);
+        switch (cmdObj.cmd) {
+            case 'twitter_sub':
+            case 'twitter_subscribe':
+                opt.sub(chat, cmdObj.args);
+                return;
+            case 'twitter_unsub':
+            case 'twitter_unsubscribe':
+                opt.unsub(chat, cmdObj.args);
+                return;
+            case 'ping':
+            case 'twitter':
+                opt.list(chat, cmdObj.args);
+                return;
+            case 'help':
+                return `推特搬运机器人:
+/twitter - 查询当前聊天中的订阅
+/twitter_subscribe [链接] - 订阅 Twitter 搬运
+/twitter_unsubscribe [链接] - 退订 Twitter 搬运`;
+        }
+    });
+    return this;
+}
+exports.default = default_1;
+;

+ 2 - 2
package.json

@@ -1,9 +1,9 @@
 {
   "bin": {
-    "cqhttp-twitter-bot": "./bin/main.js"
+    "cqhttp-twitter-bot": "./dist/main.js"
   },
   "scripts": {
-    "build": "tsc --outDir bin"
+    "build": "tsc --outDir dist"
   },
   "dependencies": {
     "command-line-usage": "^5.0.5",

+ 24 - 0
src/command.ts

@@ -0,0 +1,24 @@
+interface ICommand {
+  cmd: string;
+  args: string[];
+}
+
+export default function (message: string): ICommand {
+  message = message.trim();
+  message = message.replace('\\\\', '\\0x5c');
+  message = message.replace('\\\"', '\\0x22');
+  message = message.replace('\\\'', '\\0x27');
+  let strs = message.match(/'[\s\S]*?'|"[\s\S]*?"|\S*\[CQ:[\s\S]*?\]\S*|\S+/mg);
+  const cmd = strs.length ? strs[0].length ? strs[0].substring(0, 1) === '/' ? strs[0].substring(1) : '' : '' : '';
+  const args = strs.slice(1).map(arg => {
+    arg = arg.replace(/^["']+|["']+$/g, '');
+    arg = arg.replace('\\0x27', '\\\'');
+    arg = arg.replace('\\0x22', '\\\"');
+    arg = arg.replace('\\0x5c', '\\\\');
+    return arg;
+  });
+  return {
+    cmd,
+    args,
+  }
+};

+ 3 - 3
src/main.ts

@@ -1,8 +1,8 @@
 #!/usr/bin/env node
 
-const commandLineUsage = require('command-line-usage');
-const log4js = require('log4js');
-const path = require('path');
+import * as commandLineUsage from 'command-line-usage';
+import * as log4js from 'log4js';
+import * as path from 'path';
 
 const logger = log4js.getLogger();
 logger.level = 'info';

+ 10 - 0
src/model.d.ts

@@ -0,0 +1,10 @@
+declare enum ChatType {
+  Private = 'private',
+  Group = 'group',
+  Discuss = 'discuss',
+}
+
+interface IChat {
+  chatID: number,
+  chatType: ChatType,
+}

+ 102 - 0
src/qq.ts

@@ -0,0 +1,102 @@
+import * as CQWebsocket from 'cq-websocket';
+import * as log4js from 'log4js';
+import command from './command';
+
+const logger = log4js.getLogger('cq-websocket');
+logger.level = 'info';
+
+interface IQQProps {
+  access_token: string;
+  host: string;
+  port: number;
+  list: (chat: IChat, args: string[]) => void;
+  sub: (chat: IChat, args: string[]) => void;
+  unsub: (chat: IChat, args: string[]) => void;
+}
+
+interface IQQ {
+  bot: CQWebsocket;
+}
+
+export default function (opt: IQQProps): IQQ {
+  this.bot = new CQWebsocket({
+    access_token: opt.access_token,
+    enableAPI: true,
+    enableEvent: true,
+    host: opt.host,
+    port: opt.port,
+  });
+
+  let retryInterval = 1000;
+
+  this.bot.on('socket.connect', () => {
+    logger.info('websocket connected');
+    retryInterval = 1000;
+  });
+
+  const connect = () => {
+    logger.warn('connecting to websocket...');
+    this.bot.connect();
+  };
+
+  const reconnect = () => {
+    retryInterval *= 2;
+    if (retryInterval > 300000) retryInterval = 300000;
+    logger.info(`retrying in ${retryInterval / 1000}s...`);
+    setTimeout(() => {
+      logger.warn('reconnecting to websocket...');
+      connect();
+    }, retryInterval);
+  };
+
+  this.bot.on('socket.close', () => {
+    logger.error('websocket closed');
+    reconnect();
+  });
+
+  this.bot.on('socket.error', () => {
+    logger.error('websocket connect error');
+    reconnect();
+  });
+
+  this.bot.on('message', (e, context) => {
+    e.cancel();
+    const chat: IChat = {
+      chatType: context.message_type,
+      chatID: 0,
+    };
+    switch (context.message_type) {
+      case ChatType.Private:
+        chat.chatID = context.user_id;
+        break;
+      case ChatType.Group:
+        chat.chatID = context.group_id;
+        break;
+      case ChatType.Discuss:
+        chat.chatID = context.discuss_id;
+        break;
+    }
+    let cmdObj = command(context.raw_message);
+    switch (cmdObj.cmd) {
+      case 'twitter_sub':
+      case 'twitter_subscribe':
+        opt.sub(chat, cmdObj.args);
+        return;
+      case 'twitter_unsub':
+      case 'twitter_unsubscribe':
+        opt.unsub(chat, cmdObj.args);
+        return;
+      case 'ping':
+      case 'twitter':
+        opt.list(chat, cmdObj.args);
+        return;
+      case 'help':
+        return `推特搬运机器人:
+/twitter - 查询当前聊天中的订阅
+/twitter_subscribe [链接] - 订阅 Twitter 搬运
+/twitter_unsubscribe [链接] - 退订 Twitter 搬运`;
+    }
+  });
+
+  return this;
+};