@lumia.wang/koishi-plugin-adapter-bilibili 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,6 +5,7 @@ Other plugins can use these methods on an authenticated `bot.internal` without m
5
5
  | Method | Result |
6
6
  | --- | --- |
7
7
  | `getVideoSubtitle(bvid)` | `{ bvid, cid, language, text }`; `text` is empty when no subtitle track exists |
8
+ | `getVideoAudio(bvid, { maxDuration?, maxBytes? })` | Since 0.1.2: `{ bvid, cid, duration, mime: 'audio/mp4', data: Buffer }` for the first part's AAC track |
8
9
  | `getVideoComments(bvid, options?)` | Normalized comments with string IDs, text, author, likes and mention presence |
9
10
  | `getUserVideos(uid, { days?, pages? })` | Recent submissions, ordered by publication time |
10
11
  | `getRelatedVideos(bvid)` | Related videos as `VideoBrief[]` |
@@ -15,6 +16,7 @@ Other plugins can use these methods on an authenticated `bot.internal` without m
15
16
 
16
17
  `getVideoComments` accepts `limit` (1–60), `root` (thread root ID), `sort` (`hot` or `time`), and `anonymous`.
17
18
  `getUserVideos` accepts `days` (1–90, default 7) and `pages` (1–5, default 2).
19
+ `getVideoAudio` defaults to 600 seconds and 32 MiB. Callers may choose smaller limits, up to 1800 seconds and 64 MiB. Invalid limits, excessive duration, an unavailable AAC track, empty downloads and excessive download size throw errors. Interrupted/oversized streams are closed. Audio downloads use the context HTTP client without the adapter Cookie, while playback URL requests reuse the account and WBI signature. No external downloader or media process is started.
18
20
  Mention objects are `{ id: 'numeric UID', name: 'exact nickname' }`; include the matching `@nickname` in the text. IDs should be passed as strings.
19
21
 
20
22
  These new APIs propagate request failures and Bilibili error codes instead of treating them as empty content. A missing comment receipt does not trigger a retry. Existing `sendComment` behavior is unchanged: it remains a reply-only API for received comment targets.
