generated from tailored/router-template
add db module
This commit is contained in:
parent
ee483aa87e
commit
c2a0623482
27446
packages/xhs-core/docs/core.js
Normal file
27446
packages/xhs-core/docs/core.js
Normal file
File diff suppressed because it is too large
Load Diff
17
packages/xhs-core/docs/x-common.md
Normal file
17
packages/xhs-core/docs/x-common.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
```js
|
||||||
|
{
|
||||||
|
"s0": 5, // 平台代码(如5代表PC端)
|
||||||
|
"s1": "", // 预留字段 目前为空值
|
||||||
|
"x0": "1", // RC4密钥版本号
|
||||||
|
"x1": "4.1.0", // 算法版本号
|
||||||
|
"x2": "Windows", // 操作系统类型
|
||||||
|
"x3": "xhs-pc-web", // 应用标识
|
||||||
|
"x4": "4.62.3", // 客户端版本号
|
||||||
|
"x5": "1961ae22425vlf2zbnuz0fzj06s9hml658rk8mt7d50000872854", // cookie中a1 的值
|
||||||
|
"x6": 1744612488534, // x-t参数值
|
||||||
|
"x7":"XYW_eyJzaWduU3ZuIjoiNTYiLCJzaWduVHlwZSI6IngyIiwiYXBwSWQiOiJ4aHMtcGMtd2ViIiwic2lnblZlcnNpb24iOiIxIiwicGF5bG9hZCI6ImNhYmNiZTYwZTA2ZjE0MWU3ZWNjN2E2ODNkOGNhNDlmZjFiMDMxODdhYjU4MjUyN2I5MWU4NjYzNDBhZmQ0N2NiZGI5MzY4N2YzNDBhMjVkYzE3MGEzMmY5MGFkN2Q0YzUwOThmOGQ2YTAyMjY0NDQ2ODY5YjM1MTJlZjZlZWE3MzRhZGVkNDNkMDAyMzY0ZDBlODgxNmFhMWMwYjIyMmNiNWU4ZGM5Y2ZhZDUyODAzNGQ0MTYyNDA2NWNmZjQ5YzY2OWNkMzUwNDJlYzhjYmFmNTlkNGNlMDU5M2EyNTVhMzU5NTZkZmU0MWJjYjUzMjc3MTc5YWEwNGI1NDhjMjQ2MzJhODgxMWUyMGQyMDA5MDM0MjMzOTkxMWVjOWQ2NzYwZGZiOTlmYzY3N2VjMTA4YmZkOGZhYTI3OTc5NWM5MjEwOTA4MTk5YWYzZjJlODE1NGY2MDYzOTk3MDNmMjI3ZmRiZTk0ZDE5NjUxZjFkNjZjMTBlMDdlN2NiYjU4NjExMzc1OTk5Zjc4ZmY0MWFkZGFmYzQwMDIwMmFkNWUxIn0=",// X-s参数值
|
||||||
|
"x8": "I38rHdgsjopgIvesdVwgIC+oIELmBZ5e3VwXLgFTIxS3bqwErFeexd0ekncAzMFYnqthIhJeSnMDKutRI3KsYorWHPtGrbV0P9WfIi/eWc6eYqtyQApPI37ekmR6QL+5Ii6sdneeSfqYHqwl2qt5B0DBIx+PGDi/sVtkIxdsxuwr4qtiIhuaIE3e3LV0I3VTIC7e0utl2ADmsLveDSKsSPw5IEvsiVtJOqw8BuwfPpdeTFWOIx4TIiu6ZPwrPut5IvlaLbgs3qtxIxes1VwHIkumIkIyejgsY/WTge7eSqte/D7sDcpipedeYrDtIC6eDVw2IENsSqtlnlSuNjVtIx5e1qt3bmAeVn8LIESzIESJ+9DUIvzy4I8OIic7ZPwFIviC4o/sDLds6PwVIC7eSd7sf0k4IEve6WGMtVwUIids3s/sxZNeiVtbcUeeYVwCIvTnc06efuwALnOsSuwoIxltIxZSouwOgVwpsoTHPW5ef7NekuwcIEosSgoe1LuMIiNeWL0sxdh5IiJsxPw9IhR9JPwJPutWIv3e1Vt1IiNs1qw5IEKsdVtANqwJsVwXIvq5IxVn8fWRKWoe3qtFIhh2IiNeSPwzblQzn0JsWU4xIiZe4utbZPwRIvvexqtYPpdeVYdsTLYeIhNskdesiqtppuw+IvJeSPwvIieeV0DeIvOedfKeSPtUIx3s6qwV4B8qIkWJIvvsxFOekaKsDYeeSqwoIkpgIEpYzPwqIxGSIE7eirqSwnvs0VtZIhpBbut14lNedM0eYPwpmPwZIvmxIkzZpuwyqPt4Iv5sTeKsVPterVtqIiFwLPwkIvGCwcDWIxdsVb6s1LKeSVwDsqtFI3hxIi7sSqteICNeTg4BIE+0Hs+MIhSvIEAeSPwKGutToVteIkh2ICAsSl0eDqwZJDPnIhL1gVtFOPt1IiqJIikCIxQmIv/edB0sdnbesuw5IhL8yuwFOqwrIC/eWFIpIxqHJBJeiPtZQqtf+jh0tLPzI3baJuwRIxOsYjEYI3QUwuwBIxkCbPtBPVtlICPqICzNIEYMtqwnI3uEIv/sdPwGNjlcIvZVIh6siMJsSuw/IhTpICLb20hoIhbrJ0F4ICOsVnNeTqwuIv3sfPtXICr1IEOsVuwvIEbltqwJIhOsSUL6JVtHBVtfIE7eTVt0Iv7sTg42IvKsTfAsjutfrcNs0VwDQg6sYVtMIkNsWAJejqtUIvDmIxT7QqwMreYRIiJe1PwXNmNejUmNQVt7IiTTIxKsTe+AIkKeiPt3IEZ9IC5ejBYHICWMIxWMzfmFIEOekeqsIvk4IiWwIEosVckEeVt9JutS+eAeVdJs1qtaIh7eDB0ejqwiPqtiIkETyPtO2uw3BVtgguwerVt4oIds0desWcKeffKsSPtdIvMTI3cGIhurIE0sWYJsVbHmoqtkIvFrbc==", // 浏览器环境信息(localStorage中的MINI_BROSWER_INFO_KEY)
|
||||||
|
"x9": -1854331133,//对(x6+x7+x8)的加密结果(如RC4或AES)
|
||||||
|
"x10": 22 // 签名计数,可以写死
|
||||||
|
}
|
||||||
|
```
|
@ -57,6 +57,10 @@ class XhsClient {
|
|||||||
if (cookie) {
|
if (cookie) {
|
||||||
this.cookie = cookie;
|
this.cookie = cookie;
|
||||||
}
|
}
|
||||||
|
this.axiosInstance.interceptors.request.use((config) => {
|
||||||
|
this.printResult('request', config);
|
||||||
|
return config;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @params {*} args
|
* @params {*} args
|
||||||
@ -79,7 +83,16 @@ class XhsClient {
|
|||||||
const cookieStr = this.axiosInstance.defaults.headers.Cookie;
|
const cookieStr = this.axiosInstance.defaults.headers.Cookie;
|
||||||
return cookieStr ? qs.parse(cookieStr.replace(/; /g, '&')) : {};
|
return cookieStr ? qs.parse(cookieStr.replace(/; /g, '&')) : {};
|
||||||
}
|
}
|
||||||
|
getAgentHeader(config) {
|
||||||
|
const headers = config?.headers || {};
|
||||||
|
const newHeaders = {
|
||||||
|
'user-agent': this.userAgent,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
...headers,
|
||||||
|
};
|
||||||
|
config.headers = newHeaders;
|
||||||
|
return config;
|
||||||
|
}
|
||||||
_preHeaders(url, data = null) {
|
_preHeaders(url, data = null) {
|
||||||
let a1 = this.cookieDict.a1;
|
let a1 = this.cookieDict.a1;
|
||||||
let b1 = '';
|
let b1 = '';
|
||||||
@ -91,10 +104,13 @@ class XhsClient {
|
|||||||
headers: {
|
headers: {
|
||||||
'x-s': X_S,
|
'x-s': X_S,
|
||||||
'x-t': X_t,
|
'x-t': X_t,
|
||||||
'xs-common': X_S_COMMON,
|
// 'x-s-common': X_S_COMMON,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
getXCommon(a1, b1, x_s, x_t) {
|
||||||
|
return getXCommon(a1, b1 || '', x_s, String(x_t));
|
||||||
|
}
|
||||||
getCookieMap() {
|
getCookieMap() {
|
||||||
const cookie = this.cookie;
|
const cookie = this.cookie;
|
||||||
let cookieDict = {};
|
let cookieDict = {};
|
||||||
@ -127,8 +143,19 @@ class XhsClient {
|
|||||||
try {
|
try {
|
||||||
delete config.sign;
|
delete config.sign;
|
||||||
const requestOptions = { method, url, ...config };
|
const requestOptions = { method, url, ...config };
|
||||||
this.printResult('request', requestOptions);
|
// const newConfig = this.getAgentHeader(requestOptions);
|
||||||
const response = await this.axiosInstance(requestOptions);
|
const newConfig = requestOptions;
|
||||||
|
const response = await this.axiosInstance(newConfig).catch((error) => {
|
||||||
|
console.error('Error in request:', error?.status);
|
||||||
|
return {
|
||||||
|
code: error.status,
|
||||||
|
status: error.status,
|
||||||
|
msg: '请求失败',
|
||||||
|
data: null,
|
||||||
|
error: error,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
console.log('response', response.status);
|
||||||
if (!response.data) return response;
|
if (!response.data) return response;
|
||||||
if (response.status === 471 || response.status === 461) {
|
if (response.status === 471 || response.status === 461) {
|
||||||
const verifyType = response.headers['verifytype'];
|
const verifyType = response.headers['verifytype'];
|
||||||
@ -136,20 +163,12 @@ class XhsClient {
|
|||||||
throw new NeedVerifyError(`出现验证码,请求失败,Verifytype: ${verifyType},Verifyuuid: ${verifyUuid}`, response, verifyType, verifyUuid);
|
throw new NeedVerifyError(`出现验证码,请求失败,Verifytype: ${verifyType},Verifyuuid: ${verifyUuid}`, response, verifyType, verifyUuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = response.data;
|
const data = response?.data;
|
||||||
this.printResult('reponse', {
|
this.printResult('reponse', {
|
||||||
url: url,
|
url: url,
|
||||||
response,
|
response,
|
||||||
});
|
});
|
||||||
if (data.success) {
|
|
||||||
return data;
|
return data;
|
||||||
} else if (data.code === ErrorEnum.IP_BLOCK.code) {
|
|
||||||
throw new IPBlockError(ErrorEnum.IP_BLOCK.msg, response);
|
|
||||||
} else if (data.code === ErrorEnum.SIGN_FAULT.code) {
|
|
||||||
throw new SignError(ErrorEnum.SIGN_FAULT.msg, response);
|
|
||||||
} else {
|
|
||||||
throw new DataFetchError(data, response);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.response && (error.response.status === 471 || error.response.status) === 461) {
|
if (error.response && (error.response.status === 471 || error.response.status) === 461) {
|
||||||
// Handle verification error
|
// Handle verification error
|
||||||
@ -157,9 +176,51 @@ class XhsClient {
|
|||||||
const verifyUuid = error.response.headers['verifyuuid'];
|
const verifyUuid = error.response.headers['verifyuuid'];
|
||||||
throw new NeedVerifyError(`出现验证码,请求失败,Verifytype: ${verifyType},Verifyuuid: ${verifyUuid}`, error.response, verifyType, verifyUuid);
|
throw new NeedVerifyError(`出现验证码,请求失败,Verifytype: ${verifyType},Verifyuuid: ${verifyUuid}`, error.response, verifyType, verifyUuid);
|
||||||
}
|
}
|
||||||
throw error;
|
console.error('Error in request:', error);
|
||||||
|
return {
|
||||||
|
code: 500,
|
||||||
|
msg: '请求失败',
|
||||||
|
data: null,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* GET的请求 data必须为null
|
||||||
|
* @param {*} uri
|
||||||
|
* @param {*} data
|
||||||
|
* @param {*} config
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async requestSign(uri, data = null, config = {}) {
|
||||||
|
const header = config.headers || {};
|
||||||
|
const xs = header['x-s'];
|
||||||
|
const needSign = config.needSign ?? true;
|
||||||
|
if (needSign && config.sign && !xs) {
|
||||||
|
await config.sign(uri, data, config);
|
||||||
|
}
|
||||||
|
// else if (needSign && !xs) {
|
||||||
|
// const { headers } = this._preHeaders(uri, data);
|
||||||
|
// config = { ...config, headers: { ...config.headers, ...headers } };
|
||||||
|
// }
|
||||||
|
delete config.sign;
|
||||||
|
delete config.needSign;
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
getEndpoint(config) {
|
||||||
|
let endpoint = this._host;
|
||||||
|
let isCreator = config?.isCreator ?? false;
|
||||||
|
let isCustomer = config?.isCustomer ?? false;
|
||||||
|
if (isCustomer) {
|
||||||
|
endpoint = this._customerHost;
|
||||||
|
} else if (isCreator) {
|
||||||
|
endpoint = this._creatorHost;
|
||||||
|
}
|
||||||
|
delete config.isCreator;
|
||||||
|
delete config.isCustomer;
|
||||||
|
|
||||||
|
return { endpoint, isCreator, isCustomer };
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {*} uri
|
* @param {*} uri
|
||||||
@ -168,6 +229,7 @@ class XhsClient {
|
|||||||
* @param {*} [config.sign] - Whether to sign the request
|
* @param {*} [config.sign] - Whether to sign the request
|
||||||
* @param {boolean} [config.isCreator] - Whether the request is for a creator
|
* @param {boolean} [config.isCreator] - Whether the request is for a creator
|
||||||
* @param {boolean} [config.isCustomer] - Whether the request is for a customer
|
* @param {boolean} [config.isCustomer] - Whether the request is for a customer
|
||||||
|
* @param {boolean} [config.needSign] - 是否需要 sign
|
||||||
* @param {*} [config.headers] - XSEC token for authentication
|
* @param {*} [config.headers] - XSEC token for authentication
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
@ -175,22 +237,10 @@ class XhsClient {
|
|||||||
if (params) {
|
if (params) {
|
||||||
uri = `${uri}?${qs.stringify(params)}`;
|
uri = `${uri}?${qs.stringify(params)}`;
|
||||||
}
|
}
|
||||||
const header = config.headers || {};
|
this.printResult('get', { uri, params, config });
|
||||||
const xs = header['x-s'];
|
const endpoint = this.getEndpoint(config).endpoint;
|
||||||
if (config.sign && !xs) {
|
config = await this.requestSign(uri, null, config);
|
||||||
await config.sign(uri, null, config);
|
|
||||||
} else if (!xs) {
|
|
||||||
const { headers } = this._preHeaders(uri, null);
|
|
||||||
config = { ...config, headers: { ...config.headers, ...headers } };
|
|
||||||
}
|
|
||||||
let isCreator = config?.isCreator ?? false;
|
|
||||||
let isCustomer = config?.isCustomer ?? false;
|
|
||||||
let endpoint = this._host;
|
|
||||||
if (isCustomer) {
|
|
||||||
endpoint = this._customerHost;
|
|
||||||
} else if (isCreator) {
|
|
||||||
endpoint = this._creatorHost;
|
|
||||||
}
|
|
||||||
return this.request('GET', `${endpoint}${uri}`, config);
|
return this.request('GET', `${endpoint}${uri}`, config);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -201,27 +251,15 @@ class XhsClient {
|
|||||||
* @param {*} [config.sign] - Whether to sign the request
|
* @param {*} [config.sign] - Whether to sign the request
|
||||||
* @param {boolean} [config.isCreator] - Whether the request is for a creator
|
* @param {boolean} [config.isCreator] - Whether the request is for a creator
|
||||||
* @param {boolean} [config.isCustomer] - Whether the request is for a customer
|
* @param {boolean} [config.isCustomer] - Whether the request is for a customer
|
||||||
|
* @param {boolean} [config.needSign] - 是否需要 sign
|
||||||
* @param {*} [config.headers] - XSEC token for authentication
|
* @param {*} [config.headers] - XSEC token for authentication
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async post(uri, data = null, config = {}) {
|
async post(uri, data = null, config = {}) {
|
||||||
let jsonStr = data ? JSON.stringify(data) : null;
|
let jsonStr = data ? JSON.stringify(data) : null;
|
||||||
let endpoint = this._host;
|
const endpoint = this.getEndpoint(config).endpoint;
|
||||||
const header = config.headers || {};
|
config = await this.requestSign(uri, data, config);
|
||||||
const xs = header['x-s'];
|
this.printResult('post', { uri, data, config });
|
||||||
if (config.sign && !xs) {
|
|
||||||
await config.sign(uri, data, config);
|
|
||||||
} else if (!xs) {
|
|
||||||
const { headers } = this._preHeaders(uri, data);
|
|
||||||
config = { ...config, headers: { ...config.headers, ...headers } };
|
|
||||||
}
|
|
||||||
let isCreator = config?.isCreator ?? false;
|
|
||||||
let isCustomer = config?.isCustomer ?? false;
|
|
||||||
if (isCustomer) {
|
|
||||||
endpoint = this._customerHost;
|
|
||||||
} else if (isCreator) {
|
|
||||||
endpoint = this._creatorHost;
|
|
||||||
}
|
|
||||||
if (data) {
|
if (data) {
|
||||||
return this.request('POST', `${endpoint}${uri}`, {
|
return this.request('POST', `${endpoint}${uri}`, {
|
||||||
...config,
|
...config,
|
||||||
|
1
packages/xhs/.gitignore
vendored
Normal file
1
packages/xhs/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
db-sqlite
|
@ -24,5 +24,10 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@kevisual/xhs-core": "workspace:*",
|
"@kevisual/xhs-core": "workspace:*",
|
||||||
"@types/node": "^22.15.3"
|
"@types/node": "^22.15.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"nanoid": "^5.1.5",
|
||||||
|
"sequelize": "^6.37.7",
|
||||||
|
"sqlite3": "^5.1.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,9 +3,13 @@ import { XhsServices } from '@/services/xhs-services.ts';
|
|||||||
|
|
||||||
export const app = new QueryRouterServer();
|
export const app = new QueryRouterServer();
|
||||||
export const xhsServices = new XhsServices();
|
export const xhsServices = new XhsServices();
|
||||||
export const cookie =
|
const cookie =
|
||||||
'a1=1968ba02ff4xrt6hfrzdiz7ubs82j9y3vx11vfw9c40000317680;abRequestId=0a794332-4561-5f49-93f7-780b8b028e1f;access-token-creator.xiaohongshu.com=customer.creator.AT-68c517498636784561614544frjvxzj7yu8iewie;agora_session=6a0031373435393132333637323735343733393437313634000000000000;customerClientId=536706778174172;galaxy_creator_session_id=OhpHDDSoADhNEhnH5LLnQpletFLApu1fd91f;galaxy.creator.beaker.session.id=1745912429847011598150;gid=yjKqYfK0qDyYyj2DDSqd4ujxyW9kvxIuT62ddkMWhElyuxq8yDd6hl888q2WYy88j8i80yYD;loadts=1746020512562;sec_poison_id=441c932e-a6ac-4d8d-97ae-beb14adb1929;unread={%22ub%22:%2267eaf1fe000000001202c3ea%22%2C%22ue%22:%226803aa37000000001c0319d8%22%2C%22uc%22:35};web_session=040069b2e9c511ca302086ca253a4bde8b1cd1;webBuild=4.62.3;webId=97e5f097499594cad49aa0bd1a8ed83f;websectiga=3633fe24d49c7dd0eb923edc8205740f10fdb18b25d424d2a2322c6196d2a4ad;x-user-id-creator.xiaohongshu.com=639d86590000000026006076;xsecappid=xhs-pc-web;acw_tc=0a00df6217460205042195762e721fba339a0dbe8e4738b961a5ff15e74619;';
|
'a1=1969088bf22oidhober22hsb74h3qoavpucdvmrbb30000712484;abRequestId=e1b9d999-8838-528a-9933-5f3ac9134d8c;gid=yjKj8YYdSSUqyjKj8YYDi76FJJl3fxlDdFJJSDDxMDW4xfq8qAl0hh888WyJ4Y48ySjjfKfd;loadts=1746193349304;sec_poison_id=74e35006-555a-47a5-a11b-7d4a2482b933;unread={%22ub%22:%2268077ca2000000001b03bff6%22%2C%22ue%22:%22680e491b000000000b015506%22%2C%22uc%22:30};web_session=040069b2e9c511ca302098d5213a4b8556ed1d;webBuild=4.62.3;webId=bffbeec4c301c7b3dc284ee35dd742fb;websectiga=cffd9dcea65962b05ab048ac76962acee933d26157113bb213105a116241fa6c;xsecappid=xhs-pc-web;acw_tc=0a00d5b517461933472156520e55fc213ae73b04699cd042b86f1525ccab06;';
|
||||||
|
|
||||||
xhsServices.createRoot({
|
xhsServices.createRoot({
|
||||||
cookie,
|
cookie,
|
||||||
|
signConfig: {
|
||||||
|
signUrl: 'http://light.xiongxiao.me:5006/sign',
|
||||||
|
// signUrl: 'http://localhost:5006/sign',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
71
packages/xhs/src/libs/user-agent/list.ts
Normal file
71
packages/xhs/src/libs/user-agent/list.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
export const list = [
|
||||||
|
{
|
||||||
|
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1',
|
||||||
|
},
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Mobile Safari/537.36' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; Android 10; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Mobile Safari/537.36' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (iPad; CPU OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.77 Mobile/15E148 Safari/604.1' },
|
||||||
|
{
|
||||||
|
'user-agent':
|
||||||
|
'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36',
|
||||||
|
},
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.188 Safari/537.36 CrKey/1.54.250320' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Safari/537.36' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true' },
|
||||||
|
{
|
||||||
|
'user-agent':
|
||||||
|
'Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/102.0.0.0 Mobile Safari/537.36',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'user-agent':
|
||||||
|
'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/14.14263',
|
||||||
|
},
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; Android 6.0.1; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36' },
|
||||||
|
{
|
||||||
|
'user-agent':
|
||||||
|
'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36',
|
||||||
|
},
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36' },
|
||||||
|
{
|
||||||
|
'user-agent':
|
||||||
|
'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36',
|
||||||
|
},
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 520)' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13' },
|
||||||
|
{
|
||||||
|
'user-agent':
|
||||||
|
'Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.158 Mobile Safari/537.36',
|
||||||
|
},
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; Android 11; Pixel 3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36' },
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36' },
|
||||||
|
{
|
||||||
|
'user-agent':
|
||||||
|
'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'user-agent':
|
||||||
|
'Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36',
|
||||||
|
},
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1' },
|
||||||
|
{
|
||||||
|
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1',
|
||||||
|
},
|
||||||
|
{ 'user-agent': 'Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1' },
|
||||||
|
];
|
||||||
|
export const randomUserAgent = () => {
|
||||||
|
const randomIndex = Math.floor(Math.random() * list.length);
|
||||||
|
return list[randomIndex]['user-agent'];
|
||||||
|
};
|
50
packages/xhs/src/libs/xhs-api/api.ts
Normal file
50
packages/xhs/src/libs/xhs-api/api.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
type ApiInfo = {
|
||||||
|
uri: string;
|
||||||
|
method?: 'GET' | 'POST';
|
||||||
|
needSign?: boolean;
|
||||||
|
description?: string;
|
||||||
|
isCreator?: boolean;
|
||||||
|
};
|
||||||
|
export const api: ApiInfo[] = [
|
||||||
|
{
|
||||||
|
uri: '/api/sns/web/v1/you/mentions',
|
||||||
|
method: 'GET',
|
||||||
|
description: '获取@我的消息',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uri: '/api/sns/web/v1/you/likes',
|
||||||
|
method: 'GET',
|
||||||
|
description: '获取点赞的消息',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uri: '/api/sns/web/v1/you/connections',
|
||||||
|
method: 'GET',
|
||||||
|
description: '获取关注的消息',
|
||||||
|
needSign: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uri: '/api/sns/web/v1/you/mentions',
|
||||||
|
method: 'GET',
|
||||||
|
needSign: true,
|
||||||
|
description: '获取@我的消息',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
type ReturnApiInfo = {
|
||||||
|
apiInfo: ApiInfo;
|
||||||
|
needSign: boolean;
|
||||||
|
};
|
||||||
|
export const getApiInfo = (uri: string): ReturnApiInfo | null => {
|
||||||
|
const apiInfo = api.find((item) => item.uri?.startsWith(uri));
|
||||||
|
if (apiInfo) {
|
||||||
|
return {
|
||||||
|
apiInfo,
|
||||||
|
needSign: apiInfo.needSign ?? true,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
apiInfo: null,
|
||||||
|
needSign: true,
|
||||||
|
};
|
||||||
|
};
|
@ -1,3 +1,4 @@
|
|||||||
|
import { getApiInfo } from './xhs-api/api.ts';
|
||||||
import { XhsClient as XhsClientBase } from '@kevisual/xhs-core';
|
import { XhsClient as XhsClientBase } from '@kevisual/xhs-core';
|
||||||
import { Mention, CommonentInfo } from './xhs-type/mention.ts';
|
import { Mention, CommonentInfo } from './xhs-type/mention.ts';
|
||||||
|
|
||||||
@ -13,17 +14,29 @@ type SignInfo = {
|
|||||||
a1: string;
|
a1: string;
|
||||||
web_session?: string;
|
web_session?: string;
|
||||||
};
|
};
|
||||||
|
type SignResponse = {
|
||||||
|
a1: string;
|
||||||
|
sign: {
|
||||||
|
b1: string;
|
||||||
|
b1b1: string;
|
||||||
|
['x-s']: string;
|
||||||
|
['x-t']: string;
|
||||||
|
};
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
type SignOptions = {
|
type SignOptions = {
|
||||||
signUrl?: string;
|
signUrl?: string;
|
||||||
};
|
};
|
||||||
export const getSign = async (signInfo: SignInfo, options?: SignOptions) => {
|
export const getSign = async (signInfo: SignInfo, options?: SignOptions): Promise<SignResponse> => {
|
||||||
const { uri, data, a1, web_session } = signInfo;
|
const { uri, data, a1, web_session } = signInfo;
|
||||||
// console.log('getSign', uri, data, a1, web_session);
|
// console.log('getSign', uri, data, a1, web_session);
|
||||||
// let signUri = new URL(uri, 'http://light.xiongxiao.me:5006').pathname;
|
// let signUri = new URL(uri, 'http://light.xiongxiao.me:5006').pathname;
|
||||||
// signUri = '/api/sns/web/v2/user/me';
|
// signUri = '/api/sns/web/v2/user/me';
|
||||||
try {
|
try {
|
||||||
let signUrl = options?.signUrl || 'http://light.xiongxiao.me:5006/sign';
|
let signUrl = options?.signUrl || 'http://localhost:5005/sign';
|
||||||
// signUrl = 'http://localhost:5005/sign'
|
// signUrl = 'http://localhost:5005/sign';
|
||||||
|
// const urlA1 = ''http://light.xiongxiao.me:5006/a1';
|
||||||
|
// const urlA1 = 'http://localhost:5005/a1';
|
||||||
const signs = await fetch(signUrl, {
|
const signs = await fetch(signUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@ -52,18 +65,27 @@ export class XhsClient extends XhsClientBase {
|
|||||||
constructor(opts: XhsOptions) {
|
constructor(opts: XhsOptions) {
|
||||||
super(opts as any);
|
super(opts as any);
|
||||||
}
|
}
|
||||||
printResult(msg: string, response: any) {
|
getApiInfo = getApiInfo;
|
||||||
|
printResult(msg: string, data: any) {
|
||||||
if (msg === 'response') {
|
if (msg === 'response') {
|
||||||
console.log('url', response.url);
|
console.log('url', data.url);
|
||||||
if (response.response) {
|
console.log('status', data?.response?.status);
|
||||||
console.log('status', response.response.status);
|
if (data.response) {
|
||||||
console.log('data', response.response.data);
|
console.log('data', data.response.data);
|
||||||
}
|
}
|
||||||
} else if (msg === 'request') {
|
} else if (msg === 'request') {
|
||||||
// console.log('request', response);
|
console.log('request', data);
|
||||||
} else if (msg === 'html') {
|
} else if (msg === 'html') {
|
||||||
// console.log('html', response);
|
// console.log('html', response);
|
||||||
}
|
}
|
||||||
|
switch (msg) {
|
||||||
|
case 'get':
|
||||||
|
console.log('get', data);
|
||||||
|
break;
|
||||||
|
case 'sign':
|
||||||
|
console.log('sign', data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 获取未读消息
|
* 获取未读消息
|
||||||
@ -71,7 +93,7 @@ export class XhsClient extends XhsClientBase {
|
|||||||
*/
|
*/
|
||||||
async getUnread(): Promise<Result<UnreadCount>> {
|
async getUnread(): Promise<Result<UnreadCount>> {
|
||||||
const url = '/api/sns/web/unread_count';
|
const url = '/api/sns/web/unread_count';
|
||||||
const response = await this.get(url);
|
const response = await this.get(url, null, { needSign: false });
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
@ -103,6 +125,12 @@ export class XhsClient extends XhsClientBase {
|
|||||||
const response = await super.getUserInfoFromHtml(userId);
|
const response = await super.getUserInfoFromHtml(userId);
|
||||||
return response as ReturnData;
|
return response as ReturnData;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 这个接口不能多用,否则会出现封控406错误
|
||||||
|
* @param num
|
||||||
|
* @param cursor
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
async getFollowNotifications(num = 10, cursor = '') {
|
async getFollowNotifications(num = 10, cursor = '') {
|
||||||
const url = '/api/sns/web/v1/you/connections';
|
const url = '/api/sns/web/v1/you/connections';
|
||||||
type Connection = {
|
type Connection = {
|
||||||
@ -129,18 +157,14 @@ export class XhsClient extends XhsClientBase {
|
|||||||
* @uri /api/sns/web/v1/you/mentions
|
* @uri /api/sns/web/v1/you/mentions
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async getMention(num = 10): Promise<Result<Mention>> {
|
async getMention(num = 20): Promise<Result<Mention>> {
|
||||||
const url = '/api/sns/web/v1/you/mentions';
|
const url = '/api/sns/web/v1/you/mentions';
|
||||||
const response = await this.get(
|
const response = await this.get(
|
||||||
url,
|
url,
|
||||||
{ num },
|
{ num: 20, cursor: '' },
|
||||||
{
|
{
|
||||||
sign: this.sign.bind(this),
|
sign: this.sign.bind(this),
|
||||||
// headers: {
|
needSign: true,
|
||||||
// 'x-s':
|
|
||||||
// 'XYW_eyJzaWduU3ZuIjoiNTYiLCJzaWduVHlwZSI6IngyIiwiYXBwSWQiOiJsb2dpbiIsInNpZ25WZXJzaW9uIjoiMSIsInBheWxvYWQiOiJiNGJmMGI2MDVkZTlkOWMyY2RlNTI2YmVjNjM2ZmIxMjkxYzUxMTIyYWQyOTk5MzIyMzNjMmU0OTEzMWFmYzgzY2FmOGQzZDIzMTA0Y2RlNWUzZDZlZDczMDg0MmUzYzAxOTNkY2FjZjEyZjk1NTMzZGQzY2ZkMGFmOTg5MGZmMDIwNWI0MmQwOTNiYmJjMGNkZWU3MzdmOGE2MmRkYWVlYjZhMjcxZDViNjZkNGRjYjA1NDg2MGZhNTllN2M5MjE0ZDE2OTJjYWQyZjZmNzE1NThmYWQ3YjQxZjlhZTNiYjA1ZDExN2YzYWI2ZjRjYzY5MzcyMzRhOTY1OTkxYzMwMWY2YjI1MzY4MTZiNzM1YzhmMWEzOTk2ODhkMWU0NDFiODljYTNlNzQ3YWNlN2M2MGIzZDlhZWQwZDVlZDZlNGFhMDE5MmQ5YzZjNDE1M2IxM2RjODAwYjUzZTQxYWEzOTU4MjJhMzYyMmJjODEwYmY4MzA3MjkwMjY2ZDUzNmQwMjdkMTJlOWEwMzhlZmY1YWU4OTM5NDVlNDhmYmY2MCJ9',
|
|
||||||
// 'x-t': '1746097556685',
|
|
||||||
// },
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
@ -148,15 +172,25 @@ export class XhsClient extends XhsClientBase {
|
|||||||
async sign(uri: string, data: any, config: any) {
|
async sign(uri: string, data: any, config: any) {
|
||||||
let headers = config?.headers || {};
|
let headers = config?.headers || {};
|
||||||
const cookieDist = this.getCookieMap();
|
const cookieDist = this.getCookieMap();
|
||||||
|
const apiInfo = this.getApiInfo(uri);
|
||||||
|
if (apiInfo && !apiInfo?.needSign) {
|
||||||
|
return config || {};
|
||||||
|
}
|
||||||
const web_session = cookieDist['web_session'];
|
const web_session = cookieDist['web_session'];
|
||||||
const a1 = cookieDist['a1'];
|
const a1 = cookieDist['a1'];
|
||||||
const res = await getSign({ uri, data, a1, web_session }, this.signConfig);
|
const res = await getSign({ uri, data, a1, web_session }, this.signConfig);
|
||||||
if (res) {
|
const _sign = res.sign;
|
||||||
headers['x-s'] = res?.['x-s'];
|
this.printResult('sign', { uri, apiInfo, res });
|
||||||
headers['x-t'] = res?.['x-t'];
|
const xs = _sign?.['x-s'];
|
||||||
|
const xt = _sign?.['x-t'];
|
||||||
|
const b1 = _sign?.['b1'];
|
||||||
|
if (res && xs) {
|
||||||
|
headers['x-s'] = xs;
|
||||||
|
headers['x-t'] = xt;
|
||||||
|
// headers['x-s-common'] = this.getXCommon(a1, b1, xs, xt);
|
||||||
config.headers = headers;
|
config.headers = headers;
|
||||||
} else {
|
} else {
|
||||||
console.log('get sign error');
|
console.log('get sign error', res);
|
||||||
throw new Error('get sign error');
|
throw new Error('get sign error');
|
||||||
}
|
}
|
||||||
return config;
|
return config;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { app, xhsServices } from '@/app.ts';
|
import { app, xhsServices } from '@/app.ts';
|
||||||
import { Mention } from '@/libs/xhs-type/mention.ts';
|
import { Mention } from '@/libs/xhs-type/mention.ts';
|
||||||
import { Parse } from '@/libs/parse.ts';
|
import { Parse } from '@/libs/parse.ts';
|
||||||
import { client } from '@/test/common.ts';
|
|
||||||
app
|
app
|
||||||
.route({
|
.route({
|
||||||
path: 'mention',
|
path: 'mention',
|
||||||
|
44
packages/xhs/src/services/xhs-db/comment.ts
Normal file
44
packages/xhs/src/services/xhs-db/comment.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { InitOptions, Model, Sequelize, SyncOptions } from 'sequelize';
|
||||||
|
import { DataTypes } from 'sequelize';
|
||||||
|
export class Comment extends Model {
|
||||||
|
declare id: number;
|
||||||
|
declare content: string;
|
||||||
|
declare note_id: string;
|
||||||
|
declare user_id: string;
|
||||||
|
declare comment_id: string;
|
||||||
|
declare created_at: Date;
|
||||||
|
declare updated_at: Date;
|
||||||
|
static async initModel(sequelize: Sequelize, initOptions?: InitOptions, opts?: SyncOptions) {
|
||||||
|
Comment.init(
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
primaryKey: true,
|
||||||
|
autoIncrement: true,
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
type: DataTypes.TEXT,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
note_id: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
user_id: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
comment_id: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sequelize, // passing the `sequelize` instance is required
|
||||||
|
modelName: 'Comment', // we need to choose the model name
|
||||||
|
...initOptions,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
await Comment.sync(opts || {});
|
||||||
|
}
|
||||||
|
}
|
3
packages/xhs/src/services/xhs-db/db-manager.ts
Normal file
3
packages/xhs/src/services/xhs-db/db-manager.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export class DBManager {
|
||||||
|
constructor() {}
|
||||||
|
}
|
16
packages/xhs/src/services/xhs-db/db.ts
Normal file
16
packages/xhs/src/services/xhs-db/db.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { Sequelize } from 'sequelize';
|
||||||
|
|
||||||
|
type SequelizeOptions = {
|
||||||
|
storage: string;
|
||||||
|
logging?: boolean;
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
export const createSequelize = (opts?: SequelizeOptions) => {
|
||||||
|
const dbPath = opts?.storage || 'xhs.db';
|
||||||
|
const sequelize = new Sequelize({
|
||||||
|
dialect: 'sqlite',
|
||||||
|
storage: dbPath,
|
||||||
|
logging: opts?.logging ?? true,
|
||||||
|
});
|
||||||
|
return sequelize;
|
||||||
|
};
|
@ -1,4 +1,8 @@
|
|||||||
import { XhsClient } from '@/libs/xhs.ts';
|
import { XhsClient } from '@/libs/xhs.ts';
|
||||||
|
import { Sequelize } from 'sequelize';
|
||||||
|
import { createSequelize } from '@/services/xhs-db/db.ts';
|
||||||
|
import path from 'node:path';
|
||||||
|
import fs from 'node:fs';
|
||||||
|
|
||||||
type XhsClientOptions = {
|
type XhsClientOptions = {
|
||||||
key: string;
|
key: string;
|
||||||
@ -6,12 +10,14 @@ type XhsClientOptions = {
|
|||||||
signConfig?: {
|
signConfig?: {
|
||||||
signUrl: string;
|
signUrl: string;
|
||||||
};
|
};
|
||||||
|
initDB?: boolean;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
type XhsClientMap = {
|
type XhsClientMap = {
|
||||||
client: XhsClient;
|
client: XhsClient;
|
||||||
key: string;
|
key: string;
|
||||||
options: XhsClientOptions;
|
options: XhsClientOptions;
|
||||||
|
db: Sequelize;
|
||||||
};
|
};
|
||||||
type XhsServicesOptions = {
|
type XhsServicesOptions = {
|
||||||
root?: string;
|
root?: string;
|
||||||
@ -29,9 +35,34 @@ export class XhsServices {
|
|||||||
}
|
}
|
||||||
const client = new XhsClient({ cookie });
|
const client = new XhsClient({ cookie });
|
||||||
client.signConfig = signConfig;
|
client.signConfig = signConfig;
|
||||||
this.map.set(key, { client, key, options });
|
const storagePath = options.storage || `db-sqlite/xhs-${key}.db`;
|
||||||
|
const storage = path.resolve(storagePath);
|
||||||
|
const dir = path.dirname(storage);
|
||||||
|
if (!fs.existsSync(dir)) {
|
||||||
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
|
}
|
||||||
|
let isNew = options?.initDB ?? false;
|
||||||
|
if (!fs.existsSync(storage) || !isNew) {
|
||||||
|
isNew = true;
|
||||||
|
}
|
||||||
|
const db = createSequelize({ storage: storage });
|
||||||
|
const xhsClientMap = {
|
||||||
|
client,
|
||||||
|
key,
|
||||||
|
options,
|
||||||
|
db,
|
||||||
|
};
|
||||||
|
if (isNew) {
|
||||||
|
this.initDb(xhsClientMap);
|
||||||
|
}
|
||||||
|
this.map.set(key, xhsClientMap);
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
async initDb(xhsClientMap: XhsClientMap) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
createRoot(options: Partial<XhsClientOptions>) {
|
createRoot(options: Partial<XhsClientOptions>) {
|
||||||
options.key = options.key || this.root;
|
options.key = options.key || this.root;
|
||||||
return this.createClient(options as XhsClientOptions);
|
return this.createClient(options as XhsClientOptions);
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { program } from 'commander';
|
import { program } from 'commander';
|
||||||
|
import './query/add-comment.ts';
|
||||||
|
|
||||||
import './query/get-components.ts';
|
import './query/get-components.ts';
|
||||||
import './query/get-note.ts';
|
import './query/get-note.ts';
|
||||||
|
import './query/get-sign.ts'
|
||||||
import './query/mention.ts'
|
import './query/mention.ts'
|
||||||
import './query/unread.ts';
|
import './query/unread.ts';
|
||||||
import './query/get-userinfo.ts';
|
import './query/get-userinfo.ts';
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
import { XhsClient, xhsServices } from '../index.ts';
|
import { xhsServices } from '../index.ts';
|
||||||
import { program } from 'commander';
|
import { program } from 'commander';
|
||||||
export const cookie =
|
|
||||||
'a1=1968ba02ff4xrt6hfrzdiz7ubs82j9y3vx11vfw9c40000317680;abRequestId=0a794332-4561-5f49-93f7-780b8b028e1f;access-token-creator.xiaohongshu.com=customer.creator.AT-68c517498636784561614544frjvxzj7yu8iewie;agora_session=6a0031373435393132333637323735343733393437313634000000000000;customerClientId=536706778174172;galaxy_creator_session_id=OhpHDDSoADhNEhnH5LLnQpletFLApu1fd91f;galaxy.creator.beaker.session.id=1745912429847011598150;gid=yjKqYfK0qDyYyj2DDSqd4ujxyW9kvxIuT62ddkMWhElyuxq8yDd6hl888q2WYy88j8i80yYD;loadts=1746020512562;sec_poison_id=441c932e-a6ac-4d8d-97ae-beb14adb1929;unread={%22ub%22:%2267eaf1fe000000001202c3ea%22%2C%22ue%22:%226803aa37000000001c0319d8%22%2C%22uc%22:35};web_session=040069b2e9c511ca302086ca253a4bde8b1cd1;webBuild=4.62.3;webId=97e5f097499594cad49aa0bd1a8ed83f;websectiga=3633fe24d49c7dd0eb923edc8205740f10fdb18b25d424d2a2322c6196d2a4ad;x-user-id-creator.xiaohongshu.com=639d86590000000026006076;xsecappid=xhs-pc-web;acw_tc=0a00df6217460205042195762e721fba339a0dbe8e4738b961a5ff15e74619;';
|
|
||||||
|
|
||||||
export const client = new XhsClient({ cookie } as any);
|
|
||||||
|
|
||||||
export { program, xhsServices };
|
export { program, xhsServices };
|
||||||
|
24
packages/xhs/src/test/db/comment.ts
Normal file
24
packages/xhs/src/test/db/comment.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { Comment } from '@/services/xhs-db/comment.ts';
|
||||||
|
|
||||||
|
import { Sequelize, Model, DataTypes, InferAttributes, InferCreationAttributes } from 'sequelize';
|
||||||
|
import path from 'path';
|
||||||
|
const dbPath = path.join(process.cwd(), './test2.db');
|
||||||
|
const sequelize = new Sequelize({
|
||||||
|
dialect: 'sqlite',
|
||||||
|
storage: dbPath,
|
||||||
|
logging: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const commentTest = async () => {
|
||||||
|
await Comment.initModel(sequelize, null, { alter: true });
|
||||||
|
const comment = await Comment.create({
|
||||||
|
content: 'test',
|
||||||
|
note_id: '1',
|
||||||
|
user_id: '1',
|
||||||
|
comment_id: '1',
|
||||||
|
});
|
||||||
|
console.log(comment.toJSON());
|
||||||
|
const comments = await Comment.findAll();
|
||||||
|
console.log(comments.map((item) => item.toJSON()));
|
||||||
|
};
|
||||||
|
commentTest();
|
40
packages/xhs/src/test/db/index.ts
Normal file
40
packages/xhs/src/test/db/index.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { Sequelize, Model, DataTypes, InferAttributes, InferCreationAttributes } from 'sequelize';
|
||||||
|
import path from 'path';
|
||||||
|
const dbPath = path.join(process.cwd(), './test2.db');
|
||||||
|
const sequelize = new Sequelize({
|
||||||
|
dialect: 'sqlite',
|
||||||
|
storage: dbPath,
|
||||||
|
});
|
||||||
|
console.log('dbPath', dbPath);
|
||||||
|
sequelize
|
||||||
|
.authenticate()
|
||||||
|
.then(() => {
|
||||||
|
console.log('Connection has been established successfully.');
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('Unable to connect to the database:', err);
|
||||||
|
});
|
||||||
|
// Define a User model
|
||||||
|
class User extends Model<InferAttributes<User>, InferCreationAttributes<User>> {
|
||||||
|
declare username: string | null;
|
||||||
|
declare birthday: Date | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
User.init(
|
||||||
|
{
|
||||||
|
username: DataTypes.STRING,
|
||||||
|
birthday: DataTypes.DATE,
|
||||||
|
},
|
||||||
|
{ sequelize, modelName: 'user' },
|
||||||
|
);
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
await sequelize.sync({ alter: true });
|
||||||
|
const jane = await User.create({
|
||||||
|
username: 'janedoe',
|
||||||
|
birthday: new Date(1980, 6, 20),
|
||||||
|
});
|
||||||
|
console.log(jane.toJSON());
|
||||||
|
const users = await User.findAll();
|
||||||
|
console.log(users.map((item) => item.toJSON()));
|
||||||
|
})();
|
20
packages/xhs/src/test/db/sqlite3.ts
Normal file
20
packages/xhs/src/test/db/sqlite3.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import sqlite3 from 'sqlite3';
|
||||||
|
|
||||||
|
const db = new sqlite3.Database('./test.db');
|
||||||
|
|
||||||
|
db.serialize(() => {
|
||||||
|
db.run('CREATE TABLE lorem (info TEXT)');
|
||||||
|
|
||||||
|
const stmt = db.prepare('INSERT INTO lorem VALUES (?)');
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
stmt.run('Ipsum ' + i);
|
||||||
|
}
|
||||||
|
stmt.finalize();
|
||||||
|
|
||||||
|
db.each('SELECT rowid AS id, info FROM lorem', (err, row) => {
|
||||||
|
// @ts-ignore
|
||||||
|
console.log(row.id + ': ' + row.info);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
db.close();
|
30
packages/xhs/src/test/fetch-test.ts
Normal file
30
packages/xhs/src/test/fetch-test.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
const res = await fetch('https://edith.xiaohongshu.com/api/sns/web/v1/you/mentions?num=1&cursor=', {
|
||||||
|
headers: {
|
||||||
|
accept: 'application/json, text/plain, */*',
|
||||||
|
'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
|
||||||
|
priority: 'u=1, i',
|
||||||
|
'sec-ch-ua': '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
|
||||||
|
'sec-ch-ua-mobile': '?0',
|
||||||
|
'sec-ch-ua-platform': '"macOS"',
|
||||||
|
'sec-fetch-dest': 'empty',
|
||||||
|
'sec-fetch-mode': 'cors',
|
||||||
|
'sec-fetch-site': 'same-site',
|
||||||
|
'x-b3-traceid': 'f0a77d639fe56582',
|
||||||
|
'x-mns': 'unload',
|
||||||
|
'x-s':
|
||||||
|
'XYW_eyJzaWduU3ZuIjoiNTYiLCJzaWduVHlwZSI6IngyIiwiYXBwSWQiOiJ4aHMtcGMtd2ViIiwic2lnblZlcnNpb24iOiIxIiwicGF5bG9hZCI6ImI3ODU1NmVkYTliOGFjMmRjOGVkYjAxY2E0ZjJhMTQ1NmI4Yzk2NzQwZmY0MjhhNjY4YWQ1Yzk4OTg2YzRjNGEyOGQ0YzE4MWIxYjQ3NzZmNzNhNDkwNDMwZGMyMWVhMzc1Mzg4ODQyOThmM2U0MmM5YTlhM2IyNjU5OWZmZjdlZGM1ZjczNDE2ZmZmYzBlYzcxMTRkODM1YTE2MGQ2MmViNjU4NTMxNjkyZGRkYWExZDNkZjIyNjZlMmFmZWQyZGMzYTM0MGEwZWU0ZTkwMmExNGU2ZmE4YmY4YWEzYzliZGNlYjM1YTkyZGMwODdlYjdlOTk3YWVlMjI2NDhkODVlNDMzZmEzZDA4YjJjYzhmNDJlMDlmM2Y0ZjBlMmJmNzQzZjE2ZGZmNzAyNjdjYmMzNzE2MTkxNjY0Y2RkMGYzZWJiMTgyY2UyZTg5MjdiMDJjYTgzYWFiZWI3ZTI2M2FjYTY5NmY4NTJmYzc2OWFkNWUzNGIxNjdhMjUwNmQxNTJjZjhkZDY5MzMwNzhjNDE0ZTM3ZmNhZWY1OTQyODA1In0=',
|
||||||
|
'x-s-common':
|
||||||
|
'2UQAPsHCPUIjqArjwjHjNsQhPsHCH0rjNsQhPaHCH0c1PahIHjIj2eHjwjQ+GnPW/MPjNsQhPUHCHdYiqUMIGUM78nHjNsQh+sHCH0c1+0H1PUHVHdWMH0ijP/D9w/ZhwBQfP0Q6ynziJ9QSq0HUyo+j+AziP7b6Gg8I4n+D4fMUGfHAPeZIPeqlP0ch+sHVHdW9H0il+Ac9P/WlweZhP/HENsQh+UHCHSY8pMRS2LkCGp4D4pLAndpQyfRk/Sz8yLleadkYp9zMpDYV4Mk/a/8QJf4EanS7ypSGcd4/pMbk/9St+BbH/gz0zFMF8eQnyLSk49S0Pfl1GflyJB+1/dmjP0zk/9SQ2rSk49S0zFGMGDqEybkea/8QJLDA/FzpPLETpfT8pBlk/F4ByDMTLfkOzM83nnkm2bDUz/myyDki/pzzPLETa/z82fVU/dkz4MkTn/m+yfYi/fk8+bSgL/b82fVF/MzdPSSCLfkwzFpE/F4zPbSCz/z+pFShnnkzPFECnfMw2DEi/Dz34FEr/g4yzFME/p4nyrMCGAb+2fqF/Fzz2LRLyBM+PSLI/nM++pSLJBY+PDSE/fkp+LRgnfMyyfzVnD4+PpkxG7kwzrLUnfMyJpSCcfl82f+h/pzayFRr//b8prLU/L4zPDMTpfSwySLF/Sz+2rExy7SyzMQ3np4b2bkr/fTyyDSE/fkyJrMTzfMypMbEnD4+2SSL//m+zFp7nS4pPbkLy74+JLph/D4pPSkTz/z8JpDFnp4b2SSCJBSyzFEVnnk+PpSLy7SyzFM7/FzDJbSx8BlOpBVAnp4nJrMxa/QwzBY3/FznJrEr/gkyJLpCnDzm+bSxafk82fYT/DztJrMrJBM+PSDInfksJrMTafMw2SbCnfkbPSkonfMw2DbE/fkDySST/gkw2DLU/pz32rExn/m8PSQ3/L482SkgafS+pB4En/Qp2pkL8Ap+yfzk/LztySSL87k8pF8knS4QPMkLa/Q+PD8xnpz8+LETn/zwprkTngk0PDRgzfTwpMpC/D4Q2rEx8BY+ySp7/fMz2rELafkyyfY3nDz8+LMC/g4w2fYx/DzbPbkL//+yJLEinS48PLRLLgSOzrrlanhIOaHVHdWhH0ija/PhqDYD87+xJ7mdag8Sq9zn494QcUT6aLpPJLQy+nLApd4G/B4BprShLA+jqg4bqD8S8gYDPBp3Jf+m2DMBnnEl4BYQyrkSL9z32obl49zQ4DbApFQ0yo4c4ozdJ/c9aMpC2rSiPoPI/rTAydb7JdD7zbkQ4fRA2BQcydSy4LbQyrTSzBr7q98ppbztqgzat7b7cgmDqrEQc9YT/Sqha7kn4M+Qc94Sy7pFao4l4FzQzL8laLL6qMzQnfSQ2oQ+ag8d8nzl4MH3+7mc2Skwq9z8P9pfqgzmanTw8/+n494lqgzIqopF2rTC87Plp7mSaL+npFSiL/Z6LozzaM87cLDAn0Q6JnzSygb78DSecnpLpdzUaLL3tFSbJnE08fzSyf4CngQ6J7+fqg4OnS468nzPzrzsJ94AySkIcDSha7+DpdzYanT98n8l4MQj/LlQz9GFcDDA+9pL4gz/NM+N8/r7/pmQyBQAaLpbt741+BSQPMSlwBlb8FS3/oY6qg43aL+yp0QDP9pxan4APgp7LDS989LIPo8SPsRMLrSk87PAL9Mr2gp74LSka9pL80mA2BF68/bn4ezPqFkSngb7yrS9zL40PBRS8op7zgm1N7+/qg4dagYzqDS9y9T6pd4o2S87t9bd+bbcpURS8BEd8pzn49RQznRAyDQmq7YPqd8Qz/mAPrIAqA8fz9zQyrEAP7p74DSbJp4F4g4I/7b7cFDAafpLpdzBanVAq9Sl4ApQye+Aydp7+LEl4946pd4MaL+CaLS9LLRzq9DAGDH98pzl4F8QypboaLLM8nzM4r4ynfTFcSLMqMqILLzQyF4PadbFa9bl47pQ40+S+S8F2bbIa9LAaLbSPLl/qDSbad+3cDRSPb87Lf+c49bQcFkApMm7pLSk89p38gbPanVAqAb087+n4g4IanYS8p+n4Bky+FzAanDh4rDA+fL92DkAy9iMq9iI89LI4g46anY3aLSbqnb0Lo40agY0LFDAPBpLp9MQ2nL68pSgO/FjNsQhwaHCP/HhP/LUwerIPjIj2erIH0iUP0LEKc==',
|
||||||
|
'x-t': '1746181808129',
|
||||||
|
'x-xray-traceid': 'cb4845eff6cf7d70df0fe575e3d8af06',
|
||||||
|
cookie:
|
||||||
|
'acw_tc=0a0b121417461803133571274e75c1c431e8abf9d81133812d3ca340bf8fe2; abRequestId=e1b9d999-8838-528a-9933-5f3ac9134d8c; webBuild=4.62.3; xsecappid=xhs-pc-web; a1=1969088bf22oidhober22hsb74h3qoavpucdvmrbb30000712484; webId=bffbeec4c301c7b3dc284ee35dd742fb; websectiga=8886be45f388a1ee7bf611a69f3e174cae48f1ea02c0f8ec3256031b8be9c7ee; sec_poison_id=d6fbc71a-7538-4ebe-acd6-5e5b79bc78eb; gid=yjKj8YYdSSUqyjKj8YYDi76FJJl3fxlDdFJJSDDxMDW4xfq8qAl0hh888WyJ4Y48ySjjfKfd; web_session=040069b2e9c511ca302098d5213a4b8556ed1d; unread={%22ub%22:%2268077ca2000000001b03bff6%22%2C%22ue%22:%22680e491b000000000b015506%22%2C%22uc%22:30}; loadts=1746181806203',
|
||||||
|
Referer: 'https://www.xiaohongshu.com/',
|
||||||
|
'Referrer-Policy': 'strict-origin-when-cross-origin',
|
||||||
|
},
|
||||||
|
body: null,
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
res.json().then((data) => {
|
||||||
|
console.log('data', data);
|
||||||
|
});
|
14
packages/xhs/src/test/query/add-comment.ts
Normal file
14
packages/xhs/src/test/query/add-comment.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { xhsServices, program } from '../common.ts';
|
||||||
|
|
||||||
|
program
|
||||||
|
.command('add-comment')
|
||||||
|
.description('add comment')
|
||||||
|
.action(async () => {
|
||||||
|
const client = xhsServices.getClient();
|
||||||
|
const res = await client.postComment({
|
||||||
|
note_id: '68136dab0000000007034c46',
|
||||||
|
content: 'test comment 233',
|
||||||
|
comment_id: '68136dcf000000000401a8c9',
|
||||||
|
});
|
||||||
|
console.log(res);
|
||||||
|
});
|
@ -1,14 +1,14 @@
|
|||||||
import { client } from '../common.ts';
|
import { xhsServices, program } from '../common.ts';
|
||||||
import { program } from 'commander';
|
import utils from 'node:util';
|
||||||
|
|
||||||
program
|
program
|
||||||
.command('get-commonents')
|
.command('get-commonents')
|
||||||
.description('get commonents')
|
.description('get commonents')
|
||||||
.action(async () => {
|
.action(async () => {
|
||||||
const res = await client.getNoteComments('6810d722000000002100f139', '', {
|
const client = xhsServices.getClient();
|
||||||
|
const res = await client.getNoteComments('68136dab0000000007034c46', '', {
|
||||||
//
|
//
|
||||||
xsec_token: 'LBEqTFigLzp41AdwQ-E3hbQScnvrx2flLgHElHpQ8zHWc=',
|
xsec_token: 'LByEmonX8WfJ9ebpAowVbOZX9Xh8T0Qkjil5KRFqDD6LM=',
|
||||||
top_comment_id: '6810e7d80000000012020c7a'
|
|
||||||
});
|
});
|
||||||
console.log(res);
|
console.log(utils.inspect(res, { depth: null, colors: true }));
|
||||||
});
|
});
|
||||||
|
@ -2,8 +2,10 @@ import { xhsServices, program } from '../common.ts';
|
|||||||
import util from 'node:util';
|
import util from 'node:util';
|
||||||
const getConnections = async () => {
|
const getConnections = async () => {
|
||||||
const client = xhsServices.getClient();
|
const client = xhsServices.getClient();
|
||||||
const res = await client.getFollowNotifications(10, '');
|
const res = await client.getFollowNotifications(2, '');
|
||||||
|
if (res.code === 0) {
|
||||||
console.log(util.inspect(res, { depth: null, colors: true }));
|
console.log(util.inspect(res, { depth: null, colors: true }));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
program
|
program
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { client } from '../common.ts';
|
import { xhsServices, program } from '../common.ts';
|
||||||
import { program } from 'commander';
|
|
||||||
|
|
||||||
// client.getNoteComments()
|
// client.getNoteComments()
|
||||||
|
|
||||||
@ -7,13 +7,15 @@ import { program } from 'commander';
|
|||||||
// console.log(res);
|
// console.log(res);
|
||||||
// });
|
// });
|
||||||
const getNoteById = async () => {
|
const getNoteById = async () => {
|
||||||
|
const client = xhsServices.getClient();
|
||||||
client.getNoteById('67dcc34e000000000602a8eb', 'ABuYS8Xb1o08DlRmMLIabdqnW0OKnLR9nMpDGq5bVRdvk').then((res) => {
|
client.getNoteById('67dcc34e000000000602a8eb', 'ABuYS8Xb1o08DlRmMLIabdqnW0OKnLR9nMpDGq5bVRdvk').then((res) => {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const getNote = async () => {
|
const getNote = async () => {
|
||||||
const id = '6810d722000000002100f139';
|
const id = '68136dab0000000007034c46';
|
||||||
const x = 'LBEqTFigLzp41AdwQ-E3hbQScnvrx2flLgHElHpQ8zHWc=';
|
const x = 'LByEmonX8WfJ9ebpAowVbOZX9Xh8T0Qkjil5KRFqDD6LM=';
|
||||||
|
const client = xhsServices.getClient();
|
||||||
client.getNoteByIdFromHtml(id, x).then((res) => {
|
client.getNoteByIdFromHtml(id, x).then((res) => {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
});
|
});
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import { client, program } from '../common.ts';
|
import { xhsServices, program } from '../common.ts';
|
||||||
|
|
||||||
const getSign = async () => {
|
const getSign = async () => {
|
||||||
const uri = '/api/sns/web/v1/you/mentions';
|
const uri = '/api/sns/web/v1/you/mentions?num=20&cursor=';
|
||||||
const data = null;
|
const data = null;
|
||||||
|
// _webmsxyw('/api/sns/web/v1/you/mentions?num=20&cursor=', null);
|
||||||
const config = { headers: {} };
|
const config = { headers: {} };
|
||||||
|
const client = xhsServices.getClient();
|
||||||
const res = await client.sign(uri, data, config);
|
const res = await client.sign(uri, data, config);
|
||||||
console.log('getSign', res);
|
console.log('getSign', res);
|
||||||
};
|
};
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
import { client, program } from '../common.ts';
|
import { xhsServices, program } from '../common.ts';
|
||||||
|
|
||||||
program
|
program
|
||||||
.command('get-userinfo')
|
.command('get-userinfo')
|
||||||
.description('获取用户信息')
|
.description('获取用户信息')
|
||||||
.action(async () => {
|
.action(async () => {
|
||||||
|
const client = xhsServices.getClient();
|
||||||
const res = await client.getSelfInfoV2();
|
const res = await client.getSelfInfoV2();
|
||||||
console.log(res);
|
console.log(res);
|
||||||
});
|
});
|
||||||
|
|
||||||
const getUserById = async (userId: string) => {
|
const getUserById = async (userId: string) => {
|
||||||
|
const client = xhsServices.getClient();
|
||||||
const res = await client.getUserInfoFromHtml(userId);
|
const res = await client.getUserInfoFromHtml(userId);
|
||||||
console.log(res);
|
console.log(res);
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { client, program } from '../common.ts';
|
import { xhsServices, program } from '../common.ts';
|
||||||
import util from 'node:util';
|
import util from 'node:util';
|
||||||
const getMentions = async () => {
|
const getMentions = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await client.getMention();
|
const client = xhsServices.getClient();
|
||||||
if (res.code === 0) {
|
const res = await client.getMention(1);
|
||||||
console.log('getMentionNotifications', util.inspect(res, { depth: 10 }));
|
if (res.code) {
|
||||||
|
const data = res.data || {};
|
||||||
|
console.log('getMentionNotifications', util.inspect(data, { depth: 10 }));
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('error');
|
console.error('error');
|
||||||
@ -19,6 +21,7 @@ const getTestMentionNote = async () => {
|
|||||||
const title = '在笔记中@了你';
|
const title = '在笔记中@了你';
|
||||||
const type = 'mention/item';
|
const type = 'mention/item';
|
||||||
const track_type = '2';
|
const track_type = '2';
|
||||||
|
const client = xhsServices.getClient();
|
||||||
const note = await client.getNoteByIdFromHtml(id, xsec_token);
|
const note = await client.getNoteByIdFromHtml(id, xsec_token);
|
||||||
console.log('note', note);
|
console.log('note', note);
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { client, program } from '../common.ts';
|
import { xhsServices, program } from '../common.ts';
|
||||||
|
|
||||||
const getUnread = () => {
|
const getUnread = () => {
|
||||||
|
const client = xhsServices.getClient();
|
||||||
client.getUnread().then((res) => {
|
client.getUnread().then((res) => {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
});
|
});
|
||||||
|
BIN
packages/xhs/test2.db
Normal file
BIN
packages/xhs/test2.db
Normal file
Binary file not shown.
@ -2,6 +2,14 @@
|
|||||||
"extends": "@kevisual/types/json/backend.json",
|
"extends": "@kevisual/types/json/backend.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "./",
|
"baseUrl": "./",
|
||||||
|
"lib": [
|
||||||
|
"ESNext"
|
||||||
|
],
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"types": [
|
||||||
|
"node_modules/@types"
|
||||||
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": [
|
"@/*": [
|
||||||
"src/*"
|
"src/*"
|
||||||
|
863
pnpm-lock.yaml
generated
863
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,6 @@
|
|||||||
packages:
|
packages:
|
||||||
- packages/*
|
- packages/*
|
||||||
- submodules/*
|
- submodules/*
|
||||||
|
onlyBuiltDependencies:
|
||||||
|
- better-sqlite3
|
||||||
|
- sqlite3
|
||||||
|
Loading…
x
Reference in New Issue
Block a user