generated from tailored/router-db-template
temp
This commit is contained in:
61
packages/xhs/src/libs/parse.ts
Normal file
61
packages/xhs/src/libs/parse.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { Connection } from './xhs-type/connection.ts';
|
||||
import { Mention, CommonentInfo } from './xhs-type/mention.ts';
|
||||
import { NoteFromHtml } from './xhs-type/note.ts';
|
||||
const parseComment = (comment: CommonentInfo) => {
|
||||
if (!comment) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
comment_id: comment.id,
|
||||
content: comment.content,
|
||||
};
|
||||
};
|
||||
export class Parse {
|
||||
static getComment(mention: Mention) {
|
||||
if (mention.type === 'mention/comment') {
|
||||
const comment_info = mention.comment_info;
|
||||
const comment = parseComment(comment_info);
|
||||
const target_comment = parseComment(comment_info.target_comment);
|
||||
return {
|
||||
...comment,
|
||||
target_comment,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
static getUser(mention: Mention) {
|
||||
const user_info = mention?.item_info?.user_info;
|
||||
if (user_info) {
|
||||
return {
|
||||
user_id: user_info.userid,
|
||||
nickname: user_info.nickname,
|
||||
image: user_info.image,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
static getNote(note: NoteFromHtml) {
|
||||
return {
|
||||
node_id: note.note_id,
|
||||
xsec_token: note.xsec_token,
|
||||
time: note.time,
|
||||
last_update_time: note.last_update_time,
|
||||
desc: note.desc,
|
||||
title: note.title,
|
||||
image_list: note.image_list,
|
||||
user: note.user,
|
||||
};
|
||||
}
|
||||
static getConnects(message: Connection[]) {
|
||||
return message.map((item) => {
|
||||
const user = item.user;
|
||||
return {
|
||||
fstatus: user.fstatus,
|
||||
xsec_token: user.xsec_token,
|
||||
userid: user.userid,
|
||||
nickname: user.nickname,
|
||||
images: user.images,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
9
packages/xhs/src/libs/xhs-type/connection.ts
Normal file
9
packages/xhs/src/libs/xhs-type/connection.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export type Connection = {
|
||||
type: 'fllow/you';
|
||||
title: string;
|
||||
id: string;
|
||||
track_type: string;
|
||||
user: { fstatus: 'both' | 'follows' | 'fans'; red_official_verify_type: number; xsec_token: string; userid: string; nickname: string; images: string };
|
||||
time: number;
|
||||
score: number;
|
||||
};
|
||||
47
packages/xhs/src/libs/xhs-type/mention.ts
Normal file
47
packages/xhs/src/libs/xhs-type/mention.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
type NoteBase = {
|
||||
/**
|
||||
* note id
|
||||
**/
|
||||
id: string;
|
||||
xsec_token: string;
|
||||
type: 'note_info';
|
||||
user_info: UserInfo;
|
||||
};
|
||||
|
||||
export type UserInfo = {
|
||||
image: string;
|
||||
indicator: '作者';
|
||||
nickname: string;
|
||||
red_official_verify_type: 0;
|
||||
userid: string;
|
||||
xsec_token: string;
|
||||
};
|
||||
export type CommonentInfo = {
|
||||
id: string;
|
||||
content: string;
|
||||
target_comment: CommonentInfo;
|
||||
user_info?: UserInfo;
|
||||
};
|
||||
|
||||
export type MentionItem = {
|
||||
type: 'mention/item';
|
||||
track_type: '2';
|
||||
title: string;
|
||||
user_info: UserInfo;
|
||||
item_info: {} & NoteBase;
|
||||
};
|
||||
export type MentionComment = {
|
||||
type: 'mention/comment';
|
||||
track_type: '8';
|
||||
title: string;
|
||||
item_info: {} & NoteBase;
|
||||
comment_info: CommonentInfo;
|
||||
};
|
||||
export type Mention = MentionItem | MentionComment;
|
||||
|
||||
export type ResponseMession = {
|
||||
has_more: boolean;
|
||||
cursor: string;
|
||||
strCursor: string;
|
||||
message_list: Mention[];
|
||||
};
|
||||
47
packages/xhs/src/libs/xhs-type/note.ts
Normal file
47
packages/xhs/src/libs/xhs-type/note.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
type InteractInfo = {
|
||||
collected_count: string | number;
|
||||
comment_count: string | number;
|
||||
share_count: string | number;
|
||||
followed: boolean;
|
||||
relation: 'both';
|
||||
liked: boolean;
|
||||
liked_count: string | number;
|
||||
collected: boolean;
|
||||
};
|
||||
export type NoteFromHtml = {
|
||||
xsec_token: string;
|
||||
interact_info: InteractInfo;
|
||||
time: number;
|
||||
last_update_time: number;
|
||||
ip_location: string;
|
||||
share_info: {
|
||||
un_share: boolean;
|
||||
};
|
||||
note_id: string;
|
||||
type: 'normal';
|
||||
desc: string;
|
||||
tag_list: string[];
|
||||
at_user_list: { user_id: string; nickname: string; xsec_token: string }[];
|
||||
title: string;
|
||||
user: {
|
||||
user_id: string;
|
||||
nickname: string;
|
||||
avatar: string;
|
||||
xsec_token: string;
|
||||
};
|
||||
image_list: {
|
||||
url: string;
|
||||
trace_id: string;
|
||||
url_per: string;
|
||||
live_photo: boolean;
|
||||
file_id: string;
|
||||
width: number;
|
||||
height: number;
|
||||
info_list: {
|
||||
image_scend: string; // WB_PRV WB_DFT,
|
||||
url: string;
|
||||
}[];
|
||||
url_default: string;
|
||||
stream: any;
|
||||
}[];
|
||||
};
|
||||
210
packages/xhs/src/libs/xhs.ts
Normal file
210
packages/xhs/src/libs/xhs.ts
Normal file
@@ -0,0 +1,210 @@
|
||||
import { XhsClient as XhsClientBase } from '@kevisual/xhs-core';
|
||||
import { Mention, CommonentInfo } from './xhs-type/mention.ts';
|
||||
|
||||
export type Result<T> = {
|
||||
code: number; // 0: success
|
||||
msg?: string;
|
||||
data?: T;
|
||||
success?: boolean;
|
||||
};
|
||||
type SignInfo = {
|
||||
uri: string;
|
||||
data: any;
|
||||
a1: string;
|
||||
web_session?: string;
|
||||
};
|
||||
type SignOptions = {
|
||||
signUrl?: string;
|
||||
};
|
||||
export const getSign = async (signInfo: SignInfo, options?: SignOptions) => {
|
||||
const { uri, data, a1, web_session } = signInfo;
|
||||
// console.log('getSign', uri, data, a1, web_session);
|
||||
// let signUri = new URL(uri, 'http://light.xiongxiao.me:5006').pathname;
|
||||
// signUri = '/api/sns/web/v2/user/me';
|
||||
try {
|
||||
let signUrl = options?.signUrl || 'http://light.xiongxiao.me:5006/sign';
|
||||
// signUrl = 'http://localhost:5005/sign'
|
||||
const signs = await fetch(signUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
uri: uri,
|
||||
data: data,
|
||||
a1,
|
||||
web_session: web_session,
|
||||
}),
|
||||
}).then((res) => res.json());
|
||||
return signs;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
type XhsOptions = {
|
||||
cookie?: string;
|
||||
};
|
||||
type XhsSign = {
|
||||
signUrl?: string;
|
||||
};
|
||||
export class XhsClient extends XhsClientBase {
|
||||
signConfig?: XhsSign;
|
||||
constructor(opts: XhsOptions) {
|
||||
super(opts as any);
|
||||
}
|
||||
printResult(msg: string, response: any) {
|
||||
if (msg === 'response') {
|
||||
console.log('url', response.url);
|
||||
if (response.response) {
|
||||
console.log('status', response.response.status);
|
||||
console.log('data', response.response.data);
|
||||
}
|
||||
} else if (msg === 'request') {
|
||||
// console.log('request', response);
|
||||
} else if (msg === 'html') {
|
||||
// console.log('html', response);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取未读消息
|
||||
* @returns
|
||||
*/
|
||||
async getUnread(): Promise<Result<UnreadCount>> {
|
||||
const url = '/api/sns/web/unread_count';
|
||||
const response = await this.get(url);
|
||||
|
||||
return response;
|
||||
}
|
||||
async postRead(type: 'unread_count' | 'likes' | 'mentions' | 'unread_count' = 'mentions') {
|
||||
const uri = '/api/sns/web/v1/message/read';
|
||||
const data = {
|
||||
type,
|
||||
};
|
||||
type RetrunData = {
|
||||
code: number;
|
||||
msg: string;
|
||||
success: boolean;
|
||||
};
|
||||
const response = await this.post(uri, data, {
|
||||
sign: this.sign.bind(this),
|
||||
});
|
||||
return response as Result<RetrunData>;
|
||||
}
|
||||
async getUserInfoFromHtml(userId: string) {
|
||||
type ReturnData = {
|
||||
ip_location: string;
|
||||
desc: string;
|
||||
imageb: string;
|
||||
nickname: string;
|
||||
images: string;
|
||||
red_id: string;
|
||||
gender: number;
|
||||
};
|
||||
const response = await super.getUserInfoFromHtml(userId);
|
||||
return response as ReturnData;
|
||||
}
|
||||
async getFollowNotifications(num = 10, cursor = '') {
|
||||
const url = '/api/sns/web/v1/you/connections';
|
||||
type Connection = {
|
||||
type: 'fllow/you';
|
||||
title: string;
|
||||
id: string;
|
||||
track_type: string;
|
||||
user: { fstatus: 'both' | 'follows' | 'fans'; red_official_verify_type: number; xsec_token: string; userid: string; nickname: string; images: string };
|
||||
time: number;
|
||||
score: number;
|
||||
};
|
||||
type ReturnData = {
|
||||
message_list: Connection[];
|
||||
has_more: boolean;
|
||||
cursor: number;
|
||||
strCursor: string;
|
||||
};
|
||||
const response = await this.get(url, { num, cursor }, { sign: this.sign.bind(this) });
|
||||
return response as Result<ReturnData>;
|
||||
}
|
||||
async getComment(noteId: string, xsecToken?: string) {}
|
||||
/**
|
||||
*
|
||||
* @uri /api/sns/web/v1/you/mentions
|
||||
* @returns
|
||||
*/
|
||||
async getMention(num = 10): Promise<Result<Mention>> {
|
||||
const url = '/api/sns/web/v1/you/mentions';
|
||||
const response = await this.get(
|
||||
url,
|
||||
{ num },
|
||||
{
|
||||
sign: this.sign.bind(this),
|
||||
// headers: {
|
||||
// 'x-s':
|
||||
// 'XYW_eyJzaWduU3ZuIjoiNTYiLCJzaWduVHlwZSI6IngyIiwiYXBwSWQiOiJsb2dpbiIsInNpZ25WZXJzaW9uIjoiMSIsInBheWxvYWQiOiJiNGJmMGI2MDVkZTlkOWMyY2RlNTI2YmVjNjM2ZmIxMjkxYzUxMTIyYWQyOTk5MzIyMzNjMmU0OTEzMWFmYzgzY2FmOGQzZDIzMTA0Y2RlNWUzZDZlZDczMDg0MmUzYzAxOTNkY2FjZjEyZjk1NTMzZGQzY2ZkMGFmOTg5MGZmMDIwNWI0MmQwOTNiYmJjMGNkZWU3MzdmOGE2MmRkYWVlYjZhMjcxZDViNjZkNGRjYjA1NDg2MGZhNTllN2M5MjE0ZDE2OTJjYWQyZjZmNzE1NThmYWQ3YjQxZjlhZTNiYjA1ZDExN2YzYWI2ZjRjYzY5MzcyMzRhOTY1OTkxYzMwMWY2YjI1MzY4MTZiNzM1YzhmMWEzOTk2ODhkMWU0NDFiODljYTNlNzQ3YWNlN2M2MGIzZDlhZWQwZDVlZDZlNGFhMDE5MmQ5YzZjNDE1M2IxM2RjODAwYjUzZTQxYWEzOTU4MjJhMzYyMmJjODEwYmY4MzA3MjkwMjY2ZDUzNmQwMjdkMTJlOWEwMzhlZmY1YWU4OTM5NDVlNDhmYmY2MCJ9',
|
||||
// 'x-t': '1746097556685',
|
||||
// },
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
async sign(uri: string, data: any, config: any) {
|
||||
let headers = config?.headers || {};
|
||||
const cookieDist = this.getCookieMap();
|
||||
const web_session = cookieDist['web_session'];
|
||||
const a1 = cookieDist['a1'];
|
||||
const res = await getSign({ uri, data, a1, web_session }, this.signConfig);
|
||||
if (res) {
|
||||
headers['x-s'] = res?.['x-s'];
|
||||
headers['x-t'] = res?.['x-t'];
|
||||
config.headers = headers;
|
||||
} else {
|
||||
console.log('get sign error');
|
||||
throw new Error('get sign error');
|
||||
}
|
||||
return config;
|
||||
}
|
||||
async getNoteById(noteId: string, xsecToken?: string) {
|
||||
const data = {
|
||||
source_note_id: noteId,
|
||||
image_scenes: ['CRD_WM_WEBP'],
|
||||
};
|
||||
const uri = '/api/sns/web/v1/feed';
|
||||
|
||||
try {
|
||||
const response = await this.post(uri, data, { sign: this.sign.bind(this) });
|
||||
return response['items'][0]['node_card'];
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 发送评论,content最多为300个字符,如果多余300个字符,发送两次
|
||||
* @param comment
|
||||
* @returns
|
||||
*/
|
||||
async postComment(comment: { note_id: string; comment_id: string; content: string }) {
|
||||
const uri = '/api/sns/web/v1/comment/post';
|
||||
try {
|
||||
const data = {
|
||||
note_id: comment.note_id,
|
||||
content: comment.content,
|
||||
target_comment_id: comment.comment_id,
|
||||
at_users: [], //
|
||||
};
|
||||
type PostCommentResponse = {
|
||||
comment: CommonentInfo;
|
||||
time: number;
|
||||
toast: string;
|
||||
};
|
||||
const response = await this.post(uri, data, { sign: this.sign.bind(this) });
|
||||
return response as Result<PostCommentResponse>;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type UnreadCount = {
|
||||
unread_count: number;
|
||||
likes: number;
|
||||
connections: number;
|
||||
mentions: number;
|
||||
};
|
||||
Reference in New Issue
Block a user