From fa5d5f1bcc6cdc1789f4791149d341b575dc693b Mon Sep 17 00:00:00 2001 From: "Wesley F. Young" Date: Fri, 9 Aug 2024 15:14:11 +0800 Subject: [PATCH] refactor: shared logic in webapi.ts --- src/core/apis/webapi.ts | 515 ++++++++++++++++++++++------------------ 1 file changed, 279 insertions(+), 236 deletions(-) diff --git a/src/core/apis/webapi.ts b/src/core/apis/webapi.ts index 913bee2b..7ac194b4 100644 --- a/src/core/apis/webapi.ts +++ b/src/core/apis/webapi.ts @@ -1,259 +1,302 @@ import { RequestUtil } from '@/common/utils/request'; -import { InstanceContext } from '../wrapper'; +import { + GroupEssenceMsgRet, + InstanceContext, + WebApiGroupMember, + WebApiGroupMemberRet, + WebApiGroupNoticeRet, + WebHonorType, +} from '@/core'; import { NapCatCore } from '..'; -import { GroupEssenceMsgRet, WebApiGroupMember, WebApiGroupMemberRet, WebApiGroupNoticeRet, WebHonorType } from '../entities/webapi'; export class NTQQWebApi { - context: InstanceContext; - core: NapCatCore; - constructor(context: InstanceContext, core: NapCatCore) { - this.context = context; - this.core = core; - } - async shareDigest(groupCode: string, msgSeq: string, msgRandom: string, targetGroupCode: string) { - const CookiesObject = await this.core.getApiContext().UserApi.getCookies('qun.qq.com'); - const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; '); - const Bkn = this.genBkn(CookiesObject.skey); - let ret: any = undefined; - const data = 'group_code=' + groupCode + '&msg_seq=' + msgSeq + '&msg_random=' + msgRandom + '&target_group_code=' + targetGroupCode; - const url = 'https://qun.qq.com/cgi-bin/group_digest/share_digest?bkn=' + Bkn + "&" + data; - //console.log(url); - try { - ret = await RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': CookieValue }); - return ret; - } catch (e) { - return undefined; - } - return undefined; - } - async getGroupEssenceMsg(GroupCode: string, page_start: string) { - const CookiesObject = await this.core.getApiContext().UserApi.getCookies('qun.qq.com'); - const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; '); - const Bkn = this.genBkn(CookiesObject.skey); - const url = 'https://qun.qq.com/cgi-bin/group_digest/digest_list?bkn=' + Bkn + '&group_code=' + GroupCode + '&page_start=' + page_start + '&page_limit=20'; - let ret; - try { - ret = await RequestUtil.HttpGetJson(url, 'GET', '', { 'Cookie': CookieValue }); - } catch { - return undefined; - } - //console.log(url, CookieValue); - if (ret.retcode !== 0) { - return undefined; - } - return ret; - } - async getGroupMembers(GroupCode: string, cached: boolean = true): Promise { - //logDebug('webapi 获取群成员', GroupCode); - let MemberData: Array = new Array(); - try { - const CookiesObject = await this.core.getApiContext().UserApi.getCookies('qun.qq.com'); - const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; '); - const Bkn = this.genBkn(CookiesObject.skey); - const retList: Promise[] = []; - const fastRet = await RequestUtil.HttpGetJson('https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?st=0&end=40&sort=1&gc=' + GroupCode + '&bkn=' + Bkn, 'POST', '', { 'Cookie': CookieValue }); - if (!fastRet?.count || fastRet?.errcode !== 0 || !fastRet?.mems) { - return []; - } else { - for (const key in fastRet.mems) { - MemberData.push(fastRet.mems[key]); - } - } - //初始化获取PageNum - const PageNum = Math.ceil(fastRet.count / 40); - //遍历批量请求 - for (let i = 2; i <= PageNum; i++) { - const ret: Promise = RequestUtil.HttpGetJson('https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?st=' + (i - 1) * 40 + '&end=' + i * 40 + '&sort=1&gc=' + GroupCode + '&bkn=' + Bkn, 'POST', '', { 'Cookie': CookieValue }); - retList.push(ret); - } - //批量等待 - for (let i = 1; i <= PageNum; i++) { - const ret = await (retList[i]); - if (!ret?.count || ret?.errcode !== 0 || !ret?.mems) { - continue; - } - for (const key in ret.mems) { - MemberData.push(ret.mems[key]); - } - } - } catch { - return MemberData; - } - return MemberData; - } - // public async addGroupDigest(groupCode: string, msgSeq: string) { - // const url = `https://qun.qq.com/cgi-bin/group_digest/cancel_digest?random=665&X-CROSS-ORIGIN=fetch&group_code=${groupCode}&msg_seq=${msgSeq}&msg_random=444021292`; - // const res = await this.request(url); - // return await res.json(); - // } + context: InstanceContext; + core: NapCatCore; - // public async getGroupDigest(groupCode: string) { - // const url = `https://qun.qq.com/cgi-bin/group_digest/digest_list?random=665&X-CROSS-ORIGIN=fetch&group_code=${groupCode}&page_start=0&page_limit=20`; - // const res = await this.request(url); - // return await res.json(); - // } - async setGroupNotice(GroupCode: string, Content: string = '') { - //https://web.qun.qq.com/cgi-bin/announce/add_qun_notice?bkn=${bkn} - //qid=${群号}&bkn=${bkn}&text=${内容}&pinned=0&type=1&settings={"is_show_edit_card":1,"tip_window_type":1,"confirm_required":1} - - const CookiesObject = await this.core.getApiContext().UserApi.getCookies('qun.qq.com'); - const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; '); - const Bkn = this.genBkn(CookiesObject.skey); - let ret: any = undefined; - const data = 'qid=' + GroupCode + '&bkn=' + Bkn + '&text=' + Content + '&pinned=0&type=1&settings={"is_show_edit_card":1,"tip_window_type":1,"confirm_required":1}'; - const url = 'https://web.qun.qq.com/cgi-bin/announce/add_qun_notice?bkn=' + Bkn; - try { - ret = await RequestUtil.HttpGetJson(url, 'GET', '', { 'Cookie': CookieValue }); - return ret; - } catch (e) { - return undefined; + constructor(context: InstanceContext, core: NapCatCore) { + this.context = context; + this.core = core; } - return undefined; - } - async getGrouptNotice(GroupCode: string): Promise { - const CookiesObject = await this.core.getApiContext().UserApi.getCookies('qun.qq.com'); - const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; '); - const Bkn = this.genBkn(CookiesObject.skey); - let ret: WebApiGroupNoticeRet | undefined = undefined; - //console.log(CookieValue); - const url = 'https://web.qun.qq.com/cgi-bin/announce/get_t_list?bkn=' + Bkn + '&qid=' + GroupCode + '&ft=23&ni=1&n=1&i=1&log_read=1&platform=1&s=-1&n=20'; - try { - ret = await RequestUtil.HttpGetJson(url, 'GET', '', { 'Cookie': CookieValue }); - if (ret?.ec !== 0) { - return undefined; - } - return ret; - } catch (e) { - return undefined; - } - return undefined; - } - genBkn(sKey: string) { - sKey = sKey || ''; - let hash = 5381; - for (let i = 0; i < sKey.length; i++) { - const code = sKey.charCodeAt(i); - hash = hash + (hash << 5) + code; - } - - return (hash & 0x7FFFFFFF).toString(); - } - async getGroupHonorInfo(groupCode: string, getType: WebHonorType) { - const CookiesObject = await this.core.getApiContext().UserApi.getCookies('qun.qq.com'); - const CookieValue = Object.entries(CookiesObject).map(([key, value]) => `${key}=${value}`).join('; '); - const Bkn = this.genBkn(CookiesObject.skey); - const getDataInternal = async (Internal_groupCode: string, Internal_type: number) => { - let url = 'https://qun.qq.com/interactive/honorlist?gc=' + Internal_groupCode + '&type=' + Internal_type.toString(); - let res = ''; - let resJson; - try { - res = await RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': CookieValue }); - const match = res.match(/window\.__INITIAL_STATE__=(.*?);/); - if (match) { - resJson = JSON.parse(match[1].trim()); + async shareDigest(groupCode: string, msgSeq: string, msgRandom: string, targetGroupCode: string) { + const cookieObject = await this.core.getApiContext().UserApi.getCookies('qun.qq.com'); + const url = `https://qun.qq.com/cgi-bin/group_digest/share_digest?${ + new URLSearchParams({ + bkn: this.getBknFromCookie(cookieObject), + group_code: groupCode, + msg_seq: msgSeq, + msg_random: msgRandom, + target_group_code: targetGroupCode, + }).toString() + }`; + try { + return RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) }); + } catch (e) { + return undefined; } - if (Internal_type === 1) { - return resJson?.talkativeList; + } + + async getGroupEssenceMsg(GroupCode: string, page_start: string) { + const cookieObject = await this.core.getApiContext().UserApi.getCookies('qun.qq.com'); + const url = `https://qun.qq.com/cgi-bin/group_digest/digest_list?${ + new URLSearchParams({ + bkn: this.getBknFromCookie(cookieObject), + group_code: GroupCode, + page_start, + page_limit: '20', + }).toString() + }`; + let ret; + try { + ret = await RequestUtil.HttpGetJson + (url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) }); + } catch { + return undefined; + } + if (ret.retcode !== 0) { + return undefined; + } + return ret; + } + + async getGroupMembers(GroupCode: string, cached: boolean = true): Promise { + //logDebug('webapi 获取群成员', GroupCode); + const memberData: Array = new Array(); + const cookieObject = await this.core.getApiContext().UserApi.getCookies('qun.qq.com'); + const retList: Promise[] = []; + const fastRet = await RequestUtil.HttpGetJson + (`https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?${ + new URLSearchParams({ + st: '0', + end: '40', + sort: '1', + gc: GroupCode, + bkn: this.getBknFromCookie(cookieObject) + }).toString() + }`, 'POST', '', { 'Cookie': this.cookieToString(cookieObject) }); + if (!fastRet?.count || fastRet?.errcode !== 0 || !fastRet?.mems) { + return []; } else { - return resJson?.actorList; + for (const key in fastRet.mems) { + memberData.push(fastRet.mems[key]); + } } - } catch (e) { - this.context.logger.logDebug('获取当前群荣耀失败', url, e); - } - return undefined; + //初始化获取PageNum + const PageNum = Math.ceil(fastRet.count / 40); + //遍历批量请求 + for (let i = 2; i <= PageNum; i++) { + const ret = RequestUtil.HttpGetJson + (`https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?${ + new URLSearchParams({ + st: ((i - 1) * 40).toString(), + end: (i * 40).toString(), + sort: '1', + gc: GroupCode, + bkn: this.getBknFromCookie(cookieObject) + }).toString() + }`, 'POST', '', { 'Cookie': this.cookieToString(cookieObject) }); + retList.push(ret); + } + //批量等待 + for (let i = 1; i <= PageNum; i++) { + const ret = await (retList[i]); + if (!ret?.count || ret?.errcode !== 0 || !ret?.mems) { + continue; + } + for (const key in ret.mems) { + memberData.push(ret.mems[key]); + } + } + return memberData; } - const HonorInfo: any = { group_id: groupCode }; + // public async addGroupDigest(groupCode: string, msgSeq: string) { + // const url = `https://qun.qq.com/cgi-bin/group_digest/cancel_digest?random=665&X-CROSS-ORIGIN=fetch&group_code=${groupCode}&msg_seq=${msgSeq}&msg_random=444021292`; + // const res = await this.request(url); + // return await res.json(); + // } - if (getType === WebHonorType.TALKACTIVE || getType === WebHonorType.ALL) { - try { - let RetInternal = await getDataInternal(groupCode, 1); - if (!RetInternal) { - throw new Error('获取龙王信息失败'); + // public async getGroupDigest(groupCode: string) { + // const url = `https://qun.qq.com/cgi-bin/group_digest/digest_list?random=665&X-CROSS-ORIGIN=fetch&group_code=${groupCode}&page_start=0&page_limit=20`; + // const res = await this.request(url); + // return await res.json(); + // } + + async setGroupNotice(GroupCode: string, Content: string) { + const cookieObject = await this.core.getApiContext().UserApi.getCookies('qun.qq.com'); + let ret: any = undefined; + try { + ret = await RequestUtil.HttpGetJson + (`https://web.qun.qq.com/cgi-bin/announce/add_qun_notice${ + new URLSearchParams({ + bkn: this.getBknFromCookie(cookieObject), + qid: GroupCode, + text: Content, + pinned: '0', + type: '1', + settings: '{"is_show_edit_card":1,"tip_window_type":1,"confirm_required":1}', + }).toString() + }`, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) }); + return ret; + } catch (e) { + return undefined; } - HonorInfo.current_talkative = { - user_id: RetInternal[0]?.uin, - avatar: RetInternal[0]?.avatar, - nickname: RetInternal[0]?.name, - day_count: 0, - description: RetInternal[0]?.desc - } - HonorInfo.talkative_list = []; - for (const talkative_ele of RetInternal) { - HonorInfo.talkative_list.push({ - user_id: talkative_ele?.uin, - avatar: talkative_ele?.avatar, - description: talkative_ele?.desc, - day_count: 0, - nickname: talkative_ele?.name - }); - } - } catch (e) { - this.context.logger.logDebug(e); - } } - if (getType === WebHonorType.PERFROMER || getType === WebHonorType.ALL) { - try { - let RetInternal = await getDataInternal(groupCode, 2); - if (!RetInternal) { - throw new Error('获取群聊之火失败'); + + async getGroupNotice(GroupCode: string): Promise { + const cookieObject = await this.core.getApiContext().UserApi.getCookies('qun.qq.com'); + let ret: WebApiGroupNoticeRet | undefined = undefined; + try { + ret = await RequestUtil.HttpGetJson(`https://web.qun.qq.com/cgi-bin/announce/get_t_list?${ + new URLSearchParams({ + bkn: this.getBknFromCookie(cookieObject), + qid: GroupCode, + type: '1', + start: '0', + num: '1', + }).toString() + }`, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) }); + if (ret?.ec !== 0) { + return undefined; + } + return ret; + } catch (e) { + return undefined; } - HonorInfo.performer_list = []; - for (const performer_ele of RetInternal) { - HonorInfo.performer_list.push({ - user_id: performer_ele?.uin, - nickname: performer_ele?.name, - avatar: performer_ele?.avatar, - description: performer_ele?.desc - }); - } - } catch (e) { - this.context.logger.logDebug(e); - } } - if (getType === WebHonorType.PERFROMER || getType === WebHonorType.ALL) { - try { - let RetInternal = await getDataInternal(groupCode, 3); - if (!RetInternal) { - throw new Error('获取群聊炽焰失败'); + + async getGroupHonorInfo(groupCode: string, getType: WebHonorType) { + const cookieObject = await this.core.getApiContext().UserApi.getCookies('qun.qq.com'); + const getDataInternal = async (Internal_groupCode: string, Internal_type: number) => { + const url = `https://qun.qq.com/interactive/honorlist?${ + new URLSearchParams({ + gc: Internal_groupCode, + type: Internal_type.toString(), + }).toString() + }`; + let resJson; + try { + const res = await RequestUtil.HttpGetText(url, 'GET', '', { 'Cookie': this.cookieToString(cookieObject) }); + const match = res.match(/window\.__INITIAL_STATE__=(.*?);/); + if (match) { + resJson = JSON.parse(match[1].trim()); + } + if (Internal_type === 1) { + return resJson?.talkativeList; + } else { + return resJson?.actorList; + } + } catch (e) { + this.context.logger.logDebug('获取当前群荣耀失败', url, e); + } + return undefined; + }; + + const HonorInfo: any = { group_id: groupCode }; + + if (getType === WebHonorType.TALKACTIVE || getType === WebHonorType.ALL) { + try { + const RetInternal = await getDataInternal(groupCode, 1); + if (!RetInternal) { + throw new Error('获取龙王信息失败'); + } + HonorInfo.current_talkative = { + user_id: RetInternal[0]?.uin, + avatar: RetInternal[0]?.avatar, + nickname: RetInternal[0]?.name, + day_count: 0, + description: RetInternal[0]?.desc, + }; + HonorInfo.talkative_list = []; + for (const talkative_ele of RetInternal) { + HonorInfo.talkative_list.push({ + user_id: talkative_ele?.uin, + avatar: talkative_ele?.avatar, + description: talkative_ele?.desc, + day_count: 0, + nickname: talkative_ele?.name, + }); + } + } catch (e) { + this.context.logger.logDebug(e); + } } - HonorInfo.legend_list = []; - for (const legend_ele of RetInternal) { - HonorInfo.legend_list.push({ - user_id: legend_ele?.uin, - nickname: legend_ele?.name, - avatar: legend_ele?.avatar, - desc: legend_ele?.description - }); + if (getType === WebHonorType.PERFROMER || getType === WebHonorType.ALL) { + try { + const RetInternal = await getDataInternal(groupCode, 2); + if (!RetInternal) { + throw new Error('获取群聊之火失败'); + } + HonorInfo.performer_list = []; + for (const performer_ele of RetInternal) { + HonorInfo.performer_list.push({ + user_id: performer_ele?.uin, + nickname: performer_ele?.name, + avatar: performer_ele?.avatar, + description: performer_ele?.desc, + }); + } + } catch (e) { + this.context.logger.logDebug(e); + } } - } catch (e) { - this.context.logger.logDebug('获取群聊炽焰失败', e); - } + if (getType === WebHonorType.PERFROMER || getType === WebHonorType.ALL) { + try { + const RetInternal = await getDataInternal(groupCode, 3); + if (!RetInternal) { + throw new Error('获取群聊炽焰失败'); + } + HonorInfo.legend_list = []; + for (const legend_ele of RetInternal) { + HonorInfo.legend_list.push({ + user_id: legend_ele?.uin, + nickname: legend_ele?.name, + avatar: legend_ele?.avatar, + desc: legend_ele?.description, + }); + } + } catch (e) { + this.context.logger.logDebug('获取群聊炽焰失败', e); + } + } + if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) { + try { + const RetInternal = await getDataInternal(groupCode, 6); + if (!RetInternal) { + throw new Error('获取快乐源泉失败'); + } + HonorInfo.emotion_list = []; + for (const emotion_ele of RetInternal) { + HonorInfo.emotion_list.push({ + user_id: emotion_ele.uin, + nickname: emotion_ele.name, + avatar: emotion_ele.avatar, + desc: emotion_ele.description, + }); + } + } catch (e) { + this.context.logger.logDebug('获取快乐源泉失败', e); + } + } + //冒尖小春笋好像已经被tx扬了 + if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) { + HonorInfo.strong_newbie_list = []; + } + return HonorInfo; } - if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) { - try { - let RetInternal = await getDataInternal(groupCode, 6); - if (!RetInternal) { - throw new Error('获取快乐源泉失败'); - } - HonorInfo.emotion_list = []; - for (const emotion_ele of RetInternal) { - HonorInfo.emotion_list.push({ - user_id: emotion_ele?.uin, - nickname: emotion_ele?.name, - avatar: emotion_ele?.avatar, - desc: emotion_ele?.description - }); - } - } catch (e) { - this.context.logger.logDebug('获取快乐源泉失败', e); - } + + private cookieToString(cookieObject: any) { + return Object.entries(cookieObject).map(([key, value]) => `${key}=${value}`).join('; '); } - //冒尖小春笋好像已经被tx扬了 - if (getType === WebHonorType.EMOTION || getType === WebHonorType.ALL) { - HonorInfo.strong_newbie_list = []; + + private getBknFromCookie(cookieObject: any) { + const sKey = cookieObject.skey as string; + + let hash = 5381; + for (let i = 0; i < sKey.length; i++) { + const code = sKey.charCodeAt(i); + hash = hash + (hash << 5) + code; + } + return (hash & 0x7FFFFFFF).toString(); } - return HonorInfo; - } }