+7
-5
@@ -10,3 +10,3 @@ /// <reference types="node" /> | ||
| import { Member } from "./member"; | ||
| import { Forwardable, Quotable, Sendable } from "./message"; | ||
| import { Forwardable, Quotable, Sendable, ImageElem } from "./message"; | ||
| /** 事件接口 */ | ||
@@ -22,2 +22,4 @@ export interface Client extends BaseClient { | ||
| prependOnceListener(event: string | symbol, listener: (this: this, ...args: any[]) => void): this; | ||
| off<T extends keyof EventMap>(event: T, listener: EventMap<this>[T]): this; | ||
| off<S extends string | symbol>(event: S & Exclude<S, keyof EventMap>, listener: (this: this, ...args: any[]) => void): this; | ||
| } | ||
@@ -119,3 +121,3 @@ /** 一个客户端 */ | ||
| /** 设置头像 */ | ||
| setAvatar(file: string | Buffer | import("stream").Readable): Promise<void>; | ||
| setAvatar(file: ImageElem["file"]): Promise<void>; | ||
| /** 获取漫游表情 */ | ||
@@ -161,6 +163,6 @@ getRoamingStamp(no_cache?: boolean): Promise<string[]>; | ||
| getStrangerInfo(user_id: number): Promise<{ | ||
| user_id: number; /** 账号本地数据存储目录 */ | ||
| user_id: number; | ||
| nickname: string; | ||
| sex: Gender; | ||
| age: number; | ||
| age: number; /** 日志记录器,初始情况下是`log4js.Logger` */ | ||
| area: string; | ||
@@ -273,3 +275,3 @@ }>; | ||
| /** | ||
| * 触发system.offline.network事件后的重新登录间隔秒数,默认8(秒),不建议设置过低 | ||
| * 触发system.offline.network事件后的重新登录间隔秒数,默认5(秒),不建议设置过低 | ||
| * 设置为0则不会自动重连,然后你可以监听此事件自己处理 | ||
@@ -276,0 +278,0 @@ */ |
+1
-1
@@ -45,3 +45,3 @@ "use strict"; | ||
| cache_group_member: true, | ||
| reconn_interval: 8, | ||
| reconn_interval: 5, | ||
| data_dir: path.join(require?.main?.path || process.cwd(), "data"), | ||
@@ -48,0 +48,0 @@ ...conf, |
@@ -341,6 +341,3 @@ "use strict"; | ||
| } | ||
| }).catch((err) => { | ||
| this.emit("internal.verbose", err.message, VerboseLevel.Error); | ||
| this.emit("internal.error.network", -2, "server is busy"); | ||
| }); | ||
| }).catch(() => this.emit("internal.error.network", -2, "server is busy")); | ||
| } | ||
@@ -658,3 +655,3 @@ /** 扫码后调用此方法登录 */ | ||
| } | ||
| async function register(logout = false) { | ||
| async function register(logout = false, reflush = false) { | ||
| this[IS_ONLINE] = false; | ||
@@ -683,3 +680,3 @@ clearInterval(this[HEARTBEAT]); | ||
| try { | ||
| const payload = await this[FN_SEND](pkt); | ||
| const payload = await this[FN_SEND](pkt, 10); | ||
| if (logout) | ||
@@ -689,3 +686,3 @@ return; | ||
| const result = rsp[9] ? true : false; | ||
| if (!result) { | ||
| if (!result && !reflush) { | ||
| this.emit("internal.error.token"); | ||
@@ -758,3 +755,3 @@ } | ||
| const { token } = decodeT119.call(this, t[0x119]); | ||
| await register.call(this); | ||
| await register.call(this, false, true); | ||
| if (this[IS_ONLINE]) | ||
@@ -934,3 +931,3 @@ this.emit("internal.token", token); | ||
| if (type === 160) { | ||
| if (!t[0x204]) | ||
| if (!t[0x204] && !t[0x174]) | ||
| return this.emit("internal.verbose", "已向密保手机发送短信验证码", VerboseLevel.Mark); | ||
@@ -937,0 +934,0 @@ let phone = ""; |
@@ -122,3 +122,3 @@ "use strict"; | ||
| body = tea.encrypt(body, key); | ||
| const { data } = await axios_1.default.post("https://configsvr.msf.3g.qq.com/configsvr/serverlist.jsp", body, { timeout: 10000, responseType: "arraybuffer" }); | ||
| const { data } = await axios_1.default.post("https://configsvr.msf.3g.qq.com/configsvr/serverlist.jsp?mType=getssolist", body, { timeout: 10000, responseType: "arraybuffer" }); | ||
| let buf = Buffer.from(data); | ||
@@ -125,0 +125,0 @@ buf = tea.decrypt(buf, key).slice(4); |
+2
-3
@@ -1,4 +0,3 @@ | ||
| /// <reference types="node" /> | ||
| import { Contactable } from "./internal"; | ||
| import { Sendable, GroupMessage, MusicPlatform, Anonymous, Quotable } from "./message"; | ||
| import { Sendable, GroupMessage, ImageElem, MusicPlatform, Anonymous, Quotable } from "./message"; | ||
| import { Gfs } from "./gfs"; | ||
@@ -86,3 +85,3 @@ import { MessageRet } from "./events"; | ||
| /** 设置群头像 */ | ||
| setAvatar(file: string | Buffer | import("stream").Readable): Promise<void>; | ||
| setAvatar(file: ImageElem["file"]): Promise<void>; | ||
| /** 邀请好友入群 */ | ||
@@ -89,0 +88,0 @@ invite(uid: number): Promise<boolean>; |
@@ -324,2 +324,3 @@ "use strict"; | ||
| const rsp = core_1.pb.decode(payload)[5]; | ||
| rsp[2] && (0, errors_1.drop)(rsp[2], rsp[3]); | ||
| const ip = rsp[5]?.[0] || rsp[5], port = rsp[6]?.[0] || rsp[6]; | ||
@@ -326,0 +327,0 @@ const ukey = rsp[7].toHex(), filekey = rsp[11].toHex(); |
@@ -153,3 +153,4 @@ "use strict"; | ||
| function verifyListener(url, phone) { | ||
| this.logger.mark("登录保护二维码验证地址:" + url.replace("verify", "qrcode")); | ||
| this.logger.mark("收到登录保护,只需验证一次便长期有效,可以访问URL验证或发短信验证。访问URL完成验证后调用login()可直接登录。发短信验证需要调用sendSmsCode()和submitSmsCode()方法。"); | ||
| this.logger.mark("登录保护验证URL:" + url.replace("verify", "qrcode")); | ||
| this.logger.mark("密保手机号:" + phone); | ||
@@ -156,0 +157,0 @@ return this.em("system.login.device", { url, phone }); |
@@ -40,3 +40,7 @@ /// <reference types="node" /> | ||
| type: "image"; | ||
| /** 为string时,支持 "http(s)://" "base:64//" 本地文件和收到的file */ | ||
| /** | ||
| * @type {string} filepath such as "/tmp/1.jpg" | ||
| * @type {Buffer} image buffer | ||
| * @type {Readable} a readable stream of image | ||
| */ | ||
| file: string | Buffer | import("stream").Readable; | ||
@@ -62,3 +66,7 @@ /** 网络图片是否使用缓存 */ | ||
| type: "record"; | ||
| /** 为string时,支持 "http(s)://" "base:64//" 本地文件和收到的file */ | ||
| /** | ||
| * support for raw silk and amr file | ||
| * @type {string} filepath such as "/tmp/1.slk" | ||
| * @type {Buffer} ptt buffer (silk or amr) | ||
| */ | ||
| file: string | Buffer; | ||
@@ -73,3 +81,6 @@ url?: string; | ||
| type: "video"; | ||
| /** 仅支持本地文件与收到的file */ | ||
| /** | ||
| * need ffmpeg and ffprobe | ||
| * @type {string} filepath such as "/tmp/1.mp4" | ||
| */ | ||
| file: string; | ||
@@ -76,0 +87,0 @@ name?: string; |
@@ -352,3 +352,3 @@ "use strict"; | ||
| const tmp = { ...elem }; | ||
| tmp.type = undefined; | ||
| delete tmp.type; | ||
| const str = qs.stringify(tmp, ",", "=", { encodeURIComponent: (s) => s.replace(/&|,|\[|\]/g, escapeCQInside) }); | ||
@@ -355,0 +355,0 @@ cqcode += "[CQ:" + elem.type + (str ? "," : "") + str + "]"; |
+2
-2
| { | ||
| "name": "oicq", | ||
| "version": "2.2.2", | ||
| "upday": "2021/4/9", | ||
| "version": "2.2.3", | ||
| "upday": "2021/5/17", | ||
| "description": "QQ protocol!", | ||
@@ -6,0 +6,0 @@ "main": "lib/index.js", |
+21
-19
@@ -10,4 +10,5 @@ # oicq | ||
| * 若你不熟悉Node.js或不会组织代码,可通过 [template](https://github.com/takayama-lily/oicq-template) 创建一个简单的应用程序 | ||
| * [API Reference](#api-reference) / [Type Docs](https://takayama-lily.github.io/oicq/) (文档仅供参考,具体类型以包内d.ts声明文件为准) | ||
| * [API Reference](#api-reference) / [Type Docs](https://oicqjs.github.io/oicq/) (文档仅供参考,具体类型以包内d.ts声明文件为准) | ||
| * [从v1.x升级](https://github.com/takayama-lily/oicq/projects/3#column-16638290) (v1在master分支) | ||
| * QQ频道未来不会直接支持,请使用插件 [oicq-guild](https://github.com/takayama-lily/oicq-guild) | ||
@@ -43,3 +44,4 @@ ---- | ||
| 注意:第一次运行程序时,有可能扫描命令行中的二维码和图片中的二维码都会显示过期,只需要重新运行一次程序即可,后面不会出现这个问题。 | ||
| 注意:扫码登录现在仅能在同一ip下进行,建议使用密码登录,只需验证一次设备便长期有效 | ||
| [密码登录教程](https://github.com/takayama-lily/oicq/wiki/01.%E4%BD%BF%E7%94%A8%E5%AF%86%E7%A0%81%E7%99%BB%E5%BD%95-(%E6%BB%91%E5%8A%A8%E9%AA%8C%E8%AF%81%E7%A0%81%E6%95%99%E7%A8%8B)) | ||
@@ -49,2 +51,3 @@ ## Api Reference | ||
| * [Class: Client](#class-client) 客户端 | ||
| * [Events](#events) 事件 | ||
| * [Class: Group](#class-group) 群 | ||
@@ -57,4 +60,3 @@ * [Class: User](#class-user) 用户 | ||
| * [Class: Message](#class-message) 消息 | ||
| * [Namespace: segment](#namespace-segment) 构造消息元素 | ||
| * [使用密码登录](#使用密码登录) | ||
| * [Namespace: segment](#namespace-segment) 构造消息元素/发送消息 | ||
@@ -122,2 +124,4 @@ ### Class: Client | ||
| ### Events | ||
| | Event | Description | | ||
@@ -355,4 +359,14 @@ | ---------------------- | ----------- | | ||
| > 用于创建可发送的消息元素类型 | ||
| > `const { segment } = require("oicq")` | ||
| ```js | ||
| //样例代码,文字+图片+表情+AT | ||
| const { segment } = require("oicq") | ||
| const message = [ | ||
| "hello world", | ||
| segment.image("/tmp/abc.jpg"), | ||
| segment.face(104), | ||
| segment.at(10001), | ||
| ] | ||
| ``` | ||
| | Method | Description | | ||
@@ -375,15 +389,2 @@ | ---------- | ----------- | | ||
| ### 使用密码登录 | ||
| 首次登录推荐使用扫码,但是可能会出现掉线后需要重新扫码的情况。 | ||
| 登录一段时间后,不会再弹出滑动验证码,此时建议改用密码登录,更加稳定。 | ||
| ```js | ||
| const { createClient } = require("oicq") | ||
| const client = createClient(147258369) | ||
| //若弹出登录保护地址,去验证通过即可 | ||
| client.login("password") | ||
| ``` | ||
| ---- | ||
@@ -395,4 +396,5 @@ | ||
| * [码云镜像仓库](https://gitee.com/takayama/oicq) | ||
| * [赞助记录](./sponsors.md) 想赞助可加群给我发红包 | ||
| * [赞助记录](./sponsors.md) | ||
| * [TXHook](https://github.com/fuqiuluo/TXHook) 抓包工具推荐 | ||
| [](https://qm.qq.com/cgi-bin/qm/qr?k=NXw3NEA5lzPjkRhyEpjVBqMpdg1WHRKJ&jump_from=webapi) |
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
539784
0.12%13523
0.08%393
0.51%