├── .gitignore
├── .npmrc
├── package.json
├── README.md
├── Model
├── parser.js
└── device.js
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | @icqqjs:registry=https://npm.pkg.github.com
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ICQQ-Plugin",
3 | "type": "module",
4 | "author": "TimeRainStarSky",
5 | "dependencies": {
6 | "icqq": "*"
7 | }
8 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # TRSS-Yunzai ICQQ Plugin
4 |
5 | TRSS-Yunzai ICQQ Bot 适配器 插件
6 |
7 | [](https://github.com/TimeRainStarSky/Yunzai-ICQQ-Plugin)
8 | [](../../stargazers)
9 | [](../../archive/main.tar.gz)
10 | [](../../releases/latest)
11 |
12 | [](https://github.com/TimeRainStarSky/Yunzai-ICQQ-Plugin)
13 |
14 |
15 |
16 | ## 安装教程
17 |
18 | 1. 准备:[TRSS-Yunzai](../../../Yunzai)
19 | 2. 输入:`#安装ICQQ-Plugin`
20 | 3. 输入:`#QQ签名[签名服务器地址]`
21 | 4. 输入:`#QQ设置QQ号:密码:登录设备`
22 |
23 | ## 安装 ICQQ
24 |
25 | ```sh
26 | cd plugins/ICQQ-Plugin
27 |
28 | pnpm login --scope=@icqqjs --auth-type=legacy --registry=https://npm.pkg.github.com
29 |
30 | UserName: # 你的 GitHub 账号
31 | Password: # 前往 https://github.com/settings/tokens/new 获取,scopes 勾选 read:packages
32 | E-Mail: # 你的公开邮箱地址
33 |
34 | pnpm add icqq@npm:@icqqjs/icqq
35 | ```
36 |
37 | ## 格式示例
38 |
39 | - 密码登录:QQ号 `114514` 密码 `1919810` 登录设备 `安卓手机(1)/平板(2)`
40 |
41 | ```
42 | #QQ设置114514:1919810:2
43 | ```
44 |
45 | - 扫码登录:QQ号 `114514` 登录设备 `安卓手表(3)`
46 |
47 | ```
48 | #QQ设置114514::3
49 | ```
50 |
51 | ## 使用教程
52 |
53 | - #QQ账号
54 | - #QQ设置 + `QQ号:密码(留空扫码):登录设备:版本号:独立签名地址`
55 | - #QQ签名 + `签名服务器地址`
--------------------------------------------------------------------------------
/Model/parser.js:
--------------------------------------------------------------------------------
1 | import zlib from"zlib";function parse(e,t){return new Parser(e,t)}class Parser{constructor(e,t){this.uin=t,this.message=[],this.brief="",this.content="",this.atme=!1,this.atall=!1,this.newImg=!1,this.imgprefix={},this.exclusive=!1;try{Array.isArray(e)?this.parseElems(e):(e[4]&&e[4].length&&this.parseExclusiveElem(0,e[4]),this.parseElems(Array.isArray(e[2])?e[2]:[e[2]]))}catch(e){console.error(e)}}getNextText(){try{var e=this.it?.next().value[1][1];return String(e[1])}catch{return"[未知]"}}parseExclusiveElem(e,t){let i,s;switch(e){case 12:case 51:var r=t[1].toBuffer();i={type:12===e?"xml":"json",data:String(0{var t,i=[];for(t of e=Array.isArray(e[1])?e[1]:[e[1]]){var s={id:"",render_data:{},action:{permission:{}}};t[1]&&(s.id=t[1]?.toString()),t[2]&&(s.render_data.label=t[2][1]?.toString(),s.render_data.visited_label=t[2][2]?.toString(),s.render_data.style=Number(t[2][3])||0),t[3]&&(s.action.type=Number(t[3][1])||0,s.action.unsupport_tips=t[3][4]?.toString(),s.action.data=t[3][5]?.toString(),s.action.reply=1===t[3][7],s.action.enter=1===t[3][8],t[3][2])&&(s.action.permission.type=Number(t[3][2][1])||0,s.action.permission.specify_role_ids=t[3][2][2]||[],s.action.permission.specify_user_ids=t[3][2][3]||[]),i.push(s)}return{buttons:i}})}},s="[button消息]",r=s}catch{return}break;case 48:switch(t[3]){case 10:case 20:if(!(i=this.parseNewImgElem(t[2],"image")))return;s=(i.asface?"[动画表情]":"[图片]")+(i.summary||""),r=`{image:${i.md5.toUpperCase()}}`;break;case 11:case 21:{let e=t[2][1];var n=(e=Array.isArray(e)?e:[e]).find(e=>100!==e[1][6]);i={type:"video",file:"protobuf://"+t.toBase64(),fid:n[1][2]?.toString(),md5:"ntvideo_"+n[1][1][2]?.toString(),size:n[1][1][1],seconds:n[1][1][8],nt:!0},s="视频",r=`{video:${i.fid}}`;break}case 12:case 22:n=t[2][1][1];i={type:"record",file:"protobuf://"+t.toBase64(),url:"",fid:n[2]?.toString(),md5:n[1][2]?.toString(),size:n[1][1],seconds:n[1][8],nt:!0},s="语音",r=`{ptt:${i.file}}`;break;default:return}break;default:return}2===this.message.length&&"at"===i.type&&"at"===this.message[0]?.type&&"text"===this.message[1]?.type&&this.message[0].qq===i.qq&&" "===this.message[1].text&&(this.message.splice(0,2),this.brief=""),this.brief+=s,this.content+=r,Array.isArray(this.message)||(this.message=[]);var l=this.message[this.message.length-1];"text"===i.type&&"text"===l?.type?l.text+=i.text:this.message.push(i)}parseElems(e){for(this.it=e.entries();;)try{var t=this.it.next().value?.[1];if(!t)break;var i=Number(Object.keys(Reflect.getPrototypeOf(t))[0]),s=t[i];if(16===i)this.extra=s;else if(21===i)this.anon=s;else if(45===i)this.quotation=s;else if(!this.exclusive)switch(i){case 1:case 2:case 4:case 6:case 8:case 31:case 34:case 37:this.parsePartialElem(i,s);break;case 5:case 12:case 19:case 51:this.parseExclusiveElem(i,s);break;case 53:3===s[1]?this.parseExclusiveElem(3,s[2][1]||s[2][2]):33===s[1]?this.parsePartialElem(33,s[2]):2===s[1]?this.parseExclusiveElem(126,s):37===s[1]?this.parseExclusiveElem(37,s):20===s[1]?this.parseExclusiveElem(51,s[2]):[45,46,48,500].includes(s[1])&&this.parsePartialElem(s[1],s)}}catch(e){console.error(e)}}parseNewImgElem(e,t){try{var i={type:t,file:e[1][1][1][4]?.toString(),url:"",fid:e[1][1][2]?.toString(),md5:e[1][1][1][2]?.toString(),height:e[1][1][1][7],width:e[1][1][1][6],size:e[1][1][1][1],summary:e[2][1]?.[2]?.toString(),nt:!0},s=("image"===t&&(i.asface=1===e[2][1]?.[1]),i.file=(0,this.image.buildImageFileParam)(i.md5,i.size,i.width,i.height,e[1][1][1][5][2]),((e[2][1]?.[11]||e[2][1]?.[12])?.[30]||"").toString());if(s?.length)return this.newImg=!0,i.url="https://"+e[1][2][3]+(s.startsWith("/")?s:""+e[1][2][1]+s)+(e[1][2][2][1]||"&spec=0"),i;i.md5&&(i.url="https://"+e[1][2][3]+e[1][2][1],this.imgprefix[i.md5]=i)}catch{if("flash"===t)return this.parseImgElem(0,e,t)}}parseImgElem(e,t,i){let s;var r,e="flash"===i?!!t[1]:8!==e,a=t[e?7:13].toHex(),c=(t[e?29:34]?.[30]||"").toString();return this.imgprefix[a]&&c?.length?(r=this.imgprefix[a].url?.length?new URL(this.imgprefix[a].url).origin:"",s={...this.imgprefix[a],type:i,url:`${c.startsWith("/")?""+r+c:""+this.imgprefix[a].url+c}&spec=0`}):((s={type:i,file:"",url:"",md5:a,height:t[e?8:23],width:t[e?9:22],size:t[e?2:25],summary:t[e?29:34]?.[e?8:9]?.toString()}).file=(0,this.image.buildImageFileParam)(s.md5,s.size,s.width,s.height,t[e?5:20]),"image"===i&&(s.asface=1===t[e?29:34]?.[1]),s.url||(c&&c.includes("fileid")?s.url=`https://c2cpicdw.qpic.cn${c}&spec=0`:t[16]&&String(t[16]).startsWith("/")?s.url="https://gchat.qpic.cn"+t[16]:t[15]&&String(t[15]).startsWith("/")?s.url="https://c2cpicdw.qpic.cn"+t[15]:s.url=`https://gchat.qpic.cn/gchatpic_new/0/0-0-${a.toUpperCase()}/0`),s)}}export{parse,Parser};
--------------------------------------------------------------------------------
/Model/device.js:
--------------------------------------------------------------------------------
1 | import fs from "fs";import path from"path";let mobile=[{name:"A9.2.27.636ed9e0",version:"9.2.27.31300",ver:"9.2.27",subid:537323303,apad_subid:537323342,qua:"V1_AND_SQ_9.2.27_12160_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2589",buildtime:1757058014,ssover:22,fekit_ver:"8.500.910"},{name:"A9.2.25.593ac7a8",version:"9.2.25.30450",ver:"9.2.25",subid:537318125,apad_subid:537318164,qua:"V1_AND_SQ_9.2.25_11820_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2589",buildtime:1757058014,ssover:22,fekit_ver:"8.500.910"},{name:"A9.2.20.777b5929",version:"9.2.20.30025",ver:"9.2.20",subid:537315786,apad_subid:537315825,qua:"V1_AND_SQ_9.2.20_11650_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2589",buildtime:1757058014,ssover:22,fekit_ver:"8.409.903"},{name:"A9.2.15.012a1717",version:"9.2.15.29600",ver:"9.2.15",subid:537312176,apad_subid:537312215,qua:"V1_AND_SQ_9.2.15_11480_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2588",buildtime:1755676630,ssover:22,fekit_ver:"8.408.897"},{name:"A9.2.10.fad8a0d9",version:"9.2.10.29175",ver:"9.2.10",subid:537309838,apad_subid:537309877,qua:"V1_AND_SQ_9.2.10_11310_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2587",buildtime:1754919788,ssover:22,fekit_ver:"8.407.888"},{name:"A9.2.5.2c3ad708",version:"9.2.5.28755",ver:"9.2.5",subid:537306612,apad_subid:537306651,qua:"V1_AND_SQ_9.2.5_11142_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2585",buildtime:1752744019,ssover:22,fekit_ver:"8.406.883"},{name:"A9.2.5.6039dd6b",version:"9.2.5.28750",ver:"9.2.5",subid:537306534,apad_subid:537306573,qua:"V1_AND_SQ_9.2.5_11140_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2585",buildtime:1752744019,ssover:22,fekit_ver:"8.406.883"},{name:"A9.2.0.0a244d9a",version:"9.2.0.28325",ver:"9.2.0",subid:537303052,apad_subid:537303091,qua:"V1_AND_SQ_9.2.0_10970_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2584",buildtime:1751448568,ssover:22,fekit_ver:"8.405.873"},{name:"A9.1.97.b351e214",version:"9.1.97.27900",ver:"9.1.97",subid:537301750,apad_subid:537301789,qua:"V1_AND_SQ_9.1.97_10800_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2582",buildtime:1748422598,ssover:22,fekit_ver:"8.404.864"},{name:"A9.1.95.1eed49c0",version:"9.1.95.27050",ver:"9.1.95",subid:537297272,apad_subid:537297311,qua:"V1_AND_SQ_9.1.95_10460_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2582",buildtime:1748422598,ssover:22,fekit_ver:"8.404.864"},{name:"A9.1.92.cb84b334",version:"9.1.92.26650",ver:"9.1.92",subid:537294996,apad_subid:537295035,qua:"V1_AND_SQ_9.1.92_10300_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2581",buildtime:1747820974,ssover:22,fekit_ver:"8.403.855"},{name:"A9.1.91.304e0cba",version:"9.1.91.26645",ver:"9.1.91",subid:537294918,apad_subid:537294957,qua:"V1_AND_SQ_9.1.91_10298_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2581",buildtime:1747820974,ssover:22,fekit_ver:"8.403.855"},{name:"A9.1.90.58326526",version:"9.1.90.26625",ver:"9.1.90",subid:537294606,apad_subid:537294645,qua:"V1_AND_SQ_9.1.90_10290_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2581",buildtime:1747820974,ssover:22,fekit_ver:"8.403.855"},{name:"A9.1.76.a36f04fb",version:"9.1.76.26090",ver:"9.1.76",subid:537288619,apad_subid:537288658,qua:"V1_AND_SQ_9.1.76_10076_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2578",buildtime:1746016194,ssover:22,fekit_ver:"8.402.848"},{name:"A9.1.75.ec478a78",version:"9.1.75.26070",ver:"9.1.75",subid:537288307,apad_subid:537288346,qua:"V1_AND_SQ_9.1.75_10068_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2578",buildtime:1746016194,ssover:22,fekit_ver:"8.402.840"},{name:"A9.1.71.7bacc589",version:"9.1.71.25665",ver:"9.1.71",subid:537286259,apad_subid:537286298,qua:"V1_AND_SQ_9.1.71_9906_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2574",buildtime:1745224715,ssover:22,fekit_ver:"8.401.830"},{name:"A9.1.70.88c475c0",version:"9.1.70.25645",ver:"9.1.70",subid:537285947,apad_subid:537285986,qua:"V1_AND_SQ_9.1.70_9898_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2574",buildtime:1745224715,ssover:22,fekit_ver:"8.401.830"},{name:"A9.1.67.06b27928",version:"9.1.67.25220",ver:"9.1.67",subid:537284101,apad_subid:537284140,qua:"V1_AND_SQ_9.1.67_9728_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2570",buildtime:1742975242,ssover:22,fekit_ver:"8.400.814"},{name:"A9.1.65.5017700a",version:"9.1.65.24795",ver:"9.1.65",subid:537278302,apad_subid:537278341,qua:"V1_AND_SQ_9.1.65_9558_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2570",buildtime:1742975242,bitmap:150470524,ssover:22,fekit_ver:"8.400.814"},{name:"A9.1.60.045f5d19",version:"9.1.60.24370",ver:"9.1.60",subid:537275636,apad_subid:537275675,qua:"V1_AND_SQ_9.1.60_9388_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2568",buildtime:1740483688,bitmap:150470524,ssover:22,fekit_ver:"8.400.807"},{name:"A9.1.55.464b50b2",version:"9.1.55.23945",ver:"9.1.55",subid:537272835,apad_subid:537272874,qua:"V1_AND_SQ_9.1.55_9218_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2568",buildtime:1740483688,bitmap:150470524,ssover:22,fekit_ver:"8.309.798"},{name:"A9.1.52.b97ab15e",version:"9.1.52.23535",ver:"9.1.52",subid:537270265,apad_subid:537270304,qua:"V1_AND_SQ_9.1.52_9054_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2566",buildtime:1737457591,bitmap:150470524,ssover:22,fekit_ver:"8.308.786"},{name:"A9.1.50.83cc325e",version:"9.1.50.23520",ver:"9.1.50",subid:537270031,apad_subid:537270070,qua:"V1_AND_SQ_9.1.50_9048_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2566",buildtime:1737457591,bitmap:150470524,ssover:22,fekit_ver:"8.308.786"},{name:"A9.1.35.9f1a1697",version:"9.1.35.22670",ver:"9.1.35",subid:537265576,apad_subid:537265615,qua:"V1_AND_SQ_9.1.35_8708_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2565",buildtime:1728390173,bitmap:150470524,ssover:22,fekit_ver:"8.307.779"},{name:"A9.1.31.cb8cd007",version:"9.1.31.22255",ver:"9.1.31",subid:537262715,apad_subid:537262754,qua:"V1_AND_SQ_9.1.31_8542_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2565",buildtime:1728390173,bitmap:150470524,ssover:22,fekit_ver:"8.306.776"},{name:"A9.1.30.a920c625",version:"9.1.30.22245",ver:"9.1.30",subid:537262559,apad_subid:537262598,qua:"V1_AND_SQ_9.1.30_8538_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2565",buildtime:1728390173,bitmap:150470524,ssover:22,fekit_ver:"8.306.776"},{name:"A9.1.25.008c1bb3",version:"9.1.25.21820",ver:"9.1.25",subid:537260030,apad_subid:537260069,qua:"V1_AND_SQ_9.1.25_8368_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2565",buildtime:1728390173,bitmap:150470524,ssover:22,fekit_ver:"8.305.770"},{name:"A9.1.20.fa404fa6",version:"9.1.20.21395",ver:"9.1.20",subid:537257414,apad_subid:537257453,qua:"V1_AND_SQ_9.1.20_8198_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2565",buildtime:1728390173,bitmap:150470524,ssover:22,fekit_ver:"8.304.766"},{name:"A9.1.16.3fe73575",version:"9.1.16.20980",ver:"9.1.16",subid:537254305,apad_subid:537254344,qua:"V1_AND_SQ_9.1.16_8032_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2565",buildtime:1728390173,bitmap:150470524,ssover:22,fekit_ver:"8.303.759"},{name:"A9.1.15.25851cef",version:"9.1.15.20970",ver:"9.1.15",subid:537254149,apad_subid:537254188,qua:"V1_AND_SQ_9.1.15_8028_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2565",buildtime:1728390173,bitmap:150470524,ssover:22,fekit_ver:"8.303.755"},{name:"A9.1.10.2ce90365",version:"9.1.10.20545",ver:"9.1.10",subid:537251380,apad_subid:537251419,qua:"V1_AND_SQ_9.1.10_7858_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2565",buildtime:1728390173,bitmap:150470524,ssover:22,fekit_ver:"8.302.739"},{name:"A9.1.5.468dd2ea",version:"9.1.5.20120",ver:"9.1.5",subid:537247779,apad_subid:537247818,qua:"V1_AND_SQ_9.1.5_7688_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2565",buildtime:1728390173,bitmap:150470524,ssover:22,fekit_ver:"8.301.724"},{name:"A9.1.0.2129b4e8",version:"9.1.0.19695",ver:"9.1.0",subid:537244893,apad_subid:537244932,qua:"V1_AND_SQ_9.1.0_7518_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2564",buildtime:1724730201,bitmap:150470524,ssover:22,fekit_ver:"8.209.692"},{name:"A9.0.95.705d26da",version:"9.0.95.19320",ver:"9.0.95",subid:537242075,apad_subid:537242114,qua:"V1_AND_SQ_9.0.95_7368_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2563",buildtime:1724313621,bitmap:150470524,ssover:22,fekit_ver:"8.208.645"},{name:"A9.0.90.38ae7504",version:"9.0.90.18945",ver:"9.0.90",subid:537239255,apad_subid:537239294,qua:"V1_AND_SQ_9.0.90_7218_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2561",buildtime:1718353600,bitmap:150470524,ssover:21,fekit_ver:"8.207.627"},{name:"A9.0.85.491c232e",version:"9.0.85.18570",ver:"9.0.85",subid:537236316,apad_subid:537236355,qua:"V1_AND_SQ_9.0.85_7068_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2561",buildtime:1718353600,bitmap:150470524,ssover:21,fekit_ver:"8.206.607"},{name:"A9.0.81.3daf0e38",version:"9.0.81.18205",ver:"9.0.81",subid:537233527,apad_subid:537233566,qua:"V1_AND_SQ_9.0.81_6922_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2561",buildtime:1718353600,bitmap:150470524,ssover:21,fekit_ver:"8.205.580"},{name:"A9.0.80.0d6f99ed",version:"9.0.80.18195",ver:"9.0.80",subid:537233371,apad_subid:537233410,qua:"V1_AND_SQ_9.0.80_6918_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2561",buildtime:1718353600,bitmap:150470524,ssover:21,fekit_ver:"8.205.580"},{name:"A9.0.75.c0dc0382",version:"9.0.75.17920",ver:"9.0.75",subid:537230737,apad_subid:537230776,qua:"V1_AND_SQ_9.0.75_6808_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2561",buildtime:1718353600,bitmap:150470524,ssover:21,fekit_ver:"8.204.574"},{name:"A9.0.71.e2f45246",version:"9.0.71.17655",ver:"9.0.71",subid:537228643,apad_subid:537228682,qua:"V1_AND_SQ_9.0.71_6702_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2561",buildtime:1718353600,bitmap:150470524,ssover:21,fekit_ver:"8.203.564"},{name:"A9.0.70.e4b76fcc",version:"9.0.70.17645",ver:"9.0.70",subid:537228487,apad_subid:537228526,qua:"V1_AND_SQ_9.0.70_6698_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2561",buildtime:1718353600,bitmap:150470524,ssover:21,fekit_ver:"8.203.564"},{name:"A9.0.65.530ce28d",version:"9.0.65.17370",ver:"9.0.65",subid:537225139,apad_subid:537225178,qua:"V1_AND_SQ_9.0.65_6588_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2560",buildtime:1713424357,bitmap:150470524,ssover:21,fekit_ver:"8.202.560"},{name:"A9.0.60.c5f71993",version:"9.0.60.17095",ver:"9.0.60",subid:537222797,apad_subid:537222836,qua:"V1_AND_SQ_9.0.60_6478_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2560",buildtime:1713424357,bitmap:150470524,ssover:21,fekit_ver:"8.201.556"},{name:"A9.0.56.c25547f8",version:"9.0.56.16830",ver:"9.0.56",subid:537220323,apad_subid:537220362,qua:"V1_AND_SQ_9.0.56_6372_YYB_D",sdkver:"6.0.0.2560",buildtime:1713424357,bitmap:150470524,ssover:21,fekit_ver:"8.200.555"},{name:"A9.0.55.54f52314",version:"9.0.55.16820",ver:"9.0.55",buildtime:1713424357,subid:537220167,apad_subid:537220206,bitmap:150470524,sdkver:"6.0.0.2560",qua:"V1_AND_SQ_9.0.55_6368_YYB_D",ssover:21,fekit_ver:"8.200.555"},{name:"A9.0.50.a9d8c8dc",version:"9.0.50.16545",ver:"9.0.50",buildtime:1710769234,subid:537217916,apad_subid:537217955,bitmap:150470524,sdkver:"6.0.0.2559",qua:"V1_AND_SQ_9.0.50_6258_YYB_D",ssover:21,fekit_ver:"8.106.542"},{name:"A9.0.35.52ab3f26",version:"9.0.35.16275",ver:"9.0.35",buildtime:1710769234,subid:537215475,apad_subid:537215514,bitmap:150470524,sdkver:"6.0.0.2559",qua:"V1_AND_SQ_9.0.35_6150_YYB_D",ssover:21,fekit_ver:"8.105.541"},{name:"A9.0.35.50c16765",version:"9.0.35.16270",ver:"9.0.35",buildtime:1710769234,subid:537215397,apad_subid:537215436,bitmap:150470524,sdkver:"6.0.0.2559",qua:"V1_AND_SQ_9.0.35_6148_YYB_D",ssover:21,fekit_ver:"8.105.541"},{name:"A9.0.30.47d3bd6c",version:"9.0.30.15995",ver:"9.0.30",buildtime:1710769234,subid:537211926,apad_subid:537211965,bitmap:150470524,sdkver:"6.0.0.2559",qua:"V1_AND_SQ_9.0.30_6038_YYB_D",ssover:21,fekit_ver:"8.104.509"},{name:"A9.0.25.63b29b33",version:"9.0.25.15760",ver:"9.0.25",buildtime:1702888273,subid:537210084,apad_subid:537210123,bitmap:150470524,sdkver:"6.0.0.2558",qua:"V1_AND_SQ_9.0.25_5942_YYB_D",ssover:21,fekit_ver:"8.103.508"},{name:"A9.0.25.e1f154c9",version:"9.0.25.15735",ver:"9.0.25",buildtime:1702888273,subid:537210006,apad_subid:537210045,bitmap:150470524,sdkver:"6.0.0.2558",qua:"V1_AND_SQ_9.0.25_5932_YYB_D",ssover:21,fekit_ver:"8.103.508"},{name:"A9.0.20.38faf5bf",version:"9.0.20.15515",ver:"9.0.20",buildtime:1702888273,subid:537206436,apad_subid:537206475,bitmap:150470524,sdkver:"6.0.0.2558",qua:"V1_AND_SQ_9.0.20_5844_YYB_D",ssover:21,fekit_ver:"8.102.502"},{name:"A9.0.17.215f2081",version:"9.0.17.15190",ver:"9.0.17",subid:537204134,apad_subid:537204173,qua:"V1_AND_SQ_9.0.17_5714_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2558",buildtime:1702888273,ssover:21,fekit_ver:"8.101.471"},{name:"A9.0.17.6a4a36ca",version:"9.0.17.15185",ver:"9.0.17",buildtime:1702888273,subid:537204056,apad_subid:537204095,bitmap:150470524,sdkver:"6.0.0.2558",qua:"V1_AND_SQ_9.0.17_5712_YYB_D",ssover:21,fekit_ver:"8.101.471"},{name:"A9.0.15.4145f774",version:"9.0.15.14970",ver:"9.0.15",subid:537202216,apad_subid:537202255,qua:"V1_AND_SQ_9.0.15_5626_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2558",buildtime:1702888273,ssover:21,fekit_ver:"8.101.471"},{name:"A9.0.8.10368491",version:"9.0.8.14755",ver:"9.0.8",subid:537200218,apad_subid:537200257,qua:"V1_AND_SQ_9.0.8_5540_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2558",buildtime:1702888273,ssover:21,fekit_ver:"8.100.460"},{name:"A9.0.0.0ebb1ecb",version:"9.0.0.14110",ver:"9.0.0",buildtime:1701164403,subid:537194351,apad_subid:537194390,bitmap:150470524,sdkver:"6.0.0.2557",qua:"V1_AND_SQ_9.0.0_5282_YYB_D",ssover:21,fekit_ver:"8.0.456"},{name:"A8.9.93.bf80f08f",version:"8.9.93.13475",ver:"8.9.93",buildtime:1697015435,subid:537187398,apad_subid:537187437,bitmap:150470524,sdkver:"6.0.0.2556",qua:"V1_AND_SQ_8.9.93_5028_YYB_D",ssover:21,fekit_ver:"7.301.417"},{name:"A8.9.90.cccfa0d0",version:"8.9.90.13250",ver:"8.9.90",buildtime:1697015435,subid:537185007,apad_subid:537185046,bitmap:150470524,sdkver:"6.0.0.2556",qua:"V1_AND_SQ_8.9.90_4938_YYB_D",ssover:21,fekit_ver:"7.301.417"},{name:"A8.9.88.46a07457",version:"8.9.88.13035",ver:"8.9.88",buildtime:1697015435,subid:537182769,apad_subid:537182808,bitmap:150470524,sdkver:"6.0.0.2556",qua:"V1_AND_SQ_8.9.88_4852_YYB_D",ssover:21,fekit_ver:"7.300.410"},{name:"A8.9.85.3377f9bf",version:"8.9.85.12820",ver:"8.9.85",buildtime:1697015435,subid:537180568,apad_subid:537180607,bitmap:150470524,sdkver:"6.0.0.2556",qua:"V1_AND_SQ_8.9.85_4766_YYB_D",ssover:21,fekit_ver:"7.103.403"},{name:"A8.9.83.c9a61e5e",version:"8.9.83.12605",ver:"8.9.83",buildtime:1691565978,subid:537178646,apad_subid:537178685,bitmap:150470524,sdkver:"6.0.0.2554",qua:"V1_AND_SQ_8.9.83_4680_YYB_D",ssover:20,fekit_ver:"7.102.401"},{name:"A8.9.80.57a42f50",version:"8.9.80.12440",ver:"8.9.80",buildtime:1691565978,subid:537176863,apad_subid:537176902,bitmap:150470524,sdkver:"6.0.0.2554",qua:"V1_AND_SQ_8.9.80_4614_YYB_D",ssover:20,fekit_ver:"7.101.381"},{name:"A8.9.78.d5d9d71d",version:"8.9.78.12275",ver:"8.9.78",buildtime:1691565978,subid:537175315,apad_subid:537175354,bitmap:150470524,sdkver:"6.0.0.2554",qua:"V1_AND_SQ_8.9.78_4548_YYB_D",ssover:20,fekit_ver:"7.100.363"},{name:"A8.9.76.cefd59d7",version:"8.9.76.12115",ver:"8.9.76",subid:537173573,apad_subid:537173621,qua:"V1_AND_SQ_8.9.76_4484_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2554",buildtime:1691565978,ssover:20,fekit_ver:"7.0.344"},{name:"A8.9.76.c71a1fa8",version:"8.9.76.12115",ver:"8.9.76",buildtime:1691565978,subid:537173477,apad_subid:537173525,bitmap:150470524,sdkver:"6.0.0.2554",qua:"V1_AND_SQ_8.9.76_4484_YYB_D",ssover:20,fekit_ver:"7.0.344"},{name:"A8.9.75.354d41fc",version:"8.9.75.12110",ver:"8.9.75",buildtime:1691565978,subid:537173381,apad_subid:537173429,bitmap:150470524,sdkver:"6.0.0.2554",qua:"V1_AND_SQ_8.9.75_4482_YYB_D",ssover:20,fekit_ver:"7.0.344"},{name:"A8.9.73.08fbad4d",version:"8.9.73.11950",ver:"8.9.73",subid:537171785,apad_subid:537171833,qua:"V1_AND_SQ_8.9.73_4416_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2553",buildtime:1690371091,ssover:20,fekit_ver:"7.0.337"},{name:"A8.9.73.5b437a51",version:"8.9.73.11945",ver:"8.9.73",subid:537171689,apad_subid:537171737,qua:"V1_AND_SQ_8.9.73_4416_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2553",buildtime:1690371091,ssover:20,fekit_ver:"7.0.337"},{name:"A8.9.71.9fd08ae5",version:"8.9.71.11735",ver:"8.9.71",subid:537170024,apad_subid:537170072,qua:"V1_AND_SQ_8.9.71_4332_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2551",buildtime:1688720082,ssover:20,fekit_ver:"7.0.326"},{name:"A8.9.70.b4332bd3",version:"8.9.70.11730",ver:"8.9.70",subid:537169928,apad_subid:537169976,qua:"V1_AND_SQ_8.9.70_4330_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2551",buildtime:1688720082,ssover:20,fekit_ver:"7.0.326"},{name:"A8.9.68.e757227e",version:"8.9.68.11565",ver:"8.9.68",subid:537168313,apad_subid:537168361,qua:"V1_AND_SQ_8.9.68_4264_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2549",buildtime:1687254022,ssover:20,fekit_ver:"7.0.300"},{name:"A8.9.63.5156de84",version:"8.9.63.11390",ver:"8.9.63",subid:537164840,apad_subid:537164888,qua:"V1_AND_SQ_8.9.63_4194_YYB_D",channel:"GuanWang",sdkver:"6.0.0.2546",buildtime:1685069178,ssover:20,fekit_ver:"6.100.248"}].map(e=>({id:"com.tencent.mobileqq",nt:!0,appid:16,app_key:"0S200MNJT807V3GE",sign:Buffer.from("A6 B7 45 BF 24 A2 C2 77 52 77 16 F6 F3 6E B6 8D".split(" ").map(e=>parseInt(e,16))),main_sig_map:16724722,sub_sig_map:66560,display:"Android",device_type:-1,bitmap:150470524,...e})),tim=[{nt:!0,name:"A4.1.0.e4e0ee28",version:"4.1.0.4050",ver:"4.1.0",subid:537298353,apad_subid:537298411,qua:"V1_AND_SQ_9.0.95_4050_TIM_D",channel:"GuanWang",sdkver:"6.0.0.2563",buildtime:1724313621,ssover:22,fekit_ver:"8.402.854"},{nt:!0,name:"A4.0.99.dc92ee7f",version:"4.0.99.4030",ver:"4.0.99",subid:537282136,apad_subid:537282194,qua:"V1_AND_SQ_9.0.95_4030_TIM_D",channel:"GuanWang",sdkver:"6.0.0.2563",buildtime:1724313621,bitmap:150470524,ssover:22,fekit_ver:"8.301.736"},{nt:!0,name:"A4.0.98.2e3d9799",version:"4.0.98.4012",ver:"4.0.98",subid:537264175,apad_subid:537264222,qua:"V1_AND_SQ_9.0.95_4012_TIM_D",channel:"GuanWang",sdkver:"6.0.0.2563",buildtime:1724313621,bitmap:150470524,ssover:22,fekit_ver:"8.301.736"},{nt:!0,name:"A4.0.97.3110ef2b",version:"4.0.97.4011",ver:"4.0.97",subid:537263469,apad_subid:537263596,qua:"V1_AND_SQ_9.0.95_4011_TIM_D",channel:"GuanWang",sdkver:"6.0.0.2563",buildtime:1724313621,bitmap:150470524,ssover:22,fekit_ver:"8.301.736"},{nt:!0,name:"A4.0.96.6c784d54",version:"4.0.96.4010",ver:"4.0.96",subid:537261131,apad_subid:537261188,qua:"V1_AND_SQ_9.0.95_4010_TIM_D",channel:"GuanWang",sdkver:"6.0.0.2563",buildtime:1724313621,bitmap:150470524,ssover:22,fekit_ver:"8.301.736"},{nt:!0,name:"A4.0.95.3b8db658",version:"4.0.95.4008",ver:"4.0.95",subid:537249218,apad_subid:537249147,qua:"V1_AND_SQ_9.0.95_4008_TIM_D",channel:"GuanWang",sdkver:"6.0.0.2563",buildtime:1724313621,bitmap:150470524,ssover:22,fekit_ver:"8.301.736"},{name:"A3.5.8.0b4a96f9",version:"3.5.8.3228",ver:"3.5.8",subid:537237656,qua:"V1_AND_SQ_8.3.9_358_TIM_D",channel:"GuanWang",sdkver:"6.0.0.2484",buildtime:1630062176,ssover:18,fekit_ver:"8.200.582"},{name:"A3.5.7.877bb8bb",version:"3.5.7.3218",ver:"3.5.7",buildtime:1630062176,subid:537223825,bitmap:150470524,sdkver:"6.0.0.2484",qua:"V1_AND_SQ_8.3.9_357_TIM_D",ssover:18,fekit_ver:"8.200.552"},{name:"A3.5.6.20c82aa0",version:"3.5.6.3208",ver:"3.5.6",buildtime:1630062176,subid:537181169,bitmap:150470524,sdkver:"6.0.0.2484",qua:"V1_AND_SQ_8.3.9_356_TIM_D",ssover:18,fekit_ver:"7.101.411"},{name:"A3.5.5.fa2ef27c",version:"3.5.5.3198",ver:"3.5.5",buildtime:1630062176,subid:537177451,bitmap:150470524,sdkver:"6.0.0.2484",qua:"V1_AND_SQ_8.3.9_355_TIM_D",ssover:18,fekit_ver:"7.100.363"},{name:"A3.5.2.3f4af297",version:"3.5.2.3178",ver:"3.5.2",buildtime:1630062176,subid:537162286,bitmap:150470524,sdkver:"6.0.0.2484",qua:"V1_AND_SQ_8.3.9_352_TIM_D",ssover:18,fekit_ver:"0"},{name:"A3.5.1.db08e878",version:"3.5.1.3168",ver:"3.5.1",buildtime:1630062176,subid:537150355,bitmap:150470524,sdkver:"6.0.0.2484",qua:"V1_AND_SQ_8.3.9_351_TIM_D",ssover:18,fekit_ver:"0"},{name:"A3.5.0.88ad9c55",version:"3.5.0.3148",ver:"3.5.0",buildtime:1630062176,subid:537143920,qua:"V1_AND_SQ_8.3.9_350_TIM_D",channel:"GuanWang",sdkver:"6.0.0.2484",ssover:18,fekit_ver:"0"},{name:"A3.5.0.fda8b509",version:"3.5.0.3138",ver:"3.5.0",buildtime:1630062176,subid:537142492,qua:"V1_AND_SQ_8.3.9_350_TIM_D",channel:"GuanWang",sdkver:"6.0.0.2484",ssover:18,fekit_ver:"0"}].map(e=>({id:"com.tencent.tim",app_key:"0S200MNJT807V3GE",sign:Buffer.from("775e696d09856872fdd8ab4f3f06b1e0","hex"),appid:16,main_sig_map:16724722,sub_sig_map:66560,display:"Tim",device_type:-1,bitmap:150470524,...e})),watch=[{name:"Atestrevision",version:"2.0.8",ver:"2.0.8",buildtime:1559564731,subid:537065138,bitmap:16252796,sdkver:"6.0.0.2365",qua:"",ssover:5},{name:"Atestrevision",version:"9.0.7.2561",ver:"9.0.7",subid:537282233,channel:"",sdkver:"6.0.0.2564",qua:"V1_WAT_SQ_9.0.7_0_IDC_B",buildtime:1724730201,ssover:22,fekit_ver:"8.403.543"},{name:"Atestrevision",version:"9.0.5.2533",ver:"9.0.5",subid:537258298,channel:"",sdkver:"6.0.0.2564",qua:"V1_WAT_SQ_9.0.3_0_IDC_B",buildtime:1724730201,ssover:22,fekit_ver:"8.208.537"},{name:"Atestrevision",version:"9.0.3.2508",ver:"9.0.3",subid:537243416,channel:"",sdkver:"6.0.0.2498",qua:"V1_WAT_SQ_9.0.3_0_IDC_B",buildtime:1648001696,ssover:18,fekit_ver:"8.105.526"},{name:"Atestrevision",version:"9.0.1.2451",ver:"9.0.1",subid:537214131,channel:"",sdkver:"6.0.0.2498",qua:"V1_AND_SQ_8.9.68_0_RDM_B",buildtime:1648001696,ssover:18,fekit_ver:"8.105.526"},{name:"Atestrevision",version:"2.1.7",ver:"2.1.7",buildtime:1654570540,subid:537140974,bitmap:16252796,sdkver:"6.0.0.2366",qua:"V1_WAT_SQ_2.1.7_002_IDC_B",ssover:5,fekit_ver:"0"}].map(e=>({id:"com.tencent.qqlite",app_key:"0S200MNJT807V3GE",sign:Buffer.from("A6 B7 45 BF 24 A2 C2 77 52 77 16 F6 F3 6E B6 8D".split(" ").map(e=>parseInt(e,16))),appid:16,main_sig_map:16724722,sub_sig_map:66560,display:"Watch",device_type:8,bitmap:150470524,...e})),hd={id:"com.tencent.qq",app_key:"0S200MNJT807V3GE",name:"A6.8.2.21241",version:"6.8.2.21241",ver:"6.8.2",sign:mobile[0].sign,buildtime:1647227495,appid:16,subid:537128930,bitmap:150470524,main_sig_map:1970400,sub_sig_map:66560,sdkver:"6.2.0.1023",display:"iMac",device_type:5,qua:"",ssover:12},apklist={[1]:mobile,2:mobile.map(e=>({...e,subid:e?.apad_subid||e.subid,display:e?.apad_subid?"aPad":e.display})),3:watch,4:{...hd},5:{...mobile[0],id:"com.tencent.mqq",subid:537155074,sign:hd.sign,name:"8.9.50.611",version:"8.9.50.611",ver:"8.9.50",sdkver:"6.0.0.2535",qua:"",display:"iPad",ssover:19},6:tim,7:[]};function readCustomApkInfoList(){let e="data/icqq/custom-apks.json";try{var _;return fs.existsSync(e)?(_=JSON.parse(fs.readFileSync(e).toString()),(Array.isArray(_)?_:_?[_]:[]).map(e=>(e.sign=Buffer.from(e.sign,"hex"),{...mobile[0],nt:!1,qr_appid:0,fekit_ver:void 0,...e}))):(fs.existsSync(path.dirname(e))||fs.mkdirSync(path.dirname(e),{recursive:!0}),fs.writeFileSync(e,JSON.stringify([mobile[0]].map(e=>(delete(e={...e}).apad_subid,e.sign=e.sign.toString("hex"),e)),null,1)),Bot.makeLog("mark","创建了自定义版本信息文件:"+e),[mobile[0]])}catch(e){return console.log(e),[]}}export function getApkInfoList(e){7===e&&(apklist[e]=readCustomApkInfoList());e=Array.isArray(apklist[e])?apklist[e]:apklist[e]?[apklist[e]]:[];if(e.length)return e;throw new Error("版本列表为空")}
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | logger.info(logger.yellow("- 正在加载 ICQQ 适配器插件"))
2 |
3 | import makeConfig from "../../lib/plugins/config.js"
4 | import cfg from "../../lib/config/config.js"
5 | import { ulid } from "ulid"
6 |
7 | import url from "url"
8 | import path from "path"
9 | import fs from "node:fs/promises"
10 |
11 | const __filename = url.fileURLToPath(import.meta.url)
12 | const __dirname = path.dirname(__filename)
13 |
14 | let icqq
15 | for (const i of ["Model", "node_modules"])
16 | try {
17 | const dir = `${__dirname}/${i}/icqq/`
18 | if (!(await fs.stat(dir))) continue
19 | const p = JSON.parse(await fs.readFile(`${dir}package.json`, "utf8"))
20 | icqq = (await import(`file://${dir}${p.main}`)).default
21 | icqq.package = p
22 | if (!p.version.startsWith("0")) break
23 | ;(await import(`file://${dir}lib/core/device.js`)).default.getApkInfoList = (
24 | await import("./Model/device.js")
25 | ).getApkInfoList
26 | Object.assign(
27 | (await import(`file://${dir}lib/message/parser.js`)).default,
28 | await import("./Model/parser.js"),
29 | )
30 | Object.assign(icqq.Parser.prototype, {
31 | core: icqq.core,
32 | face: await import(`file://${dir}lib/message/face.js`),
33 | image: await import(`file://${dir}lib/message/image.js`),
34 | })
35 | break
36 | } catch (err) {
37 | icqq = err
38 | }
39 |
40 | if (icqq instanceof Error) throw icqq
41 |
42 | const { config, configSave } = await makeConfig(
43 | "ICQQ",
44 | {
45 | tips: "",
46 | permission: "master",
47 | markdown: {
48 | mode: false,
49 | button: false,
50 | callback: true,
51 | },
52 | bot: {},
53 | token: [],
54 | },
55 | {
56 | tips: [
57 | "欢迎使用 TRSS-Yunzai ICQQ Plugin ! 作者:时雨🌌星空",
58 | "参考:https://github.com/TimeRainStarSky/Yunzai-ICQQ-Plugin",
59 | ],
60 | },
61 | )
62 |
63 | const adapter = new (class ICQQAdapter {
64 | constructor() {
65 | this.id = "QQ"
66 | this.name = "ICQQ"
67 | this.version = `v${icqq.package.version}`
68 | }
69 |
70 | async uploadVideo(id, file) {
71 | const group = Bot[id].pickGroup(Math.ceil(Math.random() * 10 ** 9))
72 | const video = await group.uploadVideo({ file })
73 | const proto = Bot[id].icqq.core.pb.decode(
74 | Buffer.from(video.file.replace("protobuf://", ""), "base64"),
75 | )
76 | return group.getVideoUrl(proto[1], proto[2])
77 | }
78 |
79 | async uploadRecord(id, file) {
80 | const group = Bot[id].pickGroup(Math.ceil(Math.random() * 10 ** 9))
81 | const record = await group.uploadPtt({ file })
82 | const proto = Bot[id].icqq.core.pb.decode(
83 | Buffer.from(record.file.replace("protobuf://", ""), "base64"),
84 | )
85 | const body = Bot[id].icqq.core.pb.encode({
86 | 1: 1200,
87 | 2: 0,
88 | 14: { 10: id, 20: proto[3], 30: 2 },
89 | 101: 17,
90 | 102: 104,
91 | 99999: { 90300: 1, 91000: 2, 91100: 1 },
92 | })
93 | const payload = await Bot[id].sendUni(
94 | "PttCenterSvr.pb_pttCenter_CMD_REQ_APPLY_DOWNLOAD-1200",
95 | body,
96 | )
97 | const rsp = Bot[id].icqq.core.pb.decode(payload)[14]
98 | if (rsp[10] !== 0) Bot.makeLog("error", [rsp, "获取语音下载地址失败"], id)
99 | const url = new URL(String(rsp[30][50]))
100 | url.host = "grouptalk.c2c.qq.com"
101 | url.protocol = "https"
102 | return url.href
103 | }
104 |
105 | async uploadImage(id, file) {
106 | const image = new Bot[id].icqq.Image({ file })
107 | image.upload = await Bot[id].pickGroup(Math.ceil(Math.random() * 10 ** 9)).uploadImages([image])
108 | if (image.upload[0].status === "fulfilled")
109 | image.url = Bot[id].icqq.getGroupImageUrl(image.md5.toString("hex"))
110 | return image
111 | }
112 |
113 | async makeMarkdownImage(id, file) {
114 | const image = await Bot[id].uploadImage(file)
115 | return {
116 | des: `![图片 #${image.width || 0}px #${image.height || 0}px]`,
117 | url: `(${image.url})`,
118 | }
119 | }
120 |
121 | makeMarkdownText(text) {
122 | const match = text.match(
123 | /https?:\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/g,
124 | )
125 | if (match) for (const url of match) text = text.replace(url, `<${url}>`)
126 | return text
127 | }
128 |
129 | makeButton(id, pick, button, style, forward) {
130 | const msg = {
131 | id: ulid(),
132 | render_data: {
133 | label: button.text,
134 | visited_label: button.clicked_text,
135 | style,
136 | ...button.QQBot?.render_data,
137 | },
138 | }
139 |
140 | if (button.link)
141 | msg.action = {
142 | type: 0,
143 | permission: { type: 2 },
144 | data: button.link,
145 | ...button.QQBot?.action,
146 | }
147 | else if (button.input)
148 | msg.action = {
149 | type: 2,
150 | permission: { type: 2 },
151 | data: button.input,
152 | enter: button.send,
153 | ...button.QQBot?.action,
154 | }
155 | else if (button.callback)
156 | msg.action = {
157 | type: 2,
158 | permission: { type: 2 },
159 | data: button.callback,
160 | enter: true,
161 | ...button.QQBot?.action,
162 | }
163 | else return false
164 |
165 | if (forward && config.markdown.callback && (button.input || button.callback))
166 | for (const i of Bot.uin)
167 | if (Bot[i].adapter?.id === "QQBot" && Bot[i].sdk?.config?.appid && Bot[i].callback) {
168 | msg.action.type = 1
169 | delete msg.action.data
170 | this.markdown_appid = Number(Bot[i].sdk.config.appid)
171 | Bot[i].callback[msg.id] = {
172 | self_id: id,
173 | user_id: pick.user_id,
174 | group_id: pick.group_id,
175 | message: button.input || button.callback,
176 | }
177 | setTimeout(() => delete Bot[i].callback[msg.id], 3600000)
178 | break
179 | }
180 |
181 | if (button.permission) {
182 | if (button.permission === "admin") {
183 | msg.action.permission.type = 1
184 | } else {
185 | msg.action.permission.type = 0
186 | msg.action.permission.specify_user_ids = String(button.permission)
187 | }
188 | }
189 | return msg
190 | }
191 |
192 | makeButtons(id, pick, button_square, forward) {
193 | const msgs = []
194 | const random = Math.floor(Math.random() * 2)
195 | for (const button_row of button_square) {
196 | let column = 0
197 | const buttons = []
198 | for (let button of button_row) {
199 | button = this.makeButton(
200 | id,
201 | pick,
202 | button,
203 | (random + msgs.length + buttons.length) % 2,
204 | forward,
205 | )
206 | if (button) buttons.push(button)
207 | }
208 | if (buttons.length) msgs.push({ buttons })
209 | }
210 | return msgs
211 | }
212 |
213 | async makeMarkdownMsg(id, pick, msg) {
214 | const messages = []
215 | let content = ""
216 | const button = []
217 | const forward = []
218 |
219 | for (let i of Array.isArray(msg) ? msg : [msg]) {
220 | if (typeof i === "object") i = { ...i }
221 | else i = { type: "text", text: i }
222 |
223 | switch (i.type) {
224 | case "text":
225 | content += this.makeMarkdownText(i.text)
226 | break
227 | case "image": {
228 | const { des, url } = await this.makeMarkdownImage(id, i.file)
229 | content += `${des}${url}`
230 | break
231 | }
232 | case "file":
233 | if (i.file) i.file = await Bot.fileToUrl(i.file, i)
234 | content += this.makeMarkdownText(`文件:${i.file}`)
235 | break
236 | case "at":
237 | if (i.qq === "all") {
238 | content += "[@全体成员](mqqapi://markdown/mention?at_type=everyone)"
239 | } else {
240 | if (!i.name) {
241 | let info
242 | if (pick.pickMember) info = pick.pickMember(i.qq).info
243 | info ??=
244 | Bot[id].pickFriend(i.qq).info || (await Bot[id].pickUser(i.qq).getSimpleInfo())
245 | if (info) i.name = info.card || info.nickname
246 | }
247 |
248 | if (i.name) i.name += `(${i.qq})`
249 | else i.name = i.qq
250 | content += `[@${i.name}](mqqapi://markdown/mention?at_type=1&at_tinyid=${i.qq})`
251 | }
252 | break
253 | case "markdown":
254 | content += i.data
255 | break
256 | case "button":
257 | button.push(...this.makeButtons(id, pick, i.data, true))
258 | break
259 | case "node":
260 | for (const node of i.data)
261 | for (const message of await this.makeMarkdownMsg(id, pick, node.message))
262 | forward.push({ user_id: 80000000, nickname: "匿名消息", ...node, ...message })
263 | break
264 | case "raw":
265 | messages.push([icqq.Converter.prototype.hasOwnProperty(i.data?.type) ? i.data : i])
266 | break
267 | default:
268 | if (icqq.Converter.prototype.hasOwnProperty(i.type)) {
269 | messages.push([i])
270 | continue
271 | }
272 | content += this.makeMarkdownText(Bot.String(i))
273 | }
274 | }
275 |
276 | if (content) messages.unshift([{ type: "markdown", content }])
277 | if (button.length) {
278 | for (const i of messages) {
279 | if (i[0].type === "markdown")
280 | i.push({
281 | type: "button",
282 | content: {
283 | appid: this.markdown_appid,
284 | rows: button.splice(0, 5),
285 | },
286 | })
287 | if (!button.length) break
288 | }
289 | while (button.length)
290 | messages.push([
291 | { type: "markdown", content: " " },
292 | {
293 | type: "button",
294 | content: {
295 | appid: this.markdown_appid,
296 | rows: button.splice(0, 5),
297 | },
298 | },
299 | ])
300 | }
301 |
302 | for (const i of messages) forward.push({ type: "node", message: i })
303 | return forward
304 | }
305 |
306 | async makeMsg(id, pick, msg) {
307 | if (!Array.isArray(msg)) msg = [msg]
308 | const message = []
309 | const messages = []
310 | const forward = []
311 | let reply
312 |
313 | for (let i of msg) {
314 | if (typeof i === "object")
315 | switch (i.type) {
316 | case "text":
317 | case "image":
318 | case "face":
319 | break
320 | case "file":
321 | await pick.sendFile(i.file, i.name)
322 | continue
323 | case "reply":
324 | reply = i
325 | continue
326 | case "at":
327 | if (i.qq !== "all" && !i.name) {
328 | let info
329 | if (pick.pickMember) info = pick.pickMember(i.qq).info
330 | else info = Bot[id].pickFriend(i.qq).info
331 | if (!info) info = await Bot[id].pickUser(i.qq).getSimpleInfo()
332 | if (info) i.name = info.card || info.nickname
333 | }
334 | if (i.name && !i.text) i.text = `${i.name}(${i.qq})`
335 | break
336 | case "markdown":
337 | forward.push(...(await this.makeMarkdownMsg(id, pick, msg)))
338 | continue
339 | case "button":
340 | if (config.markdown.button) {
341 | if (config.markdown.button === "direct" || config.markdown.mode === "mix")
342 | message.push({
343 | type: "button",
344 | appid: this.markdown_appid,
345 | content: { rows: this.makeButtons(id, pick, i.data) },
346 | })
347 | else if (config.markdown.button === "separate")
348 | messages.push([
349 | {
350 | type: "button",
351 | appid: this.markdown_appid,
352 | content: { rows: this.makeButtons(id, pick, i.data) },
353 | },
354 | ])
355 | else return [await this.makeMarkdownMsg(id, pick, msg)]
356 | }
357 | continue
358 | case "node":
359 | for (const node of i.data)
360 | for (const message of await this.makeMsg(id, pick, node.message))
361 | forward.push({
362 | user_id: 80000000,
363 | nickname: "匿名消息",
364 | ...node,
365 | type: "node",
366 | message,
367 | })
368 | continue
369 | case "raw":
370 | if (icqq.Converter.prototype.hasOwnProperty(i.data?.type)) i = i.data
371 | break
372 | case "long_msg":
373 | if (msg.length > 1) continue
374 | break
375 | default:
376 | if (icqq.Converter.prototype.hasOwnProperty(i.type)) {
377 | messages.push([i])
378 | continue
379 | }
380 | i = Bot.String(i)
381 | }
382 | message.push(i)
383 | }
384 |
385 | if (message.length) messages.push(message)
386 | if (forward.length) messages.push(forward)
387 | if (reply) for (const i of messages) i.unshift(reply)
388 | return messages
389 | }
390 |
391 | async sendMsg(id, pick, msg, ...args) {
392 | const rets = { message_id: [], data: [], error: [] }
393 | let msgs
394 |
395 | const sendMsg = async () => {
396 | for (const i of msgs)
397 | try {
398 | Bot.makeLog("debug", ["发送消息", i], id)
399 | const ret = await pick.sendMsg(i, ...args)
400 | Bot.makeLog("debug", ["发送消息返回", ret], id)
401 |
402 | rets.data.push(ret)
403 | if (ret.message_id) rets.message_id.push(ret.message_id)
404 | } catch (err) {
405 | Bot.makeLog("error", ["发送消息错误", i, err], id)
406 | rets.error.push(err)
407 | return false
408 | }
409 | }
410 |
411 | if (config.markdown.mode) {
412 | if (config.markdown.mode === "mix")
413 | msgs = [...(await this.makeMsg(id, pick, msg)), await this.makeMarkdownMsg(id, pick, msg)]
414 | else msgs = [await this.makeMarkdownMsg(id, pick, msg)]
415 | } else {
416 | msgs = await this.makeMsg(id, pick, msg)
417 | }
418 |
419 | if ((await sendMsg()) === false) {
420 | msgs = await this.makeMsg(id, pick, [await Bot.makeForwardMsg([{ message: msg }])])
421 | await sendMsg()
422 | }
423 |
424 | if (rets.data.length === 1) return rets.data[0]
425 | return rets
426 | }
427 |
428 | async recallMsg(id, pick, message_id) {
429 | Bot.makeLog("info", `撤回消息:${message_id}`, id)
430 | if (!Array.isArray(message_id)) message_id = [message_id]
431 | const msgs = []
432 | for (const i of message_id) msgs.push(await pick.recallMsg(i))
433 | return msgs
434 | }
435 |
436 | getPick(id, pick, target, prop, receiver) {
437 | switch (prop) {
438 | case "sendMsg":
439 | return this.sendMsg.bind(this, id, pick)
440 | case "recallMsg":
441 | return this.recallMsg.bind(this, id, pick)
442 | case "makeForwardMsg":
443 | return Bot.makeForwardMsg
444 | case "sendForwardMsg":
445 | return async (msg, ...args) =>
446 | this.sendMsg(id, pick, await Bot.makeForwardMsg(msg), ...args)
447 | case "getInfo":
448 | return () =>
449 | pick.info ||
450 | (typeof pick.renew === "function" && pick.renew()) ||
451 | (typeof pick.getSimpleInfo === "function" && pick.getSimpleInfo())
452 | case "pickMember":
453 | case "asMember":
454 | return (...args) => {
455 | for (const i in args) args[i] = Number(args[i]) || args[i]
456 | const pickMember = pick[prop](...args)
457 | return new Proxy(
458 | {},
459 | {
460 | get: this.getPick.bind(this, id, pickMember),
461 | },
462 | )
463 | }
464 | case "raw":
465 | return pick
466 | }
467 | return target[prop] ?? pick[prop]
468 | }
469 |
470 | getBot(id, target, prop, receiver) {
471 | switch (prop) {
472 | case "pickUser":
473 | case "pickFriend":
474 | case "pickGroup":
475 | case "pickMember":
476 | return (...args) => {
477 | for (const i in args) args[i] = Number(args[i]) || args[i]
478 | const pick = target.sdk[prop](...args)
479 | return new Proxy(
480 | {},
481 | {
482 | get: this.getPick.bind(this, id, pick),
483 | },
484 | )
485 | }
486 | }
487 | if (prop in target) return target[prop]
488 | if (typeof target.sdk[prop]?.bind === "function") return target.sdk[prop].bind(target.sdk)
489 | return target.sdk[prop]
490 | }
491 |
492 | makeEvent(data) {
493 | for (const i of ["friend", "group", "member"]) {
494 | if (typeof data[i] !== "object") continue
495 | const pick = data[i]
496 | data[i] = new Proxy(
497 | {},
498 | {
499 | get: this.getPick.bind(this, data.self_id, pick),
500 | },
501 | )
502 | }
503 |
504 | if (data.post_type === "message")
505 | try {
506 | data.raw_message = data.toString()
507 | } catch (err) {
508 | Bot.makeLog("error", err, data.self_id)
509 | }
510 |
511 | if (data.source) {
512 | if (data.source.seq && data.group?.getChatHistory)
513 | data.getReply = async () => (await data.group.getChatHistory(data.source.seq, 1))[0]
514 | else if (data.source.time && data.friend?.getChatHistory)
515 | data.getReply = async () => (await data.friend.getChatHistory(data.source.time, 1))[0]
516 | }
517 | }
518 |
519 | async connect(token, send = Bot.sendMasterMsg.bind(Bot), get) {
520 | token = token.split(":")
521 | const id = Number(token.shift())
522 | const password = token.shift()
523 | const opts = {
524 | data_dir: `${process.cwd()}/data/icqq/${id}`,
525 | cache_group_member: cfg.bot.cache_group_member,
526 | ...config.bot,
527 | }
528 | const platform = token.shift()
529 | if (platform) opts.platform = Number(platform)
530 | const ver = token.shift()
531 | if (ver) opts.ver = ver
532 | const sign_api_addr = token.join(":")
533 | if (sign_api_addr) opts.sign_api_addr = sign_api_addr
534 |
535 | const bot = icqq.createClient(opts)
536 | const log = {}
537 | for (const i of ["trace", "debug", "info", "mark", "warn", "error", "fatal"])
538 | log[i] = (...args) => Bot.makeLog(i, args, id)
539 | bot.logger = log
540 |
541 | let getTips = "发送 "
542 | let sendMsg
543 | if (typeof get !== "function") {
544 | getTips += `#Bot验证${id}:`
545 | get = () =>
546 | new Promise(resolve =>
547 | Bot.once(`verify.${id}`, data => {
548 | send = data.reply
549 | sendMsg = true
550 | resolve(data.msg)
551 | }),
552 | )
553 | }
554 |
555 | bot.on("system.login.qrcode", async data => {
556 | Bot.em("system.login.qrcode", data)
557 | send([`[${id}] 扫码登录`, segment.image(data.image)])
558 | for (;;) {
559 | await Bot.sleep(3000)
560 | const { retcode } = await bot.queryQrcodeResult()
561 | switch (retcode) {
562 | case 0:
563 | return bot.qrcodeLogin()
564 | case 17:
565 | return send(`二维码已过期,发送 #Bot上线${id} 重新登录`)
566 | case 54:
567 | return send(`登录取消,发送 #Bot上线${id} 重新登录`)
568 | }
569 | }
570 | })
571 |
572 | bot.on("system.login.slider", async data => {
573 | Bot.em("system.login.slider", data)
574 | const fnc = {}
575 | if (bot.useNTLogin) {
576 | const url = `https://captcha-nt-api.928100.xyz/?key=${id}`
577 | for (;;) {
578 | const res = await (await fetch(url)).json()
579 | Bot.makeLog("debug", ["Ticket", res], id)
580 | if (res.status == "0") break
581 | await Bot.sleep(3000)
582 | }
583 | send(
584 | `[${id}] 请打开下方链接完成滑动验证\n` +
585 | `https://CapNT.928100.xyz?${new URL(data.url).searchParams.toString()}`,
586 | )
587 | fnc.ticket = async () => {
588 | const res = await (await fetch(url)).json()
589 | Bot.makeLog("debug", ["Ticket", res], id)
590 | if (res.status != "0" && res.ticket && res.randstr) return `${res.ticket},${res.randstr}`
591 | }
592 | } else {
593 | send(
594 | `[${id}] 请选择滑动验证方式\n` +
595 | `Bot 与浏览器处于同一网络下推荐网页,否则网页反代\n\n` +
596 | `网页反代验证:${getTips}网页反代\n` +
597 | `网页验证:${getTips}网页\n` +
598 | `请求码验证:${getTips}请求码\n` +
599 | `手动验证:${getTips}ticket\n` +
600 | data.url,
601 | )
602 | const msg = await get()
603 | switch (msg) {
604 | case "网页反代": {
605 | const url = `https://GT.928100.xyz/captcha/slider?key=${id}`
606 | const ws = new (await import("ws")).WebSocket(url)
607 | const wsSend = data => {
608 | Bot.makeLog("debug", [`发送 ${url}`, data], id)
609 | ws.send(JSON.stringify(data))
610 | }
611 | let ticket
612 | fnc.ticket = () => {
613 | if (ticket instanceof Error) throw ticket
614 | return ticket
615 | }
616 | fnc.close = ws.terminate.bind(ws)
617 | ws.onclose = () => {
618 | Bot.makeLog("debug", `连接关闭 ${url}`, id)
619 | ticket ??= Error(`连接关闭 ${url}`)
620 | }
621 | ws.onerror = ({ error }) => {
622 | Bot.makeLog("debug", [`连接错误 ${url}`, error], id)
623 | ticket ??= Error(`连接错误 ${url}`, { cause: error })
624 | fnc.close()
625 | }
626 | ws.onopen = () => {
627 | wsSend({ type: "register", payload: { url: data.url } })
628 | send(url)
629 | }
630 | ws.onmessage = async msg => {
631 | try {
632 | const data = JSON.parse(msg.data)
633 | Bot.makeLog("debug", [`收到 ${url}`, data], id)
634 | switch (data.type) {
635 | case "ticket":
636 | ticket = data.payload.ticket
637 | fnc.close()
638 | break
639 | case "handle":
640 | const { url, ...opts } = data.payload
641 | const req = await fetch(url, opts)
642 | data.payload = {
643 | result: Buffer.from(await req.arrayBuffer()).toString("base64"),
644 | headers: Object.fromEntries(req.headers.entries()),
645 | }
646 | wsSend(data)
647 | break
648 | default:
649 | Bot.makeLog("info", data, id)
650 | }
651 | } catch (err) {
652 | Bot.makeLog("error", err, id)
653 | }
654 | }
655 | break
656 | }
657 | case "网页": {
658 | const url = `https://GT.928100.xyz/captcha/slider?key=${id}`
659 | await fetch(url, {
660 | method: "POST",
661 | headers: { "Content-Type": "application/json" },
662 | body: JSON.stringify({ url: data.url }),
663 | })
664 | send(url)
665 |
666 | fnc.ticket = async () => {
667 | const res = await (
668 | await fetch(url, {
669 | method: "POST",
670 | headers: { "Content-Type": "application/json" },
671 | body: JSON.stringify({ submit: id }),
672 | })
673 | ).json()
674 | return res.data?.ticket
675 | }
676 | break
677 | }
678 | case "请求码": {
679 | const url = data.url.replace("ssl.captcha.qq.com", "txhelper.glitch.me")
680 | const code = await (await fetch(url)).text()
681 | send(code)
682 |
683 | fnc.ticket = async () => {
684 | const res = await (await fetch(url)).text()
685 | if (res !== code) return res
686 | }
687 | break
688 | }
689 | default:
690 | return bot.submitSlider(msg)
691 | }
692 | }
693 | try {
694 | for (let i = 0; i < 60; i++) {
695 | await Bot.sleep(3000)
696 | const ticket = await fnc.ticket()
697 | if (ticket) return bot.submitSlider(ticket)
698 | }
699 | } catch (err) {
700 | Bot.makeLog("error", err, id)
701 | return send(`滑动验证错误,发送 #Bot上线${id} 重新登录`)
702 | }
703 | if (fnc.close) fnc.close()
704 | return send(`滑动验证超时,发送 #Bot上线${id} 重新登录`)
705 | })
706 |
707 | bot.on("system.login.device", async data => {
708 | Bot.em("system.login.device", data)
709 | if (bot.useNTLogin) {
710 | send(
711 | `[${id}] 触发设备验证\n` +
712 | `请在QQ内点击下方链接完成验证, 复制到浏览器无效\n` +
713 | `通过验证后${getTips}继续登录\n\n` +
714 | data.url,
715 | )
716 | for (;;) {
717 | if ((await get()) === "继续登录") {
718 | bot.login()
719 | break
720 | }
721 | }
722 | } else {
723 | send(
724 | `[${id}] 请选择设备锁验证方式\n` +
725 | `短信验证:${getTips}短信\n` +
726 | `扫码验证:扫码完成后,${getTips}继续登录\n` +
727 | data.url,
728 | )
729 | for (;;) {
730 | const msg = await get()
731 | if (msg === "短信") {
732 | bot.sendSmsCode()
733 | send(`[${id}] 短信已发送,${getTips}验证码`)
734 | bot.submitSmsCode(await get())
735 | break
736 | } else if (msg === "继续登录") {
737 | bot.login()
738 | break
739 | }
740 | }
741 | }
742 | })
743 |
744 | bot.on("system.login.auth", async data => {
745 | Bot.em("system.login.auth", data)
746 | send(`[${id}] 请完成身份验证后,${getTips}继续登录\n${data.url}`)
747 | for (;;) {
748 | if ((await get()) === "继续登录") {
749 | bot.login()
750 | break
751 | }
752 | }
753 | })
754 |
755 | bot.on("system.login.error", data => {
756 | Bot.em("system.login.error", data)
757 | send(`[${id}] 登录错误:${data.message}(${data.code})\n` + `发送 #Bot上线${id} 重新登录`)
758 | })
759 | bot.on("system.offline", data => {
760 | const i = Bot.uin.indexOf(id)
761 | if (i !== -1) Bot.uin.splice(i, 1)
762 | Bot.em("system.offline", data)
763 | send(`[${id}] 账号下线:${data.message}\n` + `发送 #Bot上线${id} 重新登录`)
764 | })
765 | bot.on("system.online", data => {
766 | Bot.em("system.online", data)
767 | bot.logger = log
768 | if (sendMsg) send(`[${id}] 登录完成`)
769 | Bot.em(`connect.${id}`, { self_id: id })
770 | })
771 |
772 | Bot[id] = new Proxy(
773 | {
774 | adapter: this,
775 | sdk: bot,
776 | icqq,
777 | avatar: bot.pickFriend(id).getAvatarUrl(),
778 | version: {
779 | id: this.id,
780 | name: this.name,
781 | version: this.version,
782 | },
783 | uploadImage: this.uploadImage.bind(this, id),
784 | uploadRecord: this.uploadRecord.bind(this, id),
785 | uploadVideo: this.uploadVideo.bind(this, id),
786 | },
787 | {
788 | get: this.getBot.bind(this, id),
789 | },
790 | )
791 | await new Promise(resolve => {
792 | bot.once("system.online", resolve)
793 | bot.login(id, password)
794 | })
795 |
796 | bot.on("message", data => {
797 | this.makeEvent(data)
798 | Bot.em(`${data.post_type}.${data.message_type}.${data.sub_type}`, data)
799 | })
800 |
801 | bot.on("notice", data => {
802 | this.makeEvent(data)
803 | Bot.em(`${data.post_type}.${data.notice_type}.${data.sub_type}`, data)
804 | })
805 |
806 | bot.on("request", data => {
807 | this.makeEvent(data)
808 | Bot.em(`${data.post_type}.${data.request_type}.${data.sub_type}`, data)
809 | })
810 |
811 | for (const i of ["internal.input", "sync"])
812 | bot.on(i, data => {
813 | data.self_id = id
814 | Bot.em(i, data)
815 | })
816 |
817 | Bot.makeLog("mark", `${this.name}(${this.id}) ${this.version} 已连接`, id)
818 | return true
819 | }
820 |
821 | async load() {
822 | for (const token of config.token) await Bot.sleep(5000, this.connect(token))
823 | }
824 | })()
825 |
826 | Bot.adapter.push(adapter)
827 |
828 | export class ICQQAdapter extends plugin {
829 | constructor() {
830 | super({
831 | name: "ICQQAdapter",
832 | dsc: "ICQQ 适配器设置",
833 | event: "message",
834 | rule: [
835 | {
836 | reg: "^#[Qq]+账号$",
837 | fnc: "List",
838 | permission: config.permission,
839 | },
840 | {
841 | reg: "^#[Qq]+设置[0-9]+",
842 | fnc: "Token",
843 | permission: config.permission,
844 | },
845 | {
846 | reg: "^#[Qq]+签名.+$",
847 | fnc: "SignUrl",
848 | permission: config.permission,
849 | },
850 | ],
851 | })
852 | }
853 |
854 | List() {
855 | this.reply(`共${config.token.length}个账号:\n${config.token.join("\n")}`, true)
856 | }
857 |
858 | async Token() {
859 | const token = this.e.msg.replace(/^#[Qq]+设置/, "").trim()
860 | if (config.token.includes(token)) {
861 | config.token = config.token.filter(item => item !== token)
862 | this.reply(`账号已删除,重启后生效,共${config.token.length}个账号`, true)
863 | } else {
864 | if (
865 | await adapter.connect(token, msg => this.reply(msg, true), Bot.getTextMsg.bind(Bot, this.e))
866 | ) {
867 | config.token.push(token)
868 | this.reply(`账号已连接,共${config.token.length}个账号`, true)
869 | } else {
870 | this.reply("账号连接失败", true)
871 | return false
872 | }
873 | }
874 | await configSave()
875 | }
876 |
877 | async SignUrl() {
878 | config.bot.sign_api_addr = this.e.msg.replace(/^#[Qq]+签名/, "").trim()
879 | await configSave()
880 | this.reply("签名已设置,重启后生效", true)
881 | }
882 | }
883 |
884 | logger.info(logger.green("- ICQQ 适配器插件 加载完成"))
885 |
--------------------------------------------------------------------------------