From 21b2bd2c8e31a63b46e89a40a2da6c83ecaa8d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=8B=E7=93=9C=E4=B8=80=E5=8D=81=E9=9B=AA?= Date: Tue, 28 May 2024 17:11:07 +0800 Subject: [PATCH 1/3] feat: cookies --- src/common/utils/request.ts | 57 ++++++++++++++++++++++++------------- src/ntqqapi/api/user.ts | 37 +++++++++--------------- 2 files changed, 51 insertions(+), 43 deletions(-) diff --git a/src/common/utils/request.ts b/src/common/utils/request.ts index 8ae463d..c5b303d 100644 --- a/src/common/utils/request.ts +++ b/src/common/utils/request.ts @@ -3,28 +3,45 @@ import http from 'node:http'; export class RequestUtil { // 适用于获取服务器下发cookies时获取,仅GET - static async HttpsGetCookies(url: string): Promise> { - return new Promise>((resolve, reject) => { - const protocol = url.startsWith('https://') ? https : http; - protocol.get(url, (res) => { - const cookiesHeader = res.headers['set-cookie']; - if (!cookiesHeader) { - resolve(new Map()); - } else { - const cookiesMap = new Map(); - cookiesHeader.forEach((cookieStr) => { - cookieStr.split(';').forEach((cookiePart) => { - const trimmedPart = cookiePart.trim(); - if (trimmedPart.includes('=')) { - const [key, value] = trimmedPart.split('=').map(part => part.trim()); - cookiesMap.set(key, decodeURIComponent(value)); // 解码cookie值 - } - }); + static async HttpsGetCookies(url: string): Promise<{ [key: string]: string }> { + const client = url.startsWith('https') ? https : http; + return new Promise((resolve, reject) => { + client.get(url, (res) => { + let cookies: { [key: string]: string } = {}; + const handleRedirect = (res: http.IncomingMessage) => { + //console.log(res.headers.location); + if (res.statusCode === 301 || res.statusCode === 302) { + if (res.headers.location) { + const redirectUrl = new URL(res.headers.location, url); + RequestUtil.HttpsGetCookies(redirectUrl.href).then((redirectCookies) => { + // 合并重定向过程中的cookies + cookies = { ...cookies, ...redirectCookies }; + resolve(cookies); + }); + } else { + resolve(cookies); + } + } else { + resolve(cookies); + } + }; + res.on('data', () => { }); // Necessary to consume the stream + res.on('end', () => { + handleRedirect(res); + }); + if (res.headers['set-cookie']) { + //console.log(res.headers['set-cookie']); + res.headers['set-cookie'].forEach((cookie) => { + const parts = cookie.split(';')[0].split('='); + const key = parts[0]; + const value = parts[1]; + if (key && value && key.length > 0 && value.length > 0) { + cookies[key] = value; + } }); - resolve(cookiesMap); } - }).on('error', (error) => { - reject(error); + }).on('error', (err) => { + reject(err); }); }); } diff --git a/src/ntqqapi/api/user.ts b/src/ntqqapi/api/user.ts index bf4bf5e..cb23f36 100644 --- a/src/ntqqapi/api/user.ts +++ b/src/ntqqapi/api/user.ts @@ -6,6 +6,7 @@ import { NTQQWindowApi, NTQQWindows } from './window' import { cacheFunc, isQQ998, log, sleep } from '../../common/utils' import { wrapperApi } from '@/ntqqapi/native/wrapper' import * as https from 'https' +import { RequestUtil } from '@/common/utils/request' let userInfoCache: Record = {} // uid: User @@ -95,7 +96,16 @@ export class NTQQUserApi { ], }) } - + static async getQzoneCookies() { + const requestUrl = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + selfInfo.uin + '&clientkey=' + this.getClientKey() + '&u1=https%3A%2F%2Fuser.qzone.qq.com%2F' + selfInfo.uin + '%2Finfocenter&keyindex=19%27' + let cookies: { [key: string]: string; } = {}; + try { + cookies = await RequestUtil.HttpsGetCookies(requestUrl); + } catch (e: any) { + cookies = {} + } + return cookies; + } static async getSkey(): Promise { const clientKeyData = await this.getClientKey() if (clientKeyData.result !== 0) { @@ -103,33 +113,14 @@ export class NTQQUserApi { } const url = 'https://ssl.ptlogin2.qq.com/jump?ptlang=1033&clientuin=' + selfInfo.uin + '&clientkey=' + clientKeyData.clientKey - + '&u1=https%3A%2F%2Fh5.qzone.qq.com%2Fqqnt%2Fqzoneinpcqq%2Ffriend%3Frefresh%3D0%26clientuin%3D0%26darkMode%3D0&keyindex=' + clientKeyData.keyIndex - - return new Promise((resolve, reject) => { - const req = https.get(url, (res) => { - const rawCookies = res.headers['set-cookie'] - const cookies = {} - rawCookies.forEach(cookie => { - // 使用正则表达式匹配 cookie 名称和值 - const regex = /([^=;]+)=([^;]*)/ - const match = regex.exec(cookie) - if (match) { - cookies[match[1].trim()] = match[2].trim() - } - }) - resolve(cookies['skey']) - }) - req.on('error', e => { - reject(e) - }); - req.end(); - }); + + '&u1=https%3A%2F%2Fh5.qzone.qq.com%2Fqqnt%2Fqzoneinpcqq%2Ffriend%3Frefresh%3D0%26clientuin%3D0%26darkMode%3D0&keyindex=' + clientKeyData.keyIndex; + return (await RequestUtil.HttpsGetCookies(url))?.skey; } @cacheFunc(60 * 30 * 1000) static async getCookies(domain: string) { const skey = await this.getSkey(); - const pskey= (await this.getPSkey([domain])).get(domain); + const pskey = (await this.getPSkey([domain])).get(domain); if (!pskey || !skey) { throw new Error('获取Cookies失败') } From 6f8ea9677fd4056995bfb8769c1142d01498105a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=8B=E7=93=9C=E4=B8=80=E5=8D=81=E9=9B=AA?= Date: Tue, 28 May 2024 17:14:24 +0800 Subject: [PATCH 2/3] feat: support qzone cookies --- src/onebot11/action/user/GetCookie.ts | 42 ++++++++++++++++----------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/onebot11/action/user/GetCookie.ts b/src/onebot11/action/user/GetCookie.ts index 63598ad..f192408 100644 --- a/src/onebot11/action/user/GetCookie.ts +++ b/src/onebot11/action/user/GetCookie.ts @@ -1,17 +1,25 @@ -import BaseAction from '../BaseAction' -import { NTQQUserApi } from '../../../ntqqapi/api' -import { groups } from '../../../common/data' -import { ActionName } from '../types' - -interface Payload { - domain: string -} - -export class GetCookies extends BaseAction { - actionName = ActionName.GetCookies - - protected async _handle(payload: Payload) { - const domain = payload.domain || 'qun.qq.com' - return NTQQUserApi.getCookies(domain); - } -} +import BaseAction from '../BaseAction' +import { NTQQUserApi, WebApi } from '../../../ntqqapi/api' +import { groups, selfInfo } from '../../../common/data' +import { ActionName } from '../types' + +interface Payload { + domain: string +} + +export class GetCookies extends BaseAction { + actionName = ActionName.GetCookies + + protected async _handle(payload: Payload) { + const domain = payload.domain || 'qun.qq.com' + if (domain.endsWith("qzone.qq.com")) { + const _Skey = await NTQQUserApi.getSkey() as string; + // 兼容整个 *.qzone.qq.com + let data = (await NTQQUserApi.getQzoneCookies()); + const Bkn = WebApi.genBkn(data.p_skey); + const CookieValue = 'p_skey=' + data.p_skey + '; skey=' + data.skey + '; p_uin=o' + selfInfo.uin + '; uin=o' + selfInfo.uin; + return { bkn: WebApi.genBkn(data.p_skey), cookies: CookieValue }; + } + return NTQQUserApi.getCookies(domain); + } +} From c459587dcd427178c84bf3e2570e8de4cfd13c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=8B=E7=93=9C=E4=B8=80=E5=8D=81=E9=9B=AA?= Date: Wed, 29 May 2024 12:03:35 +0800 Subject: [PATCH 3/3] refactor: get cookies --- src/ntqqapi/api/user.ts | 5 +++++ src/onebot11/action/user/GetCookie.ts | 8 -------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/ntqqapi/api/user.ts b/src/ntqqapi/api/user.ts index 0aab61b..a6f058b 100644 --- a/src/ntqqapi/api/user.ts +++ b/src/ntqqapi/api/user.ts @@ -122,6 +122,11 @@ export class NTQQUserApi { @cacheFunc(60 * 30 * 1000) static async getCookies(domain: string) { + if (domain.endsWith("qzone.qq.com")) { + let data = (await NTQQUserApi.getQzoneCookies()); + const CookieValue = 'p_skey=' + data.p_skey + '; skey=' + data.skey + '; p_uin=o' + selfInfo.uin + '; uin=o' + selfInfo.uin; + return { bkn: NTQQUserApi.genBkn(data.p_skey), cookies: CookieValue }; + } const skey = await this.getSkey(); const pskey = (await this.getPSkey([domain])).get(domain); if (!pskey || !skey) { diff --git a/src/onebot11/action/user/GetCookie.ts b/src/onebot11/action/user/GetCookie.ts index f192408..4b6f181 100644 --- a/src/onebot11/action/user/GetCookie.ts +++ b/src/onebot11/action/user/GetCookie.ts @@ -12,14 +12,6 @@ export class GetCookies extends BaseAction