├── .dockerignore ├── .editorconfig ├── .gitignore ├── .importsortrc ├── .markdownlintrc ├── .npmignore ├── .prettierignore ├── .prettierrc ├── docker ├── Dockerfile └── deps │ └── docker-compose.yml ├── jest.config.js ├── jest.setup.js ├── package.json ├── readme.md ├── src ├── index.ts └── rest │ ├── index.ts │ ├── internal │ ├── index.ts │ ├── request.spec.ts │ └── request.ts │ ├── rest.spec.ts │ ├── rest.ts │ └── types │ ├── endpoints.ts │ ├── http.ts │ ├── index.ts │ └── response.ts ├── tsconfig.app.json ├── tsconfig.dev.json ├── tsconfig.json ├── tsconfig.spec.json ├── tslint.json └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset=utf-8 3 | end_of_line=lf 4 | insert_final_newline=false 5 | indent_style=space 6 | indent_size=2 7 | 8 | [{index,*.ng,*.sht,*.html,*.shtm,*.shtml,*.htm}] 9 | indent_style=space 10 | indent_size=2 11 | 12 | [{.babelrc,.stylelintrc,.eslintrc,jest.config,*.json,*.jsb3,*.jsb2,*.bowerrc}] 13 | indent_style=space 14 | indent_size=2 15 | 16 | [{*.applejs,*.js}] 17 | indent_style=space 18 | indent_size=2 19 | 20 | [{*.ats,*.ts}] 21 | indent_style=space 22 | indent_size=2 23 | 24 | [*.less] 25 | indent_style=space 26 | indent_size=2 27 | 28 | [*.scss] 29 | indent_style=space 30 | indent_size=2 31 | 32 | [*.coffee] 33 | indent_style=space 34 | indent_size=2 35 | 36 | [{.analysis_options,*.yml,*.yaml}] 37 | indent_style=space 38 | indent_size=2 39 | 40 | [tslint.json] 41 | indent_style=space 42 | indent_size=2 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | log 4 | *.log 5 | npm-debug.log* 6 | yarn-debug.log* 7 | yarn-error.log* 8 | 9 | # Runtime data 10 | pids 11 | *.pid 12 | *.seed 13 | *.pid.lock 14 | 15 | # Directory for instrumented libs generated by jscoverage/JSCover 16 | lib-cov 17 | 18 | # Coverage directory used by tools like istanbul 19 | coverage 20 | 21 | # nyc test coverage 22 | .nyc_output 23 | 24 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 25 | .grunt 26 | 27 | # Bower dependency directory (https://bower.io/) 28 | bower_components 29 | 30 | # node-waf configuration 31 | .lock-wscript 32 | 33 | # Compiled binary addons (http://nodejs.org/api/addons.html) 34 | build/Release 35 | 36 | # Dependency directories 37 | node_modules/ 38 | jspm_packages/ 39 | 40 | # Typescript v1 declaration files 41 | typings/ 42 | 43 | # Optional npm cache directory 44 | .npm 45 | 46 | # Optional eslint cache 47 | .eslintcache 48 | 49 | # Optional REPL history 50 | .node_repl_history 51 | 52 | # Output of 'npm pack' 53 | *.tgz 54 | 55 | # Yarn Integrity file 56 | .yarn-integrity 57 | 58 | # dotenv environment variables file 59 | .env 60 | 61 | dist 62 | deploy 63 | .history 64 | db/* 65 | package-lock.json 66 | .vscode 67 | .coveralls.yml 68 | type-docs 69 | .idea 70 | /docker/deps/coolq -------------------------------------------------------------------------------- /.importsortrc: -------------------------------------------------------------------------------- 1 | ".ts": { 2 | "parser": "typescript", 3 | "style": "module-alias", 4 | } 5 | -------------------------------------------------------------------------------- /.markdownlintrc: -------------------------------------------------------------------------------- 1 | { 2 | "default": true, 3 | "heading-increment": true, 4 | "first-heading-h1": { "level": 1 }, 5 | "heading-style": { "consistent": "atx" }, 6 | "ul-style": { "style": "consistent" }, 7 | "ul-start-left": false, 8 | "bullet": true, 9 | "whitespace": false, 10 | "no-hard-tabs": false, 11 | "no-reversed-links": true, 12 | "no-multiple-blanks": true, 13 | "line-length": false, 14 | "commands-show-output": false, 15 | "no-missing-space-atx": true, 16 | "no-multiple-space-atx": true, 17 | "no-missing-space-closed-atx": true, 18 | "no-multiple-space-closed-atx": true, 19 | "blanks-around-headings": true, 20 | "heading-start-left": true, 21 | "no-duplicate-heading": false, 22 | "single-h1": { "level": 1 }, 23 | "no-trailing-punctuation": true, 24 | "no-multiple-space-blockquote": true, 25 | "no-blanks-blockquote": true, 26 | "ol-prefix": true, 27 | "list-marker-space": true, 28 | "blanks-around-fences": true, 29 | "blanks-around-lists": true, 30 | "no-inline-html": true, 31 | "no-bare-urls": true, 32 | "hr-style": true, 33 | "no-emphasis-as-heading": true, 34 | "no-space-in-emphasis": true, 35 | "no-space-in-code": true, 36 | "no-space-in-links": true, 37 | "fenced-code-language": true, 38 | "first-line-h1": { "level": 1 }, 39 | "no-empty-links": true, 40 | "required-headings": true, 41 | "proper-names": [], 42 | "no-alt-text": true 43 | } 44 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | 4 | # ignore the .ts files 5 | /src 6 | /test 7 | 8 | # dokcer 9 | /docker/deps/coolq 10 | .dockerignore 11 | 12 | # ide 13 | .idea 14 | .vscode 15 | 16 | 17 | # misc 18 | /log 19 | /logs 20 | npm-debug.log 21 | .npmignore 22 | .git* 23 | .prettie* 24 | .editorconfig 25 | .importsortrc 26 | .markdownlintrc 27 | appveyor.yml 28 | package-lock.json 29 | jest* 30 | tsconfig* 31 | tslint.json 32 | .DS_Store 33 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "useTabs": false, 4 | "semi": true, 5 | "singleQuote": true, 6 | "trailingComma": "all", 7 | "bracketSpacing": true, 8 | "arrowParens": "always", 9 | "overrides": [ 10 | { 11 | "files": "*.ts", 12 | "options": { 13 | "printWidth": 140 14 | } 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM coolq/wine-coolq:latest 2 | 3 | ARG GIT_TAG 4 | 5 | ADD https://github.com/richardchien/coolq-http-api/releases/download/${GIT_TAG}/io.github.richardchien.coolqhttpapi.cpk /home/user/io.github.richardchien.coolqhttpapi.cpk 6 | ADD bootstrap.py /home/user/bootstrap.py 7 | RUN chown user:user /home/user/io.github.richardchien.coolqhttpapi.cpk /home/user/bootstrap.py 8 | RUN echo "\n\nsudo -E -Hu user /usr/bin/python3 /home/user/bootstrap.py" >> /etc/cont-init.d/110-get-coolq 9 | 10 | EXPOSE 5700 11 | 12 | VOLUME ["/home/user/coolq"] -------------------------------------------------------------------------------- /docker/deps/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | cqhttp: 5 | image: richardchien/cqhttp:latest 6 | # network_mode: "host" # 取消注释此项将使容器使用宿主机网络,此时相当于插件直接运行在宿主机,下面的 ports 可以全部删掉,另外注意根据需要配置 CQHTTP 只监听 127.0.0.1 7 | ports: 8 | - 9000:9000 # noVNC 管理 9 | - 127.0.0.1:5700:5700 # CQHTTP 默认的 HTTP 端口 10 | - 127.0.0.1:6700:6700 # CQHTTP 默认的 WebSocket 端口 11 | restart: always # 重启策略 12 | volumes: 13 | - ./coolq/:/home/user/coolq/ # 挂载 酷Q 主目录 14 | environment: 15 | VNC_PASSWD: PAsSwoRd # noVNC 连接密码 16 | COOLQ_ACCOUNT: -1 # 要登录的机器人 QQ 号 17 | FORCE_ENV: 'true' # 强制使用环境变量中的配置(下面以 CQHTTP_ 开头的那些),这会使手动对 CQHTTP 配置文件的修改在重启容器后失效,删除此项则下面的配置只在容器第一次启动时写入配置文件 18 | COOLQ_URL: 'https://dlsec.cqp.me/cqa-tuling' # 如果使用 酷Q Air,本行可以删除,如使用 酷Q Pro,需将 URL 中的 cqa-tuling 改为 cqp-tuling 19 | CQHTTP_POST_URL: http://172.17.0.1:8080 # HTTP 上报地址,172.17.0.1 通常是宿主机在默认网桥上的 IP 地址,可通过 docker inspect bridge 查看 20 | CQHTTP_SERVE_DATA_FILES: 'true' 21 | CQHTTP_USE_WS: 'true' 22 | # 更多其它配置项 23 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rootDir: '.', 3 | setupFilesAfterEnv: ['./jest.setup.js'], 4 | moduleFileExtensions: ['js', 'json', 'ts'], 5 | modulePathIgnorePatterns: ['dist', '.history'], 6 | globals: { 7 | 'ts-jest': { 8 | tsConfig: './tsconfig.spec.json', 9 | isolatedModules: true 10 | }, 11 | }, 12 | transform: { 13 | '^.+\\.ts$': 'ts-jest', 14 | }, 15 | testMatch: ['/src/**/*.spec.ts'], 16 | testURL: 'http://localhost/', 17 | collectCoverageFrom: ['src/**/*.{js,ts}', '!src/**/main.{js,ts}', '!src/**/index.{js,ts}', '!**/node_modules/**'], 18 | coveragePathIgnorePatterns: ['/node_modules/', '/test-helpers/', '/main.{js,ts}'], 19 | coverageReporters: ['json', 'lcov'], 20 | verbose: true, 21 | preset: 'ts-jest', 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /jest.setup.js: -------------------------------------------------------------------------------- 1 | jest.setTimeout(45000*10000); 2 | 3 | // test in node env https://stackoverflow.com/a/43020260 4 | global.XMLHttpRequest = undefined; 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ioqq", 3 | "version": "1.0.0", 4 | "description": "通过js代码调用QQ的模块,实现QQ机器人功能", 5 | "license": "GPL-3.0-or-later", 6 | "main": "dist/index.js", 7 | "typings": "dist/index.d.ts", 8 | "engines": { 9 | "node": ">= 10.15.0", 10 | "npm": ">= 6.4.1", 11 | "yarn": ">= 1.12.3" 12 | }, 13 | "scripts": { 14 | "bdd": "yarn jest --watch --onlyChanged", 15 | "build:prod": "yarn build:preprocess && yarn tsc:app", 16 | "build:preprocess": "rimraf dist", 17 | "ci:build-check": "yarn run tsc:app --noEmit", 18 | "coverage": "jest -c jest.config.js --collectCoverage", 19 | "docker:up": "docker-compose -f ./docker/deps/docker-compose.yml up -d", 20 | "docker:stop": "docker-compose -f ./docker/deps/docker-compose.yml stop", 21 | "docker:down": "docker-compose -f ./docker/deps/docker-compose.yml down && yarn rm:coolq", 22 | "format": "yarn format:ts:import && prettier --config .prettierrc --write '{docker,src}/**/*.{ts,md,yaml,yml}'", 23 | "format:ts:import": "import-sort --write 'src/**/*.ts'", 24 | "jest": "jest -c jest.config.js", 25 | "lint": "yarn lint:ts", 26 | "lint:ts": "tslint -p tsconfig.json -c tslint.json", 27 | "prepublishOnly": "yarn build:prod", 28 | "rm:coolq": "rimraf ./docker/deps/coolq", 29 | "test": "yarn jest --runInBand", 30 | "tsc:app": "tsc -p tsconfig.app.json", 31 | "tsc:dev": "tsc -p tsconfig.dev.json" 32 | }, 33 | "keywords": [ 34 | "qq", 35 | "QQ", 36 | "qq robot", 37 | "qq chat", 38 | "qq api", 39 | "qq sdk", 40 | "腾讯", 41 | "tencent" 42 | ], 43 | "repository": { 44 | "type": "git", 45 | "url": "git+https://github.com/zlq4863947/ioqq.git" 46 | }, 47 | "author": "zlq4863947@gmail.com", 48 | "bugs": { 49 | "url": "https://github.com/zlq4863947/ioqq/issues" 50 | }, 51 | "homepage": "https://github.com/zlq4863947/ioqq#readme", 52 | "devDependencies": { 53 | "@types/jest": "^24.0.11", 54 | "@types/qs": "^6.5.3", 55 | "@types/url-join": "^4.0.0", 56 | "import-sort": "^6.0.0", 57 | "import-sort-cli": "^6.0.0", 58 | "import-sort-parser-typescript": "^6.0.0", 59 | "import-sort-style-module-alias": "^1.0.4", 60 | "jest": "^24.5.0", 61 | "prettier": "^1.16.4", 62 | "ts-jest": "^24.0.0", 63 | "ts-node": "^8.0.3", 64 | "tsconfig-paths": "^3.8.0", 65 | "tslint": "^5.14.0", 66 | "tslint-eslint-rules": "^5.4.0", 67 | "typescript": "^3.3.4000", 68 | "vrsource-tslint-rules": "^6.0.0", 69 | "yarn": "^1.17.3" 70 | }, 71 | "dependencies": { 72 | "axios": "^0.19.0", 73 | "qs": "^6.8.0", 74 | "rimraf": "^3.0.0", 75 | "url-join": "^4.0.1" 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ioqq上手指南 2 | 3 | **ioqq**为调用**酷Q** 的 DLL 接口来操作qq,从而使qq可通过编程编写成qq机器人的API库。 4 | **酷Q**安装环境可使用**ioqq**提供的命令一键安装及运行。 5 | 6 | ## 功能 7 | 8 | - 通过API操纵QQ 9 | 10 | ## 前提环境 11 | 12 | - 安装[docker](https://www.docker.com/) 13 | 14 | > 也可以直接安装[酷Q](https://cqp.cc/t/23253),不过建议安装[docker](https://www.docker.com/),便于使用ioqq管理酷Q环境 15 | 16 | ## 环境安装 17 | 18 | ### 1、安装ioqq模块 19 | 运行 `npm install ioqq` 20 | 21 | ### 2、安装并运行酷Q 22 | 运行 `npm explore ioqq -- npm run docker:up` 23 | ![](https://upload-images.jianshu.io/upload_images/5664775-97735822a8c614e7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 24 | 25 | > 运行`npm explore ioqq -- npm run docker:stop`,可以停止运行docker的酷Q容器 26 | > 运行`npm explore ioqq -- npm run docker:down`,可以停止并删除docker的酷Q容器 27 | 28 | ### 3、配置酷Q,登录希望被程序控制的QQ 29 | 30 | - 使用浏览器进入`127.0.0.1:9000`地址 31 | ![](https://upload-images.jianshu.io/upload_images/5664775-f298a5ce4b740886.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 32 | 33 | - 输入默认密码: `PAsSwoRd`, 点击`Send Password`按钮 34 | ![](https://upload-images.jianshu.io/upload_images/5664775-f263c921e1684b6b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 35 | 36 | - 输入qq账号和密码,建议使用小号(Q龄尽量别太小),登录的QQ需要开启安全设备锁。 37 | ![](https://upload-images.jianshu.io/upload_images/5664775-141ca5356ad8a17d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 38 | 39 | - 填写正确qq号及密码并点击确定按钮后,会提示安全验证(没开启设备锁的同学,会被提示要求开启设备锁),点击`是`,输入正确验证码后,点击确定 40 | ![](https://upload-images.jianshu.io/upload_images/5664775-b51771cf99ff1b8d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 41 | 42 | - 成功在酷Q上登录qq 43 | ![](https://upload-images.jianshu.io/upload_images/5664775-abc12dfb0f9e239e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 44 | 45 | ### 使用方法 46 | 47 | - 手动创建`test.js`文件后,复制以下代码: 48 | 49 | ``` 50 | var { Rest } = require("ioqq"); 51 | 52 | var rest = new Rest("http://127.0.0.1:5700"); 53 | rest.sendPrivateMessage(123456, `测试的消息,t=${Date.now()}`); 54 | ``` 55 | > Rest中的`http://127.0.0.1:5700`为默认http接口地址 56 | > `sendPrivateMessage`为给指定好友发送私有消息,其中第一个参数为对方QQ号码 57 | 58 | - 运行 `node test` 59 | ![](https://upload-images.jianshu.io/upload_images/5664775-1918974e3562e3a3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 60 | 61 | - 运行结果 62 | ![](https://upload-images.jianshu.io/upload_images/5664775-5f8a3275585c4c05.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 63 | 64 | 以上就是安装及使用ioqq的教程,其他详细信息,请参考[ioqq](https://github.com/zlq4863947/ioqq)项目说明。 65 | 66 | ### 常用方法 67 | 68 | - sendGroupMessage 69 | 发送Q群消息 70 | 71 | - sendPrivateMessage 72 | 发送个人消息 73 | 74 | - getGroupList 75 | 获取所有已加入Q群的信息 -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './rest'; 2 | -------------------------------------------------------------------------------- /src/rest/index.ts: -------------------------------------------------------------------------------- 1 | export * from './rest'; 2 | -------------------------------------------------------------------------------- /src/rest/internal/index.ts: -------------------------------------------------------------------------------- 1 | export * from './request'; 2 | -------------------------------------------------------------------------------- /src/rest/internal/request.spec.ts: -------------------------------------------------------------------------------- 1 | import { HttpMethod } from '../types'; 2 | import { RequestOptions, request } from './request'; 3 | 4 | describe('request function', () => { 5 | it('should request http', async () => { 6 | const options: RequestOptions = { 7 | url: 'http://127.0.0.1:5700/send_group_msg', 8 | method: HttpMethod.GET, 9 | data: { 10 | group_id: 814067625, 11 | message: `测试的消息,t=${Date.now()}`, 12 | }, 13 | }; 14 | const res = await request(options); 15 | expect(res).toBeDefined(); 16 | expect(res.error).toBeUndefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/rest/internal/request.ts: -------------------------------------------------------------------------------- 1 | import Axios, { AxiosRequestConfig } from 'axios'; 2 | import { stringify } from 'qs'; 3 | 4 | import { HttpMethod, RestResponse } from '../types'; 5 | 6 | import urljoin = require('url-join'); 7 | 8 | export interface RequestOptions { 9 | url: string; 10 | method: HttpMethod; 11 | data: { [attr: string]: any }; 12 | accessToken?: string; 13 | } 14 | 15 | export async function request(options: RequestOptions): Promise { 16 | const config: AxiosRequestConfig = { 17 | method: options.method, 18 | }; 19 | if (options.accessToken) { 20 | options.data['access_token'] = options.accessToken; 21 | } 22 | 23 | let query = ''; 24 | if (options.method !== HttpMethod.GET) { 25 | config.data = options.data; 26 | } else { 27 | query = Object.keys(options.data).length !== 0 ? `?${stringify(options.data)}` : ''; 28 | } 29 | 30 | const url = urljoin(options.url, query); 31 | 32 | try { 33 | const response = await Axios(url, config); 34 | 35 | return { body: response.data }; 36 | } catch (error) { 37 | return { 38 | body: {}, 39 | error: error.response.data.error, 40 | }; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/rest/rest.spec.ts: -------------------------------------------------------------------------------- 1 | import { Rest } from './rest'; 2 | 3 | describe('Rest', () => { 4 | let rest: Rest; 5 | 6 | beforeAll(() => { 7 | rest = new Rest('http://127.0.0.1:5700'); 8 | }); 9 | 10 | it('should send message to qq group', async () => { 11 | const res = await rest.sendGroupMessage(814067625, `测试的消息,t=${Date.now()}`); 12 | expect(res).toBeDefined(); 13 | expect(res.error).toBeUndefined(); 14 | expect(res.status).toEqual('ok'); 15 | }); 16 | 17 | it('should send message to qq friend', async () => { 18 | const res = await rest.sendPrivateMessage(123453, `测试的消息,t=${Date.now()}`); 19 | expect(res).toBeDefined(); 20 | expect(res.error).toBeUndefined(); 21 | expect(res.status).toEqual('ok'); 22 | }); 23 | 24 | it('should get qq group list info', async () => { 25 | const res = await rest.getGroupList(); 26 | expect(res).toBeDefined(); 27 | expect(res.error).toBeUndefined(); 28 | expect(res.status).toEqual('ok'); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /src/rest/rest.ts: -------------------------------------------------------------------------------- 1 | import { request } from './internal'; 2 | import { Endpoints, HttpMethod, RestGroupListResponse, RestMessageResponse } from './types'; 3 | 4 | export class Rest { 5 | constructor(private readonly url: string, private readonly accessToken?: string) {} 6 | 7 | /** 8 | * 向qq群发送消息 9 | * @param groudId Q群号 10 | * @param message 发送信息 11 | */ 12 | async sendGroupMessage(groudId: number, message: string): Promise { 13 | const res = await request({ 14 | url: `${this.url}/${Endpoints.SendGroupMsg}`, 15 | method: HttpMethod.GET, 16 | data: { 17 | group_id: groudId, 18 | message, 19 | }, 20 | accessToken: this.accessToken, 21 | }); 22 | 23 | return { 24 | ...res.body, 25 | error: res.error, 26 | } as RestMessageResponse; 27 | } 28 | 29 | /** 30 | * 向qq好友发送消息 31 | * @param userId 好友qq号 32 | * @param message 发送信息 33 | */ 34 | async sendPrivateMessage(userId: number, message: string): Promise { 35 | const res = await request({ 36 | url: `${this.url}/${Endpoints.SendPrivateMsg}`, 37 | method: HttpMethod.GET, 38 | data: { 39 | user_id: userId, 40 | message, 41 | }, 42 | accessToken: this.accessToken, 43 | }); 44 | 45 | return { 46 | ...res.body, 47 | error: res.error, 48 | } as RestMessageResponse; 49 | } 50 | 51 | /** 52 | * 获取qq群列表 53 | */ 54 | async getGroupList(): Promise { 55 | const res = await request({ 56 | url: `${this.url}/${Endpoints.GetGroupList}`, 57 | method: HttpMethod.GET, 58 | data: {}, 59 | accessToken: this.accessToken, 60 | }); 61 | 62 | return { 63 | ...res.body, 64 | error: res.error, 65 | } as RestGroupListResponse; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/rest/types/endpoints.ts: -------------------------------------------------------------------------------- 1 | export enum Endpoints { 2 | /** 获取群列表 */ 3 | GetGroupList = 'get_group_list', 4 | /** 发送群消息 */ 5 | SendGroupMsg = 'send_group_msg', 6 | /** 发送私聊消息 */ 7 | SendPrivateMsg = 'send_private_msg', 8 | } 9 | -------------------------------------------------------------------------------- /src/rest/types/http.ts: -------------------------------------------------------------------------------- 1 | export enum HttpMethod { 2 | GET = 'GET', 3 | POST = 'POST', 4 | PUT = 'PUT', 5 | DELETE = 'DELETE', 6 | } 7 | -------------------------------------------------------------------------------- /src/rest/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './endpoints'; 2 | export * from './http'; 3 | export * from './response'; 4 | -------------------------------------------------------------------------------- /src/rest/types/response.ts: -------------------------------------------------------------------------------- 1 | export interface ErrorResponse { 2 | error?: Error; 3 | } 4 | 5 | export interface RestResponse extends ErrorResponse { 6 | body: { [attr: string]: any }; 7 | } 8 | 9 | export interface RestCQResponse extends ErrorResponse { 10 | retcode: number; 11 | status: CqStatus; 12 | } 13 | 14 | export type CqStatus = 'ok' | 'async' | 'failed'; 15 | 16 | export interface RestMessageResponse extends RestCQResponse { 17 | data: { 18 | message_id: number; 19 | }; 20 | } 21 | 22 | export interface CqGroupInfo { 23 | group_id: number; 24 | group_name: string; 25 | } 26 | 27 | export interface RestGroupListResponse extends RestCQResponse { 28 | data: CqGroupInfo[]; 29 | } 30 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es5", 5 | "rootDir": "./src", 6 | "watch": false, 7 | "declaration": true, 8 | "sourceMap": false, 9 | "downlevelIteration": true 10 | }, 11 | "exclude": [ 12 | "dist", 13 | "node_modules", 14 | "**/*.spec.ts" 15 | ] 16 | } 17 | 18 | -------------------------------------------------------------------------------- /tsconfig.dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "watch": true, 5 | "declaration": false, 6 | "sourceMap": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2018", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "strict": true, 7 | "types": ["node", "jest"], 8 | "typeRoots": ["./node_modules/@types"], 9 | "rootDir": "./", 10 | "outDir": "dist", 11 | "declaration": true, 12 | "experimentalDecorators": true, 13 | "emitDecoratorMetadata": true, 14 | "skipLibCheck": true, 15 | "resolveJsonModule": true, 16 | "baseUrl": "./", 17 | "sourceMap": true 18 | }, 19 | "include": [ 20 | "src/**/*.ts" 21 | ], 22 | "exclude": [ 23 | "dist", 24 | "node_modules", 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": {}, 4 | "include": [ 5 | "src/**/*.spec.ts", 6 | "src/**/*.d.ts" 7 | ], 8 | "exclude": [ 9 | "dist", 10 | "node_modules" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint-eslint-rules" 4 | ], 5 | "rulesDirectory": [ 6 | "node_modules/vrsource-tslint-rules/rules" 7 | ], 8 | "rules": { 9 | "adjacent-overload-signatures": true, 10 | "array-type": [true, "array"], 11 | "arrow-return-shorthand": true, 12 | "await-promise": true, 13 | "ban": [ 14 | true, 15 | "eval", 16 | {"name": "$", "message": "don't use"}, 17 | {"name": ["fdescribe"], "message": "don't focus tests"}, 18 | {"name": ["fit"], "message": "don't focus tests"}, 19 | {"name": ["describe", "only"], "message": "don't focus tests"}, 20 | {"name": ["it", "only"], "message": "don't focus tests"} 21 | ], 22 | "ban-comma-operator": true, 23 | "ban-types": [true, ["Object", "Use {} instead."], ["Array", "Use [] instead."]], 24 | "block-spacing": [ 25 | true, 26 | "always" 27 | ], 28 | "callable-types": true, 29 | "class-name": true, 30 | "comment-format": [true, "check-space"], 31 | "cyclomatic-complexity": true, 32 | "deprecation": true, 33 | "eofline": true, 34 | "file-name-casing": [true, "kebab-case"], 35 | "forin": true, 36 | "import-blacklist": [ 37 | true 38 | ], 39 | "interface-name": [true, "never-prefix"], 40 | "interface-over-type-literal": true, 41 | "label-position": true, 42 | "match-default-export-name": true, 43 | "member-access": [true, "no-public"], 44 | "member-ordering": [ 45 | true, 46 | { 47 | "order": [ 48 | "public-static-field", 49 | "protected-static-field", 50 | "private-static-field", 51 | "public-static-method", 52 | "protected-static-method", 53 | "private-static-method", 54 | "public-instance-field", 55 | "protected-instance-field", 56 | "private-instance-field", 57 | "public-constructor", 58 | "protected-constructor", 59 | "private-constructor", 60 | "public-instance-method", 61 | "protected-instance-method", 62 | "private-instance-method" 63 | ] 64 | } 65 | ], 66 | "newline-before-return": true, 67 | "no-arg": true, 68 | "no-bitwise": true, 69 | "no-boolean-literal-compare": true, 70 | "no-console": [ 71 | true, 72 | "debug", 73 | "info", 74 | "time", 75 | "timeEnd", 76 | "trace" 77 | ], 78 | "no-conditional-assignment": true, 79 | "no-consecutive-blank-lines": true, 80 | "no-construct": true, 81 | "no-debugger": true, 82 | "no-default-export": true, 83 | "no-duplicate-imports": true, 84 | "no-duplicate-super": true, 85 | "no-duplicate-switch-case": true, 86 | "no-duplicate-variable": true, 87 | "no-dynamic-delete": true, 88 | "no-empty": false, 89 | "no-empty-interface": true, 90 | "no-eval": true, 91 | "no-extra-semi": true, 92 | "no-floating-promises": true, 93 | "no-for-in-array": true, 94 | "no-import-side-effect": true, 95 | "no-inferrable-types": [ 96 | true, 97 | "ignore-params" 98 | ], 99 | "no-inferred-empty-object-type": true, 100 | "no-inner-declarations": true, 101 | "no-internal-module": true, 102 | "no-invalid-regexp": true, 103 | "no-invalid-template-strings": true, 104 | "no-invalid-this": true, 105 | "no-irregular-whitespace": true, 106 | "no-magic-numbers": false, 107 | "no-mergeable-namespace": true, 108 | "no-misused-new": true, 109 | "no-multi-spaces": true, 110 | "no-namespace": true, 111 | "no-parameter-properties": false, 112 | "no-parameter-reassignment": true, 113 | "no-reference": true, 114 | "no-regex-spaces": true, 115 | "no-return-await": true, 116 | "no-shadowed-variable": true, 117 | "no-sparse-arrays": true, 118 | "no-string-literal": false, 119 | "no-string-throw": true, 120 | "no-submodule-imports": [ 121 | true, 122 | "@dripjs", 123 | "@nestjs", 124 | "rxjs" 125 | ], 126 | "no-switch-case-fall-through": true, 127 | "no-this-assignment": true, 128 | "no-trailing-whitespace": true, 129 | "no-unbound-method": false, 130 | "no-unnecessary-callback-wrapper": true, 131 | "no-unnecessary-class": false, 132 | "no-unnecessary-initializer": true, 133 | "no-unnecessary-type-assertion": true, 134 | "no-unnecessary-qualifier": true, 135 | "no-unsafe-any": false, 136 | "no-unsafe-finally": true, 137 | "no-unused-expression": true, 138 | "no-use-before-declare": true, 139 | "no-var-keyword": true, 140 | "no-var-requires": true, 141 | "number-literal-format": true, 142 | "object-literal-shorthand": true, 143 | "object-literal-sort-keys": false, 144 | "one-variable-per-declaration": true, 145 | "only-arrow-functions": [true, "allow-declarations", "allow-named-functions"], 146 | "prefer-case-blocks": true, 147 | "prefer-conditional-expression": true, 148 | "prefer-const": true, 149 | "prefer-function-over-method": [true, "allow-public"], 150 | "prefer-literal": [ 151 | true, 152 | "object", 153 | "function", 154 | "array" 155 | ], 156 | "prefer-method-signature": false, 157 | "prefer-object-spread": true, 158 | "prefer-readonly": true, 159 | "prefer-switch": [true, {"min-cases": 4}], 160 | "prefer-template": true, 161 | "prefer-while": true, 162 | 163 | "promise-function-async": true, 164 | "radix": true, 165 | "restrict-plus-operands": true, 166 | "return-undefined": true, 167 | "space-in-parens": [true, "never"], 168 | "switch-default": true, 169 | "switch-final-break": true, 170 | "trailing-comma": [ 171 | true, 172 | { 173 | "multiline": "always", 174 | "singleline": "never" 175 | } 176 | ], 177 | "triple-equals": [ 178 | true, 179 | "allow-null-check" 180 | ], 181 | "type-literal-delimiter": true, 182 | "typedef": [true, "call-signature", "parameter"], 183 | "unified-signatures": true, 184 | "use-default-type-parameter": true, 185 | "use-isnan": true, 186 | "valid-typeof": true, 187 | "variable-name": [ 188 | true, 189 | "ban-keywords", 190 | "check-format", 191 | "allow-leading-underscore" 192 | ], 193 | "ext-variable-name": [ 194 | true, 195 | ["class", "pascal"], 196 | ["interface", "pascal"], 197 | ["parameter", "camel", "allow-leading-underscore"], 198 | ["property", "static", "camel"], 199 | ["property", "private", "camel", "allow-leading-underscore"], 200 | ["property", "protected", "camel", "allow-leading-underscore"], 201 | ["variable", "local", "camel", "allow-leading-underscore"], 202 | ["method", "private", "camel", "allow-leading-underscore"], 203 | ["method", "protected", "camel", "allow-leading-underscore"], 204 | ["function", "camel"] 205 | ] 206 | } 207 | } 208 | --------------------------------------------------------------------------------