refactor(onebot): inline ctx.bridge.apis.profile/web/groupAlbum direct calls
Remove the remaining ~20 passthrough fields from ApiActionContext spanning four Api areas — most were already dead (no caller) since extended.ts had migrated to direct `ctx.bridge.apis.X` paths in earlier #6 commits. profile area: - setProfile / setOnlineStatus / fetchCustomFace / setGroupAvatar ── all already dead - getProfileLike ── one live caller in extended.ts inlined web area: - getGroupHonorInfo / getGroupEssence / getGroupEssenceAll / sendGroupNotice / getGroupNotice / deleteGroupNotice / getCookiesStr / getCsrfToken / getCredentials / forceFetchClientKey ── all already dead groupAlbum area: - getGroupAlbumList / uploadImageToGroupAlbum / getGroupAlbumMediaList / commentGroupAlbumMedia / deleteGroupAlbumMedia / likeGroupAlbumMedia ── all 7 live callers in actions/group-album.ts inlined to `ctx.bridge.apis.groupAlbum.<m>(...)` friend area: - setFriendRemark ── already dead Behavior preserved: getProfileLike's `userId = 0 → self` semantics keep working because ProfileApi.getLike uses `isSelf = !userId` internally (0 and undefined are equivalent for that check); same default args at the action site (`start = 0`, `count = 10`). Group-album action handlers now wrap the typed Api return values (GroupAlbumMediaResult, GroupAlbumCommentResult) with `as unknown as JsonValue` for okResponse compatibility — the old ctx wrapper was typed `Promise<any>` which silently hid the cast; making the cast explicit doesn't change runtime. Part 4 of the OneBot-side slim-down. 552/552 tests still green.
This commit is contained in:
@@ -790,7 +790,10 @@ export function register(h: ApiHandler, ctx: ApiActionContext): void {
|
||||
|
||||
|
||||
try {
|
||||
const data = await ctx.getProfileLike(userId, start, count);
|
||||
// getLike treats falsy userId as "self" (it does `isSelf = !userId`
|
||||
// internally), so passing 0 or undefined is equivalent — matches the
|
||||
// old `ctx.getProfileLike(userId, start, count)` wrapper exactly.
|
||||
const data = await ctx.bridge.apis.profile.getLike(userId, start, count);
|
||||
return okResponse(data);
|
||||
} catch (e) {
|
||||
return failedResponse(RETCODE.ACTION_FAILED, String(e));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { ApiHandler, ApiActionContext } from '../api-handler';
|
||||
import { asNumber, asString } from '../api-handler';
|
||||
import { RETCODE, failedResponse, okResponse } from '../types';
|
||||
import type { JsonValue } from '../types';
|
||||
|
||||
export function register(h: ApiHandler, ctx: ApiActionContext): void {
|
||||
h.registerAction('get_group_album_list', async (params) => {
|
||||
@@ -8,7 +9,7 @@ export function register(h: ApiHandler, ctx: ApiActionContext): void {
|
||||
if (!groupId) return failedResponse(RETCODE.BAD_REQUEST, 'group_id is required');
|
||||
|
||||
try {
|
||||
const albumList = await ctx.getGroupAlbumList(groupId);
|
||||
const albumList = await ctx.bridge.apis.groupAlbum.list(groupId);
|
||||
return okResponse(albumList);
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'failed to get group album list';
|
||||
@@ -28,7 +29,7 @@ export function register(h: ApiHandler, ctx: ApiActionContext): void {
|
||||
if (!file) return failedResponse(RETCODE.BAD_REQUEST, 'file is required');
|
||||
|
||||
try {
|
||||
await ctx.uploadImageToGroupAlbum(groupId, albumId, albumName, file);
|
||||
await ctx.bridge.apis.groupAlbum.upload(groupId, albumId, albumName, file);
|
||||
return okResponse(null);
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'failed to upload image to group album';
|
||||
@@ -45,8 +46,11 @@ export function register(h: ApiHandler, ctx: ApiActionContext): void {
|
||||
if (!albumId) return failedResponse(RETCODE.BAD_REQUEST, 'album_id is required');
|
||||
|
||||
try {
|
||||
const mediaList = await ctx.getGroupAlbumMediaList(groupId, albumId, attachInfo);
|
||||
return okResponse(mediaList);
|
||||
const mediaList = await ctx.bridge.apis.groupAlbum.getMediaList(groupId, albumId, attachInfo);
|
||||
// GroupAlbumMediaResult is a concrete domain type; okResponse
|
||||
// expects JsonValue. The shape is JSON-compatible — same as the
|
||||
// old ctx wrapper returning `Promise<any>`.
|
||||
return okResponse(mediaList as unknown as JsonValue);
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'failed to get group album media list';
|
||||
return failedResponse(RETCODE.INTERNAL_ERROR, message);
|
||||
@@ -65,8 +69,12 @@ export function register(h: ApiHandler, ctx: ApiActionContext): void {
|
||||
if (!content) return failedResponse(RETCODE.BAD_REQUEST, 'content is required');
|
||||
|
||||
try {
|
||||
const comment = await ctx.commentGroupAlbumMedia(groupId, albumId, lloc, content);
|
||||
return okResponse(comment);
|
||||
const comment = await ctx.bridge.apis.groupAlbum.comment(groupId, albumId, lloc, content);
|
||||
// GroupAlbumCommentResult is a concrete domain type; okResponse
|
||||
// expects JsonValue. The shape is JSON-compatible (no functions
|
||||
// / classes / bigints), so cast is safe — same as the old ctx
|
||||
// wrapper returning `Promise<any>`.
|
||||
return okResponse(comment as unknown as JsonValue);
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'failed to comment on album media';
|
||||
return failedResponse(RETCODE.INTERNAL_ERROR, message);
|
||||
@@ -84,7 +92,7 @@ export function register(h: ApiHandler, ctx: ApiActionContext): void {
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await ctx.likeGroupAlbumMedia(groupId, albumId, batchId, lloc, true);
|
||||
const res = await ctx.bridge.apis.groupAlbum.like(groupId, albumId, batchId, lloc, true);
|
||||
return okResponse(res);
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'failed to set like on album media';
|
||||
@@ -104,7 +112,7 @@ export function register(h: ApiHandler, ctx: ApiActionContext): void {
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await ctx.likeGroupAlbumMedia(groupId, albumId, batchId, lloc, false);
|
||||
const res = await ctx.bridge.apis.groupAlbum.like(groupId, albumId, batchId, lloc, false);
|
||||
return okResponse(res);
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'failed to cancel like on album media';
|
||||
@@ -122,7 +130,7 @@ export function register(h: ApiHandler, ctx: ApiActionContext): void {
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await ctx.deleteGroupAlbumMedia(groupId, albumId, lloc);
|
||||
const res = await ctx.bridge.apis.groupAlbum.delete(groupId, albumId, lloc);
|
||||
return okResponse(res);
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'failed to delete album media';
|
||||
|
||||
@@ -80,9 +80,9 @@ export interface ApiActionContext {
|
||||
// Essence (adapter: bakes the set/unset boolean)
|
||||
setEssenceMsg: (messageId: number) => Promise<void>;
|
||||
deleteEssenceMsg: (messageId: number) => Promise<void>;
|
||||
// Profile reads with OneBot-specific default args
|
||||
getProfileLike: (userId?: number, start?: number, limit?: number) => Promise<any>;
|
||||
getGroupEssence: (groupId: number, pageStart?: number, pageLimit?: number) => Promise<GroupEssenceMsgRet>;
|
||||
// Profile reads and group essence reads: direct via
|
||||
// `ctx.bridge.apis.profile.getLike(...)` and
|
||||
// `ctx.bridge.apis.web.getEssence(...)`.
|
||||
// Friend deletion: direct via `ctx.bridge.apis.friend.delete(userId, block)`.
|
||||
// Module wrappers / multi-dep compositions
|
||||
getGroupMsgHistory: (groupId: number, messageId?: number, count?: number) => Promise<JsonObject[]>;
|
||||
@@ -94,32 +94,18 @@ export interface ApiActionContext {
|
||||
sendForwardMsg: (messages: JsonValue, groupId?: number) => Promise<{ forwardId: string }>;
|
||||
getForwardMsg: (resId: string) => Promise<JsonObject[]>;
|
||||
forwardSingleMsg: (messageId: number, target: { groupId?: number; userId?: number }) => Promise<{ messageId: number }>;
|
||||
// Extended NapCat-compatible
|
||||
setFriendRemark: (userId: number, remark: string) => Promise<void>;
|
||||
setGroupAvatar: (groupId: number, source: string) => Promise<void>;
|
||||
// setMsgEmojiLike: stays because it threads messageStore meta lookup.
|
||||
setMsgEmojiLike: (messageId: number, emojiId: string, set: boolean) => Promise<void>;
|
||||
// markGroupMsgAsRead / markPrivateMsgAsRead: direct via
|
||||
// `ctx.bridge.apis.message.{markGroupRead,markPrivateRead}`.
|
||||
setOnlineStatus: (status: number, extStatus?: number, batteryStatus?: number) => Promise<void>;
|
||||
setProfile: (nickname?: string, personalNote?: string) => Promise<void>;
|
||||
fetchCustomFace: (count?: number) => Promise<string[]>;
|
||||
// getEmojiLikes: direct via `ctx.bridge.apis.interaction.getEmojiLikes(...)`.
|
||||
// Web
|
||||
getGroupHonorInfo: (groupId: number, type: WebHonorType | string) => Promise<any>;
|
||||
getGroupEssenceAll: (groupId: number) => Promise<GroupEssenceMsgRet[]>;
|
||||
getGroupAlbumList: (groupId: number) => Promise<any>;
|
||||
uploadImageToGroupAlbum: (groupId: number, albumId: string, albumName: string, filePath: string) => Promise<void>;
|
||||
getGroupAlbumMediaList: (groupId: number, albumId: string, attachInfo?: string) => Promise<any>;
|
||||
commentGroupAlbumMedia: (groupId: number, albumId: string, lloc: string, content: string) => Promise<any>;
|
||||
deleteGroupAlbumMedia: (groupId: number, albumId: string, lloc: string) => Promise<any>;
|
||||
likeGroupAlbumMedia: (groupId: number, albumId: string, batchId: string, lloc: string | undefined, isLike: boolean) => Promise<any>;
|
||||
sendGroupNotice: (groupId: number, content: string, options?: any) => Promise<any>;
|
||||
getGroupNotice: (groupId: number) => Promise<any[]>;
|
||||
deleteGroupNotice: (groupId: number, fid: string) => Promise<boolean>;
|
||||
getCookiesStr: (domain: string) => Promise<string>;
|
||||
getCsrfToken: () => Promise<number>;
|
||||
getCredentials: (domain: string) => Promise<{ cookies: string; token: number; csrf_token: number }>;
|
||||
forceFetchClientKey: () => Promise<ClientKeyInfo>;
|
||||
// All other extended / NapCat-compatible / Web / Album actions are
|
||||
// accessed directly through `ctx.bridge.apis.<area>.<method>()`:
|
||||
// * profile area: setProfile / setOnlineStatus / fetchCustomFace /
|
||||
// setGroupAvatar / getLike
|
||||
// * friend area: setRemark / delete / handleRequest
|
||||
// * web area: getHonorInfo / getEssence(All) / sendNotice /
|
||||
// getNotice / deleteNotice / getCookiesStr /
|
||||
// getCsrfToken / getCredentials / forceFetchClientKey
|
||||
// * groupAlbum area: list / upload / getMediaList / comment /
|
||||
// delete / like
|
||||
// Media lookup (populated from previously dispatched message segments)
|
||||
getImageInfo: (file: string) => Promise<JsonObject | null>;
|
||||
getRecordInfo: (file: string) => Promise<JsonObject | null>;
|
||||
|
||||
@@ -124,15 +124,6 @@ export function buildApiContext(ref: OneBotInstanceContext): ApiActionContext {
|
||||
// request handling moved to direct `ctx.bridge.apis.friend.handleRequest`.
|
||||
handleGroupRequest: (flag, _subType, approve, reason) => handleGroupAddRequest(bridge, flag, approve, reason),
|
||||
|
||||
// Essence — bake the set/unset boolean.
|
||||
setEssenceMsg: (messageId) => setEssenceMessage(bridge, messageStore, messageId, true),
|
||||
deleteEssenceMsg: (messageId) => setEssenceMessage(bridge, messageStore, messageId, false),
|
||||
|
||||
// Profile-like / get_group_essence — OneBot-specific defaults that the
|
||||
// action handlers don't supply.
|
||||
getProfileLike: (userId = undefined, start = 0, limit = 10) => bridge.apis.profile.getLike(userId, start, limit),
|
||||
getGroupEssence: (groupId, pageStart = 0, pageLimit = 50) => bridge.apis.web.getEssence(groupId, pageStart, pageLimit),
|
||||
|
||||
// Message-store-backed history reads.
|
||||
getGroupMsgHistory: (groupId, messageId, count) => getGroupMsgHistory(messageStore, groupId, messageId, count),
|
||||
getFriendMsgHistory: (userId, messageId, count) => getFriendMsgHistory(messageStore, userId, messageId, count),
|
||||
@@ -145,41 +136,21 @@ export function buildApiContext(ref: OneBotInstanceContext): ApiActionContext {
|
||||
sendForwardMsg: (messages, groupId) => uploadForwardMessage(ref, messages, groupId),
|
||||
getForwardMsg: (resId) => getForwardMessage(ref, resId),
|
||||
forwardSingleMsg: (messageId, target) => forwardSingleMessage(ref, messageId, target),
|
||||
forceFetchClientKey: () => bridge.apis.web.forceFetchClientKey(),
|
||||
setFriendRemark: (userId, remark) => bridge.apis.friend.setRemark(userId, remark),
|
||||
setGroupAvatar: (groupId, source) => bridge.apis.profile.setGroupAvatar(groupId, source),
|
||||
|
||||
// Cross-store: looks up the meta then routes through Bridge.
|
||||
// Essence — bakes the set/unset boolean (the only "compose with
|
||||
// messageStore meta lookup" entry remaining outside of dedicated
|
||||
// module helpers).
|
||||
setEssenceMsg: (messageId) => setEssenceMessage(bridge, messageStore, messageId, true),
|
||||
deleteEssenceMsg: (messageId) => setEssenceMessage(bridge, messageStore, messageId, false),
|
||||
|
||||
// Emoji-like — same shape: meta lookup → bridge call. Group-only
|
||||
// (QQ doesn't expose emoji reactions on private chats).
|
||||
setMsgEmojiLike: async (messageId, emojiId, set) => {
|
||||
const meta = messageStore.findMeta(messageId);
|
||||
if (!meta) throw new Error('message not found');
|
||||
// QQ itself doesn't expose emoji reactions on private chats, so
|
||||
// there is no wire path to forward this to; fail loudly instead
|
||||
// of silently no-op'ing.
|
||||
if (!meta.isGroup) throw new Error('emoji reactions are not supported on private messages');
|
||||
await bridge.apis.interaction.setReaction(meta.targetId, meta.sequence, emojiId, set);
|
||||
},
|
||||
setOnlineStatus: (status: number, extStatus?: number, batteryStatus?: number) => bridge.apis.profile.setOnlineStatus(status, extStatus, batteryStatus),
|
||||
setProfile: (nickname?: string, personalNote?: string) => bridge.apis.profile.setProfile(nickname, personalNote),
|
||||
|
||||
// Web-backed actions.
|
||||
getGroupHonorInfo: (groupId: number, type: WebHonorType | string) => bridge.apis.web.getHonorInfo(groupId, type),
|
||||
getGroupEssenceAll: (groupId) => bridge.apis.web.getEssenceAll(groupId),
|
||||
getGroupAlbumList: (groupId) => bridge.apis.groupAlbum.list(groupId),
|
||||
uploadImageToGroupAlbum: (groupId, albumId, albumName, filePath) => bridge.apis.groupAlbum.upload(groupId, albumId, albumName, filePath),
|
||||
getGroupAlbumMediaList: (groupId, albumId, attachInfo) => bridge.apis.groupAlbum.getMediaList(groupId, albumId, attachInfo),
|
||||
commentGroupAlbumMedia: (groupId, albumId, lloc, content) => bridge.apis.groupAlbum.comment(groupId, albumId, lloc, content),
|
||||
deleteGroupAlbumMedia: (groupId, albumId, lloc) => bridge.apis.groupAlbum.delete(groupId, albumId, lloc),
|
||||
likeGroupAlbumMedia: (groupId, albumId, batchId, lloc, isLike) => bridge.apis.groupAlbum.like(groupId, albumId, batchId, lloc, isLike),
|
||||
sendGroupNotice: (groupId, content, options) => bridge.apis.web.sendNotice(groupId, content, options),
|
||||
getGroupNotice: (groupId) => bridge.apis.web.getNotice(groupId),
|
||||
deleteGroupNotice: (groupId, fid) => bridge.apis.web.deleteNotice(groupId, fid),
|
||||
getCookiesStr: (domain) => bridge.apis.web.getCookiesStr(domain),
|
||||
getCsrfToken: () => bridge.apis.web.getCsrfToken(),
|
||||
getCredentials: (domain) => bridge.apis.web.getCredentials(domain),
|
||||
|
||||
// Extended
|
||||
fetchCustomFace: (count) => bridge.apis.profile.fetchCustomFace(count),
|
||||
|
||||
// Media lookup.
|
||||
getImageInfo: (file) => getCachedImageInfo(mediaStore, file),
|
||||
|
||||
Reference in New Issue
Block a user