@@ -0,0 +1,51 @@
1
+ import { Context } from 'koishi';
2
+ import type { BilibiliDmBot } from '../../bot/bot';
3
+ export interface BilibiliCommentNotification {
4
+ id: string;
5
+ oid: number;
6
+ type: 1 | 11;
7
+ channelId: string;
8
+ userId: string;
9
+ userName: string;
10
+ userAvatar: string;
11
+ content: string;
12
+ timestamp: number;
13
+ rpid: number;
14
+ root: number;
15
+ parent: number;
16
+ mentions: BilibiliMention[];
17
+ }
18
+ export interface BilibiliMention {
19
+ id: string;
20
+ name: string;
21
+ }
22
+ export interface BilibiliCommentTarget {
23
+ oid: number;
24
+ type: 1 | 11;
25
+ rpid: number;
26
+ root: number;
27
+ parent: number;
28
+ }
29
+ export interface BilibiliCommentMention {
30
+ id: string;
31
+ name: string;
32
+ }
33
+ export declare class CommentAPI {
34
+ private readonly bot;
35
+ private readonly ctx;
36
+ private intervalId;
37
+ private isPolling;
38
+ private initialized;
39
+ private requestActive;
40
+ private readonly processedIds;
41
+ private readonly unavailableVideos;
42
+ constructor(bot: BilibiliDmBot, ctx: Context);
43
+ startPolling(interval: number): void;
44
+ stopPolling(): void;
45
+ isPollingActive(): boolean;
46
+ sendComment(channelId: string, content: string, target?: BilibiliCommentTarget, mentions?: BilibiliCommentMention[]): Promise<string | null>;
47
+ private poll;
48
+ private fetchNotifications;
49
+ private parseNotification;
50
+ private createNotification;
51
+ }
@@ -0,0 +1,108 @@
1
+ import { BilibiliDmBot } from '../../bot/bot';
2
+ import { Context } from 'koishi';
3
+ import { DynamicItem, DynamicSummary } from './types';
4
+ export declare class DynamicAPI {
5
+ private bot;
6
+ private ctx;
7
+ private pollIntervalId;
8
+ private isPolling;
9
+ private pollInterval;
10
+ private lastDynamicBaseline;
11
+ private recentDynamics;
12
+ private maxRecentCount;
13
+ private dataFilePath;
14
+ constructor(bot: BilibiliDmBot, ctx: Context);
15
+ /**
16
+ * 确保数据目录存在
17
+ */
18
+ private ensureDataDir;
19
+ /**
20
+ * 加载最近动态数据
21
+ */
22
+ private loadRecentDynamics;
23
+ /**
24
+ * 保存最近动态数据
25
+ */
26
+ private saveRecentDynamics;
27
+ /**
28
+ * 生成动态内容的hash
29
+ */
30
+ private generateDynamicHash;
31
+ /**
32
+ * 将动态转换为摘要信息
33
+ */
34
+ private dynamicToSummary;
35
+ /**
36
+ * 获取指定 UP 主的动态
37
+ * @param uid UP 主的 UID
38
+ * @param offset 分页偏移量
39
+ * @returns Promise<DynamicItem[]> 指定 UP 主的动态列表
40
+ */
41
+ getPersonalDynamics(uid: string, offset?: string): Promise<DynamicItem[]>;
42
+ /**
43
+ * 获取动态详情
44
+ * @param dynamicId 动态 ID
45
+ * @returns Promise<DynamicItem | null> 动态详情
46
+ */
47
+ getDynamicDetail(dynamicId: string): Promise<DynamicItem | null>;
48
+ /**
49
+ * 获取所有关注的 UP 主的动态
50
+ * @param offset 分页偏移量
51
+ * @param updateBaseline 更新基线
52
+ * @returns Promise<DynamicItem[]> 所有关注的 UP 主的动态列表
53
+ */
54
+ getAllFollowedDynamics(offset?: string, updateBaseline?: string): Promise<DynamicItem[]>;
55
+ /**
56
+ * 开始监听动态更新
57
+ * @param interval 轮询间隔(毫秒),默认60秒
58
+ */
59
+ startDynamicPolling(interval?: number): void;
60
+ /**
61
+ * 停止监听动态更新
62
+ */
63
+ stopDynamicPolling(): void;
64
+ /**
65
+ * 初始化最近动态列表
66
+ */
67
+ private initializeRecentDynamics;
68
+ /**
69
+ * 检查新动态
70
+ */
71
+ private checkForNewDynamics;
72
+ /**
73
+ * 触发动态事件
74
+ */
75
+ private emitDynamicEvent;
76
+ /**
77
+ * 解析动态内容
78
+ */
79
+ private parseDynamicContent;
80
+ /**
81
+ * 根据动态类型获取事件名称
82
+ */
83
+ private getDynamicEventName;
84
+ /**
85
+ * 获取监听状态
86
+ */
87
+ isPollingActive(): boolean;
88
+ /**
89
+ * 设置轮询间隔
90
+ */
91
+ setPollInterval(interval: number): void;
92
+ /**
93
+ * 获取当前基线
94
+ */
95
+ getCurrentBaseline(): string;
96
+ /**
97
+ * 设置基线
98
+ */
99
+ setBaseline(baseline: string): void;
100
+ /**
101
+ * 获取最近动态摘要(用于调试)
102
+ */
103
+ getRecentDynamicsSummary(): DynamicSummary[];
104
+ /**
105
+ * 手动触发一次检查
106
+ */
107
+ manualCheck(): Promise<void>;
108
+ }
@@ -0,0 +1,91 @@
1
+ import { BilibiliDmBot } from '../../bot/bot';
2
+ import { Context } from 'koishi';
3
+ import { LiveUser, LiveSummary } from './types';
4
+ export declare class LiveAPI {
5
+ private bot;
6
+ private ctx;
7
+ private pollIntervalId;
8
+ private isPolling;
9
+ private pollInterval;
10
+ private currentLiveUsers;
11
+ private dataFilePath;
12
+ constructor(bot: BilibiliDmBot, ctx: Context);
13
+ /**
14
+ * 确保数据目录存在
15
+ */
16
+ private ensureDataDir;
17
+ /**
18
+ * 加载当前直播用户数据
19
+ */
20
+ private loadCurrentLiveUsers;
21
+ /**
22
+ * 保存当前直播用户数据
23
+ */
24
+ private saveCurrentLiveUsers;
25
+ /**
26
+ * 生成直播用户的hash
27
+ */
28
+ private generateLiveUserHash;
29
+ /**
30
+ * 将直播用户转换为摘要信息
31
+ */
32
+ private liveUserToSummary;
33
+ /**
34
+ * 获取当前正在直播的UP主列表
35
+ * @returns Promise<LiveUser[] | null> 正在直播的UP主列表,网络错误时返回null
36
+ */
37
+ getLiveUsers(): Promise<LiveUser[] | null>;
38
+ /**
39
+ * 开始监听直播状态更新
40
+ * @param interval 轮询间隔(毫秒),默认30秒
41
+ */
42
+ startLivePolling(interval?: number): void;
43
+ /**
44
+ * 停止监听直播状态更新
45
+ */
46
+ stopLivePolling(): void;
47
+ /**
48
+ * 初始化当前直播列表
49
+ */
50
+ private initializeCurrentLiveUsers;
51
+ /**
52
+ * 检查直播状态变化
53
+ */
54
+ private checkForLiveStatusChanges;
55
+ /**
56
+ * 触发开播事件
57
+ */
58
+ private emitLiveStartEvent;
59
+ /**
60
+ * 触发下播事件
61
+ */
62
+ private emitLiveEndEvent;
63
+ /**
64
+ * 触发直播信息更新事件
65
+ */
66
+ private emitLiveUpdateEvent;
67
+ /**
68
+ * 获取监听状态
69
+ */
70
+ isPollingActive(): boolean;
71
+ /**
72
+ * 设置轮询间隔
73
+ */
74
+ setPollInterval(interval: number): void;
75
+ /**
76
+ * 获取当前直播用户摘要(用于调试)
77
+ */
78
+ getCurrentLiveUsersSummary(): LiveSummary[];
79
+ /**
80
+ * 手动触发一次检查
81
+ */
82
+ manualCheck(): Promise<void>;
83
+ /**
84
+ * 获取指定UP主的直播状态
85
+ */
86
+ getUserLiveStatus(mid: number): Promise<LiveUser | null>;
87
+ /**
88
+ * 检查指定UP主是否正在直播
89
+ */
90
+ isUserLive(mid: number): Promise<boolean | null>;
91
+ }
@@ -0,0 +1,10 @@
1
+ import { LiveRoomInfo } from './types';
2
+ import { BilibiliDmBot } from '../../bot/bot';
3
+ export declare class LiveRoomAPI {
4
+ private bot;
5
+ constructor(bot: BilibiliDmBot);
6
+ getRoomInfo(roomId: number): Promise<LiveRoomInfo>;
7
+ enterRoom(roomId: number): Promise<void>;
8
+ heartbeat(roomId: number): Promise<void>;
9
+ getDanmakuInfo(roomId: number): Promise<any>;
10
+ }
@@ -0,0 +1,41 @@
1
+ import { BilibiliDmBot } from '../../bot/bot';
2
+ import { LiveChatEventData } from './types';
3
+ export declare class LiveWebSocketManager {
4
+ private bot;
5
+ private onMessage;
6
+ private ws;
7
+ private heartbeatTimer;
8
+ private currentRoomId;
9
+ private isConnected;
10
+ private reconnectAttempts;
11
+ private maxReconnectAttempts;
12
+ private reconnectDelay;
13
+ private liveRoomAPI;
14
+ private disposed;
15
+ private autoReconnect;
16
+ constructor(bot: BilibiliDmBot, onMessage: (data: LiveChatEventData) => void);
17
+ dispose(): void;
18
+ setLiveRoomAPI(liveRoomAPI: any): void;
19
+ enterRoom(roomId: number): Promise<void>;
20
+ leaveRoom(): Promise<void>;
21
+ private connectWebSocket;
22
+ private sendAuthPacket;
23
+ private generateBuvid;
24
+ private generateQueueUuid;
25
+ private createPacket;
26
+ private parseHeader;
27
+ private handleMessage;
28
+ private processPacket;
29
+ private handleLiveMessage;
30
+ private parseRawMessage;
31
+ private processLiveMessage;
32
+ private parseDanmuMsg;
33
+ private parseSendGift;
34
+ private parseWelcome;
35
+ private parseInteractWord;
36
+ private startHeartbeat;
37
+ private stopHeartbeat;
38
+ private disconnect;
39
+ getCurrentRoomId(): number | null;
40
+ isConnectedToRoom(): boolean;
41
+ }
@@ -0,0 +1,16 @@
1
+ import { BilibiliDmBot } from '../../bot/bot';
2
+ import { ComprehensiveSearchResponse, SearchArticle, SearchLiveRoom, SearchLiveUser, SearchOptions, SearchUser, SearchVideo } from './types';
3
+ export declare class SearchAPI {
4
+ private bot;
5
+ constructor(bot: BilibiliDmBot);
6
+ comprehensiveSearch(keyword: string): Promise<ComprehensiveSearchResponse | null>;
7
+ searchUsers(keyword: string, options?: SearchOptions): Promise<SearchUser[]>;
8
+ searchVideos(keyword: string, options?: SearchOptions): Promise<SearchVideo[]>;
9
+ searchLive(keyword: string, options?: SearchOptions): Promise<{
10
+ liveRooms: SearchLiveRoom[];
11
+ liveUsers: SearchLiveUser[];
12
+ }>;
13
+ searchArticles(keyword: string, options?: SearchOptions): Promise<SearchArticle[]>;
14
+ searchUsersByName(username: string, exactMatch?: boolean): Promise<SearchUser[]>;
15
+ searchUpUsers(keyword: string, options?: SearchOptions): Promise<SearchUser[]>;
16
+ }
@@ -0,0 +1,48 @@
1
+ import { BilibiliDmBot } from '../../bot/bot';
2
+ import { FollowingUser } from './types';
3
+ export declare class UserAPI {
4
+ private bot;
5
+ constructor(bot: BilibiliDmBot);
6
+ /**
7
+ * 关注指定 UP 主
8
+ * @param uid UP 主的 UID
9
+ * @returns Promise<boolean> 是否成功关注
10
+ */
11
+ followUser(uid: string): Promise<boolean>;
12
+ /**
13
+ * 取消关注指定 UP 主
14
+ * @param uid UP 主的 UID
15
+ * @returns Promise<boolean> 是否成功取消关注
16
+ */
17
+ unfollowUser(uid: string): Promise<boolean>;
18
+ /**
19
+ * 获取关注的用户列表
20
+ * @param maxPages 最大页数,默认10页
21
+ * @returns Promise<FollowingUser[]> 关注的用户列表
22
+ */
23
+ getFollowedUsers(maxPages?: number): Promise<FollowingUser[]>;
24
+ /**
25
+ * 获取用户信息
26
+ * @param uid 用户UID
27
+ * @returns Promise<any> 用户信息
28
+ */
29
+ getUserInfo(uid: string): Promise<any>;
30
+ /**
31
+ * 检查是否关注了指定用户
32
+ * @param uid 用户UID
33
+ * @returns Promise<boolean> 是否已关注
34
+ */
35
+ isFollowing(uid: string): Promise<boolean>;
36
+ /**
37
+ * 批量检查关注状态
38
+ * @param uids 用户UID列表
39
+ * @returns Promise<Record<string, boolean>> UID到关注状态的映射
40
+ */
41
+ batchCheckFollowing(uids: string[]): Promise<Record<string, boolean>>;
42
+ /**
43
+ * 获取指定UID的登录cookie数据
44
+ * @param uid 登录bot的UID
45
+ * @returns Promise<any | null> 返回cookie数据,如果文件不存在则返回null
46
+ */
47
+ getTokenByUid(uid: string): Promise<any | null>;
48
+ }
@@ -0,0 +1,9 @@
1
+ import { BilibiliDmBot } from '../../bot/bot';
2
+ import { ExternalParseResponse, VideoConclusionData, VideoData } from './types';
3
+ export declare class VideoAPI {
4
+ private bot;
5
+ constructor(bot: BilibiliDmBot);
6
+ getVideoInfo(bvid: string): Promise<VideoData | null>;
7
+ parseExternalUrl(url: string, accessKey?: string): Promise<ExternalParseResponse | null>;
8
+ getVideoConclusion(bvid: string, cid: number, up_mid: number): Promise<VideoConclusionData | null>;
9
+ }
@@ -45,7 +45,19 @@ export interface FavoriteFolder {
45
45
  id: number;
46
46
  title: string;
47
47
  }
