diff --git a/src/core/apis/webapi.ts b/src/core/apis/webapi.ts index dd281b00..cede8d2e 100644 --- a/src/core/apis/webapi.ts +++ b/src/core/apis/webapi.ts @@ -12,6 +12,7 @@ import { createReadStream, readFileSync, statSync } from 'node:fs'; import { createHash } from 'node:crypto'; import { basename } from 'node:path'; import { qunAlbumControl } from '../data/webapi'; +import { createAlbumCommentRequest, createAlbumFeedPublish, createAlbumMediaFeed } from '../data/album'; export class NTQQWebApi { context: InstanceContext; core: NapCatCore; @@ -443,4 +444,73 @@ export class NTQQWebApi { if (!session) throw new Error('创建群相册会话失败'); await this.uploadQunAlbumSlice(path, session, skey, pskey, uin, 16384); } + async getAlbumMediaListByNTQQ(gc: string, albumId: string, attach_info: string = '') { + return (await this.context.session.getAlbumService().getMediaList({ + qun_id: gc, + attach_info: attach_info, + seq: 0, + request_time_line: { + request_invoke_time: "0" + }, + album_id: albumId, + lloc: '', + batch_id: '' + })).response; + } + + async doAlbumMediaPlainCommentByNTQQ( + qunId: string, + albumId: string, + lloc: string, + content: string) { + const random_seq = Math.floor(Math.random() * 9000) + 1000; + const uin = this.core.selfInfo.uin || '10001'; + //16位number数字 + const client_key = Date.now() * 1000 + return await this.context.session.getAlbumService().doQunComment( + random_seq, { + map_info: [], + map_bytes_info: [], + map_user_account: [] + }, + qunId, + 2, + createAlbumMediaFeed(uin, albumId, lloc), + createAlbumCommentRequest(uin, content, client_key) + ); + } + + async deleteAlbumMediaByNTQQ( + qunId: string, + albumId: string, + lloc: string) { + const random_seq = Math.floor(Math.random() * 9000) + 1000; + return await this.context.session.getAlbumService().deleteMedias( + random_seq, + qunId, + albumId, + [lloc], + [] + ); + } + + async doAlbumMediaLikeByNTQQ( + qunId: string, + albumId: string, + lloc: string, + id: string) { + const random_seq = Math.floor(Math.random() * 9000) + 1000; + const uin = this.core.selfInfo.uin || '10001'; + return await this.context.session.getAlbumService().doQunLike( + random_seq, { + map_info: [], + map_bytes_info: [], + map_user_account: [] + }, { + id: id, + status: 1 + }, + createAlbumFeedPublish(qunId, uin, albumId, lloc) + ) + } } \ No newline at end of file diff --git a/src/core/data/album.ts b/src/core/data/album.ts new file mode 100644 index 00000000..3568a193 --- /dev/null +++ b/src/core/data/album.ts @@ -0,0 +1,221 @@ +/** + * 群相册列表请求参数接口 + */ +export interface AlbumListRequest { + qun_id: string; + attach_info: string; + seq: number; + request_time_line: { + request_invoke_time: string; + }; + album_id: string; + lloc: string; + batch_id: string; +} + +/** + * 创建群相册列表请求参数 + * @param qunId 群号 + * @param albumId 相册ID + * @param seq 请求序列号,默认值为0 + * @returns 请求参数对象 + */ +export function createAlbumListRequest( + qunId: string, + albumId: string, + seq: number = 0 +): AlbumListRequest { + return { + qun_id: qunId, + attach_info: "", + seq: seq, + request_time_line: { + request_invoke_time: "0" + }, + album_id: albumId, + lloc: "", + batch_id: "" + }; +} + +/** + * 相册媒体项请求接口 + */ +export interface AlbumMediaFeed { + cell_common: { + time: string; + }; + cell_user_info: { + user: { + uin: string; + }; + }; + cell_media: { + album_id: string; + batch_id: string; + media_items: Array<{ + image: { + lloc: string; + }; + }>; + }; +} + +/** + * 创建相册媒体请求参数 + * @param uin 用户QQ号 + * @param albumId 相册ID + * @param lloc + * @returns 媒体请求参数对象 + */ +export function createAlbumMediaFeed( + uin: string, + albumId: string, + lloc: string +): AlbumMediaFeed { + return { + cell_common: { + time: "" + }, + cell_user_info: { + user: { + uin: uin + } + }, + cell_media: { + album_id: albumId, + batch_id: "", + media_items: [{ + image: { + lloc: lloc + } + }] + } + }; +} +/** + * 相册评论内容接口 + */ +export interface AlbumCommentContent { + type: number; + content: string; + who: number; + uid: string; + name: string; + url: string; +} + +/** + * 相册评论请求接口 + */ +export interface AlbumCommentReplyContent { + client_key: number; + content: AlbumCommentContent[]; + user: { + uin: string; + }; +} +export enum RichMsgType { + KRICHMSGTYPEPLAINTEXT, + KRICHMSGTYPEAT, + KRICHMSGTYPEURL, + KRICHMSGTYPEMEDIA +} + +/** + * 创建相册评论请求参数 + * @param uin 用户QQ号 + * @param content 评论内容 + * @param client_key 客户端鉴权密钥 + * @returns 评论请求参数对象 + */ +export function createAlbumCommentRequest( + uin: string, + content: string, + client_key: number +): AlbumCommentReplyContent { + return { + client_key: client_key, + //暂时只支持纯文本吧 + content: [{ + type: RichMsgType.KRICHMSGTYPEPLAINTEXT, + content: content, + who: 0, + uid: "", + name: "", + url: "" + }], + user: { + uin: uin + } + }; +} + +export interface AlbumFeedLikePublish { + cell_common: { + time: number; + feed_id: string; + }; + cell_user_info: { + user: { + uin: string; + }; + }; + cell_media: { + album_id: string; + batch_id: number; + media_items: Array<{ + type: number; + image: { + lloc: string; + sloc: string; + }; + }>; + }; + cell_qun_info: { + qun_id: string; + }; +} + +/** + * 创建相册动态发布请求参数 + * @param qunId 群号 + * @param uin 用户QQ号 + * @param albumId 相册ID + * @param lloc 信息 + * @param sloc 信息(可选,默认与lloc相同) + * @returns 动态发布请求参数对象 + */ +export function createAlbumFeedPublish( + qunId: string, + uin: string, + albumId: string, + lloc: string, + sloc?: string +): AlbumFeedLikePublish { + return { + cell_common: { + time: Date.now(), + feed_id: "" + }, + cell_user_info: { + user: { + uin: uin + } + }, + cell_media: { + album_id: albumId, + batch_id: 0, + media_items: [{ + type: 0, + image: { + lloc: lloc, + sloc: sloc || lloc + } + }] + }, + cell_qun_info: { + qun_id: qunId + } + }; +} \ No newline at end of file diff --git a/src/core/services/NodeIKernelAlbumService.ts b/src/core/services/NodeIKernelAlbumService.ts index 8cd77845..9cc086b2 100644 --- a/src/core/services/NodeIKernelAlbumService.ts +++ b/src/core/services/NodeIKernelAlbumService.ts @@ -1,3 +1,5 @@ +import { AlbumCommentReplyContent, AlbumFeedLikePublish, AlbumListRequest, AlbumMediaFeed } from "../data/album"; + export interface NodeIKernelAlbumService { setAlbumServiceInfo(...args: unknown[]): unknown;// needs 3 arguments @@ -19,7 +21,7 @@ export interface NodeIKernelAlbumService { trace_id: string, is_from_cache: boolean, request_time_line: unknown, - album_list: Array, + album_list: Array<{ name: string, album_id: string }>, attach_info: string, has_more: boolean, right: unknown, @@ -32,11 +34,19 @@ export interface NodeIKernelAlbumService { addAlbum(...args: unknown[]): unknown;// needs 2 arguments - deleteMedias(...args: unknown[]): unknown;// needs 4 arguments + deleteMedias(seq: number, group_code: string, album_id: string, media_ids: string[], ban_ids: unknown[]): Promise;// needs 4 arguments modifyAlbum(...args: unknown[]): unknown;// needs 3 arguments - getMediaList(...args: unknown[]): unknown;// needs 1 arguments + getMediaList(param: AlbumListRequest): Promise<{ + response: { + seq: number, + result: number, + errMs: string,//没错就是errMs不是errMsg + trace_id: string, + request_time_line: unknown, + } + }>;// needs 1 arguments quoteToQzone(...args: unknown[]): unknown;// needs 1 arguments @@ -55,12 +65,36 @@ export interface NodeIKernelAlbumService { getQunLikes(...args: unknown[]): unknown;// needs 4 arguments deleteQunFeed(...args: unknown[]): unknown;// needs 1 arguments - - doQunComment(...args: unknown[]): unknown;// needs 6 arguments + //seq random + //stCommonExt {"map_info":[],"map_bytes_info":[],"map_user_account":[]} + //qunId string + doQunComment(seq: number, ext: { + map_info: unknown[], + map_bytes_info: unknown[], + map_user_account: unknown[] + }, + qunId: string, + commentType: number, + feed: AlbumMediaFeed, + content: AlbumCommentReplyContent, + ): Promise;// needs 6 arguments doQunReply(...args: unknown[]): unknown;// needs 7 arguments - doQunLike(...args: unknown[]): unknown;// needs 5 arguments + doQunLike( + seq: number, + ext: { + map_info: unknown[], + map_bytes_info: unknown[], + map_user_account: unknown[] + }, + param: { + //{"id":"421_1_0_1012959257|V61Yiali4PELg90bThrH4Bo2iI1M5Kab|V5bCgAxMDEyOTU5MjU3e*KqaLVYdic!^||^421_1_0_1012959257|V61Yiali4PELg90bThrH4Bo2iI1M5Kab|17560336594^||^1","status":1} + id: string, + status: number + }, + like: AlbumFeedLikePublish + ): Promise;// needs 5 arguments getRedPoints(...args: unknown[]): unknown;// needs 3 arguments diff --git a/src/onebot/action/extends/DelGroupAlbumMedia.ts b/src/onebot/action/extends/DelGroupAlbumMedia.ts new file mode 100644 index 00000000..44a0ef80 --- /dev/null +++ b/src/onebot/action/extends/DelGroupAlbumMedia.ts @@ -0,0 +1,24 @@ +import { OneBotAction } from '@/onebot/action/OneBotAction'; +import { ActionName } from '@/onebot/action/router'; +import { Static, Type } from '@sinclair/typebox'; + +const SchemaData = Type.Object({ + group_id: Type.String(), + album_id: Type.String(), + lloc: Type.String() +}); + +type Payload = Static; + +export class DelGroupAlbumMedia extends OneBotAction { + override actionName = ActionName.DelGroupAlbumMedia; + override payloadSchema = SchemaData; + + async _handle(payload: Payload) { + return await this.core.apis.WebApi.deleteAlbumMediaByNTQQ( + payload.group_id, + payload.album_id, + payload.lloc + ); + } +} diff --git a/src/onebot/action/extends/DoGroupAlbumComment.ts b/src/onebot/action/extends/DoGroupAlbumComment.ts new file mode 100644 index 00000000..9153345e --- /dev/null +++ b/src/onebot/action/extends/DoGroupAlbumComment.ts @@ -0,0 +1,26 @@ +import { OneBotAction } from '@/onebot/action/OneBotAction'; +import { ActionName } from '@/onebot/action/router'; +import { Static, Type } from '@sinclair/typebox'; + +const SchemaData = Type.Object({ + group_id: Type.String(), + album_id: Type.String(), + lloc: Type.String(), + content: Type.String(), +}); + +type Payload = Static; + +export class DoGroupAlbumComment extends OneBotAction { + override actionName = ActionName.DoGroupAlbumComment; + override payloadSchema = SchemaData; + + async _handle(payload: Payload) { + return await this.core.apis.WebApi.doAlbumMediaPlainCommentByNTQQ( + payload.group_id, + payload.album_id, + payload.lloc, + payload.content + ); + } +} diff --git a/src/onebot/action/extends/GetGroupAlbumMediaList.ts b/src/onebot/action/extends/GetGroupAlbumMediaList.ts new file mode 100644 index 00000000..be14af05 --- /dev/null +++ b/src/onebot/action/extends/GetGroupAlbumMediaList.ts @@ -0,0 +1,24 @@ +import { OneBotAction } from '@/onebot/action/OneBotAction'; +import { ActionName } from '@/onebot/action/router'; +import { Static, Type } from '@sinclair/typebox'; + +const SchemaData = Type.Object({ + group_id: Type.String(), + album_id: Type.String(), + attach_info: Type.String({ default: "" }), +}); + +type Payload = Static; + +export class GetGroupAlbumMediaList extends OneBotAction { + override actionName = ActionName.GetGroupAlbumMediaList; + override payloadSchema = SchemaData; + + async _handle(payload: Payload) { + return await this.core.apis.WebApi.getAlbumMediaListByNTQQ( + payload.group_id, + payload.album_id, + payload.attach_info + ); + } +} diff --git a/src/onebot/action/extends/SetGroupAlbumMediaLike.ts b/src/onebot/action/extends/SetGroupAlbumMediaLike.ts new file mode 100644 index 00000000..f5c12aff --- /dev/null +++ b/src/onebot/action/extends/SetGroupAlbumMediaLike.ts @@ -0,0 +1,27 @@ +import { OneBotAction } from '@/onebot/action/OneBotAction'; +import { ActionName } from '@/onebot/action/router'; +import { Static, Type } from '@sinclair/typebox'; + +const SchemaData = Type.Object({ + group_id: Type.String(), + album_id: Type.String(), + lloc: Type.String(), + id: Type.String(),//421_1_0_1012959257|V61Yiali4PELg90bThrH4Bo2iI1M5Kab|V5bCgAxMDEyOTU5MjU3.PyqaPndPxg!^||^421_1_0_1012959257|V61Yiali4PELg90bThrH4Bo2iI1M5Kab|17560363448^||^1 + set: Type.Boolean({default: true})//true=点赞 false=取消点赞 未实现 +}); + +type Payload = Static; + +export class SetGroupAlbumMediaLike extends OneBotAction { + override actionName = ActionName.SetGroupAlbumMediaLike; + override payloadSchema = SchemaData; + + async _handle(payload: Payload) { + return await this.core.apis.WebApi.doAlbumMediaLikeByNTQQ( + payload.group_id, + payload.album_id, + payload.lloc, + payload.id + ); + } +} diff --git a/src/onebot/action/index.ts b/src/onebot/action/index.ts index 8da0e02d..d6187237 100644 --- a/src/onebot/action/index.ts +++ b/src/onebot/action/index.ts @@ -126,10 +126,18 @@ import { GetCollectionList } from './extends/GetCollectionList'; import { SetGroupTodo } from './packet/SetGroupTodo'; import { GetQunAlbumList } from './extends/GetQunAlbumList'; import { UploadImageToQunAlbum } from './extends/UploadImageToQunAlbum'; +import { DoGroupAlbumComment } from './extends/DoGroupAlbumComment'; +import { GetGroupAlbumMediaList } from './extends/GetGroupAlbumMediaList'; +import { SetGroupAlbumMediaLike } from './extends/SetGroupAlbumMediaLike'; +import { DelGroupAlbumMedia } from './extends/DelGroupAlbumMedia'; export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore) { const actionHandlers = [ + new DelGroupAlbumMedia(obContext, core), + new SetGroupAlbumMediaLike(obContext, core), + new DoGroupAlbumComment(obContext, core), + new GetGroupAlbumMediaList(obContext, core), new GetQunAlbumList(obContext, core), new UploadImageToQunAlbum(obContext, core), new SetGroupTodo(obContext, core), diff --git a/src/onebot/action/router.ts b/src/onebot/action/router.ts index 6fbc59c3..c2ed5a00 100644 --- a/src/onebot/action/router.ts +++ b/src/onebot/action/router.ts @@ -10,6 +10,10 @@ export interface InvalidCheckResult { } export const ActionName = { + DelGroupAlbumMedia: 'del_group_album_media', + SetGroupAlbumMediaLike: 'set_group_album_media_like', + DoGroupAlbumComment: 'do_group_album_comment', + GetGroupAlbumMediaList: 'get_group_album_media_list', UploadImageToQunAlbum: 'upload_image_to_qun_album', GetQunAlbumList: 'get_qun_album_list', SetGroupTodo: 'set_group_todo',