48
+ export interface VideoAudioOptions {
49
+ maxDuration?: number;
50
+ maxBytes?: number;
51
+ }
52
+ export interface VideoAudio {
53
+ bvid: string;
54
+ cid: number;
55
+ duration: number;
56
+ mime: 'audio/mp4';
57
+ data: Buffer;
58
+ }
48
59
  export interface VideoToolkit {
60
+ getVideoAudio(bvid: string, options?: VideoAudioOptions): Promise<VideoAudio>;
49
61
  getVideoSubtitle(bvid: string): Promise<VideoSubtitle>;
50
62
  getVideoComments(bvid: string, options?: VideoCommentOptions): Promise<VideoComment[]>;
51
63
  getUserVideos(uid: string, options?: UserVideoOptions): Promise<VideoBrief[]>;
@@ -64,6 +76,8 @@ export declare class VideoToolkitAPI implements VideoToolkit {
64
76
  private post;
65
77
  private info;
66
78
  getVideoSubtitle(bvid: string): Promise<VideoSubtitle>;
79
+ /** Downloads one bounded AAC track for Node-based audio processing. */
80
+ getVideoAudio(bvid: string, options?: VideoAudioOptions): Promise<VideoAudio>;
67
81
  getVideoComments(bvid: string, options?: VideoCommentOptions): Promise<VideoComment[]>;
68
82
  getUserVideos(uid: string, options?: UserVideoOptions): Promise<VideoBrief[]>;
69
83
  getRelatedVideos(bvid: string): Promise<VideoBrief[]>;
@@ -1,6 +1,6 @@
1
1
  import { Context } from 'koishi';
2
2
  import { BilibiliDmBot } from '../bot/bot';
3
- import { VideoCommentOptions, UserVideoOptions } from './apis/videoToolkit';
3
+ import { VideoCommentOptions, UserVideoOptions, VideoAudioOptions } from './apis/videoToolkit';
4
4
  import { BilibiliCommentMention, BilibiliCommentTarget } from './apis/comment';
5
5
  import { DynamicItem, FollowingUser, InternalInterface, SearchUser, SearchVideo, SearchLiveRoom, SearchLiveUser, SearchArticle, ComprehensiveSearchResponse, SearchOptions, VideoData, ExternalParseResponse, VideoConclusionData } from './apis/types';
6
6
  export declare class Internal implements InternalInterface {
@@ -21,6 +21,7 @@ export declare class Internal implements InternalInterface {
21
21
  isCommentPollingActive(): boolean;
22
22
  sendComment(channelId: string, content: string, target?: BilibiliCommentTarget, mentions?: BilibiliCommentMention[]): Promise<string | null>;
23
23
  getVideoSubtitle(bvid: string): Promise<import(".").VideoSubtitle>;
24
+ getVideoAudio(bvid: string, options?: VideoAudioOptions): Promise<import(".").VideoAudio>;
24
25
  getVideoComments(bvid: string, options?: VideoCommentOptions): Promise<import(".").VideoComment[]>;
25
26
  getUserVideos(uid: string, options?: UserVideoOptions): Promise<import(".").VideoBrief[]>;
26
27
  getRelatedVideos(bvid: string): Promise<import(".").VideoBrief[]>;
@@ -0,0 +1 @@
1
+ export declare function getBilibiliErrorMessage(code: number): string;
@@ -0,0 +1,17 @@
1
+ import { BilibiliService } from './service';
2
+ import { Adapter, Context } from 'koishi';
3
+ import { PluginConfig } from './types';
4
+ import { BilibiliDmBot } from './bot';
5
+ export interface BilibiliAdapterConfig extends PluginConfig {
6
+ service: BilibiliService;
7
+ }
8
+ export declare class BilibiliDmAdapter extends Adapter<Context, BilibiliDmBot> {
9
+ config: BilibiliAdapterConfig;
10
+ static immediate: boolean;
11
+ private readonly services;
12
+ constructor(ctx: Context, config: BilibiliAdapterConfig);
13
+ start(): Promise<void>;
14
+ fork(parent?: Context, config?: any, error?: any): Promise<this>;
15
+ dispose(): Promise<void>;
16
+ startBot(pluginConfig: PluginConfig, service: BilibiliService): Promise<void>;
17
+ }
@@ -0,0 +1,173 @@
1
+ import { Bot, Context, Fragment, Universal } from 'koishi';
2
+ import { BilibiliMessageEncoder } from './messageEncoder';
3
+ import { Internal } from '../bilibiliAPI/internal';
4
+ import { BilibiliCookie } from './types';
5
+ import { BilibiliCommentMention, BilibiliCommentNotification } from '../bilibiliAPI/apis/comment';
6
+ import { PluginConfig } from './types';
7
+ import { HttpClient } from './http';
8
+ import type { BilibiliService } from './service';
9
+ declare module 'koishi' {
10
+ interface Context {
11
+ internal: Internal;
12
+ }
13
+ interface Events {
14
+ 'bilibili/live'(data: {
15
+ id: string;
16
+ uid: string;
17
+ name: string;
18
+ avatar: string;
19
+ timestamp: number;
20
+ action: string;
21
+ type: string;
22
+ room_id: string;
23
+ title: string;
24
+ cover: string;
25
+ jump_url: string;
26
+ }): void;
27
+ 'bilibili/dynamic'(data: {
28
+ id: string;
29
+ uid: string;
30
+ name: string;
31
+ avatar: string;
32
+ timestamp: number;
33
+ action: string;
34
+ type: string;
35
+ text: string;
36
+ jump_url: string;
37
+ cover: string;
38
+ title?: string;
39
+ description?: string;
40
+ bvid?: string;
41
+ aid?: string;
42
+ images?: string[];
43
+ cvid?: number;
44
+ }): void;
45
+ 'bilibili/live-chat'(data: {
46
+ roomId: number;
47
+ roomInfo: {
48
+ title: string;
49
+ uname: string;
50
+ face: string;
51
+ area_name: string;
52
+ online: number;
53
+ };
54
+ message: {
55
+ type: 'danmaku' | 'gift' | 'welcome' | 'guard_buy' | 'super_chat' | 'other' | 'interact' | 'entry_effect' | 'watched_change';
56
+ data: any;
57
+ timestamp: number;
58
+ raw: any;
59
+ };
60
+ }): void;
61
+ }
62
+ }
63
+ export declare class BilibiliDmBot extends Bot<Context, PluginConfig> {
64
+ ctx: Context;
65
+ private readonly service;
66
+ static inject: string[];
67
+ static MessageEncoder: typeof BilibiliMessageEncoder;
68
+ private lastPollTs;
69
+ private processedMsgIds;
70
+ private readonly _maxCacheSize;
71
+ private cleanupFunctions;
72
+ private isStopping;
73
+ private botOnlineTimestamp;
74
+ private consecutiveFailures;
75
+ private currentPollInterval;
76
+ private readonly _msgIdExpireTime;
77
+ private startTask;
78
+ private loginReady;
79
+ private loginCancelled;
80
+ private readonly loginReadyPromise;
81
+ private resolveLoginReady;
82
+ private readonly commentTargets;
83
+ readonly http: HttpClient;
84
+ readonly pluginConfig: PluginConfig;
85
+ readonly internal: Internal;
86
+ constructor(ctx: Context, config: PluginConfig, service: BilibiliService);
87
+ addCleanup(fn: () => void): void;
88
+ markLoginReady(): void;
89
+ cancelLogin(): void;
90
+ private handlePollSuccess;
91
+ private handlePollFailure;
92
+ private autoShutdown;
93
+ private startPolling;
94
+ private startDynamicPolling;
95
+ private startLivePolling;
96
+ private startCommentPolling;
97
+ private startContinuousPolling;
98
+ private poll;
99
+ /**
100
+ * 根据消息来源获取消息前缀
101
+ */
102
+ private getMessagePrefix;
103
+ private adaptMessage;
104
+ start(): Promise<void>;
105
+ private startInternal;
106
+ stop(): Promise<void>;
107
+ /**
108
+ * 启动消息ID定期清理
109
+ */
110
+ private startMessageIdCleanup;
111
+ saveCookie(cookie: BilibiliCookie): Promise<void>;
112
+ getSelf(): Promise<Universal.User>;
113
+ getUser(userId: string): Promise<Universal.User>;
114
+ /**
115
+ * 创建私聊频道
116
+ * @param userId 用户ID
117
+ * @returns 频道信息
118
+ */
119
+ createDirectChannel(userId: string): Promise<{
120
+ id: string;
121
+ type: Universal.Channel.Type;
122
+ }>;
123
+ /**
124
+ * 获取登录信息
125
+ * @returns 登录信息
126
+ */
127
+ toJSON(): Universal.Login;
128
+ getLogin(): Promise<Universal.Login>;
129
+ /**
130
+ * 获取好友列表
131
+ * @returns 好友列表
132
+ */
133
+ getFriendList(): Promise<{
134
+ data: any[];
135
+ }>;
136
+ sendMessage(channelId: string, content: Fragment): Promise<string[]>;
137
+ sendComment(channelId: string, content: string, mentions?: BilibiliCommentMention[]): Promise<string | null>;
138
+ receiveComment(notification: BilibiliCommentNotification): Promise<void>;
139
+ private parseCommentContent;
140
+ private preprocessContent;
141
+ sendPrivateMessage(userId: string, content: Fragment): Promise<string[]>;
142
+ getMessage(channelId: string, messageId: string): Promise<Universal.Message | undefined>;
143
+ /**
144
+ * 获取消息列表
145
+ * @param channelId 频道ID
146
+ * @param next 分页参数
147
+ * @param direction 方向
148
+ * @param limit 限制数量
149
+ * @param order 排序
150
+ * @returns 消息列表
151
+ */
152
+ getMessageList(channelId: string, next?: string, direction?: Universal.Direction, limit?: number, order?: Universal.Order): Promise<{
153
+ data: Universal.Message[];
154
+ }>;
155
+ deleteMessage(channelId: string, messageId: string): Promise<void>;
156
+ /**
157
+ * 进入指定直播间
158
+ * @param roomId 直播间ID
159
+ */
160
+ enterLiveRoom(roomId: number): Promise<void>;
161
+ /**
162
+ * 退出当前直播间
163
+ */
164
+ leaveLiveRoom(): Promise<void>;
165
+ /**
166
+ * 获取当前所在的直播间ID
167
+ */
168
+ getCurrentLiveRoomId(): number | null;
169
+ /**
170
+ * 检查是否已连接到直播间
171
+ */
172
+ isConnectedToLiveRoom(): boolean;
173
+ }