mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-10-25 17:36:32 +08:00
164 lines
13 KiB
Markdown
164 lines
13 KiB
Markdown
# 第三方可插拔组件接口说明
|
||
|
||
WeFlow 不再内置任何用于读取/解密本地数据的原生组件。以下四类能力全部由用户在
|
||
「设置 -> 数据库 -> 第三方组件路径」中自行配置一个可执行文件/动态库/插件路径,
|
||
应用只按下述协议与其交互,不对其来源、签名或实现方式做任何校验。
|
||
|
||
留空或指向的文件不存在时,对应功能会直接返回"未配置"错误,不会有任何降级或替代实现。
|
||
|
||
## 1. WCDB 实现(`wcdbLibPath`)
|
||
|
||
一个动态库(Windows `*.dll` / macOS `*.dylib` / Linux `*.so`),通过 [koffi](https://koffi.dev/)
|
||
以 C ABI 方式加载,用于读取本地 SQLCipher 数据库并提供会话/消息/联系人/朋友圈等查询。
|
||
|
||
加载流程(见 `electron/services/wcdbCore.ts` 的 `initialize()`):
|
||
1. `koffi.load(wcdbLibPath)`。
|
||
2. 依次尝试绑定下列导出函数;可选符号不存在时该功能会被跳过(返回 `null`),不影响其余功能。
|
||
`wcdb_init`、`wcdb_shutdown`、`wcdb_open_account`、`wcdb_close_account` 和
|
||
`wcdb_free_string` 必须存在,用于初始化、账号生命周期和返回字符串的释放;
|
||
查询、统计、媒体、日志等功能接口按需实现即可。
|
||
|
||
完整函数签名列表(`int32` 返回值均为状态码,`0` 表示成功;`_Out_ void** outJson` 类参数
|
||
由组件分配字符串内存,调用方通过 `wcdb_free_string` 释放):
|
||
|
||
```
|
||
int32 wcdb_open_account(const char* path, const char* key, _Out_ int64* handle)
|
||
int32 wcdb_close_account(int64 handle)
|
||
int32 wcdb_init()
|
||
int32 wcdb_shutdown()
|
||
int32 wcdb_purge_memory()
|
||
void wcdb_free_string(void* ptr)
|
||
int32 wcdb_set_my_account_id(int64 handle, const char* accountId)
|
||
int32 wcdb_get_sessions(int64 handle, _Out_ void** outJson)
|
||
int32 wcdb_mark_all_sessions_read(int64 handle, _Out_ void** outError)
|
||
int32 wcdb_reorder_sessions_by_time(int64 handle, _Out_ void** outJson)
|
||
int32 wcdb_get_messages(int64 handle, const char* username, int32 limit, int32 offset, _Out_ void** outJson)
|
||
int32 wcdb_get_messages_by_type(int64 handle, const char* sessionId, int64 localType, int32 ascending, int32 limit, int32 offset, _Out_ void** outJson)
|
||
int32 wcdb_get_message_count(int64 handle, const char* username, _Out_ int32* outCount)
|
||
int32 wcdb_get_message_by_id(int64 handle, const char* sessionId, int32 localId, _Out_ void** outJson)
|
||
int32 wcdb_get_message_by_svrid(int64 handle, const char* sessionId, const char* svrid, _Out_ void** outJson)
|
||
int32 wcdb_get_session_message_counts(int64 handle, const char* sessionIdsJson, _Out_ void** outJson)
|
||
int32 wcdb_get_session_message_type_stats(int64 handle, const char* sessionId, int32 beginTimestamp, int32 endTimestamp, _Out_ void** outJson)
|
||
int32 wcdb_get_session_message_type_stats_batch(int64 handle, const char* sessionIdsJson, const char* optionsJson, _Out_ void** outJson)
|
||
int32 wcdb_get_session_message_date_counts(int64 handle, const char* sessionId, _Out_ void** outJson)
|
||
int32 wcdb_get_session_message_date_counts_batch(int64 handle, const char* sessionIdsJson, _Out_ void** outJson)
|
||
int32 wcdb_open_message_cursor(int64 handle, const char* sessionId, int32 batchSize, int32 ascending, int32 beginTimestamp, int32 endTimestamp, _Out_ int64* outCursor)
|
||
int32 wcdb_fetch_message_batch(int64 handle, int64 cursor, _Out_ void** outJson, _Out_ int32* outHasMore)
|
||
int32 wcdb_close_message_cursor(int64 handle, int64 cursor)
|
||
int32 wcdb_set_message_cursor_projection(int64 handle, int64 cursor, int32 projection)
|
||
int32 wcdb_search_messages(int64 handle, const char* sessionId, const char* keyword, int32 limit, int32 offset, int32 beginTimestamp, int32 endTimestamp, _Out_ void** outJson)
|
||
int32 wcdb_ai_query_session_candidates(int64 handle, const char* optionsJson, _Out_ void** outJson)
|
||
int32 wcdb_update_message(int64 handle, const char* sessionId, int64 localId, int32 createTime, const char* newContent, _Out_ void** outError)
|
||
int32 wcdb_insert_text_message(int64 handle, const char* sessionId, const char* content, int64 status, int64 createTime, _Out_ void** outJson)
|
||
int32 wcdb_delete_message(int64 handle, const char* sessionId, int64 localId, int32 createTime, const char* dbPathHint, _Out_ void** outError)
|
||
int32 wcdb_check_message_anti_revoke_trigger(int64 handle, const char* sessionId, _Out_ int32* outInstalled)
|
||
int32 wcdb_install_message_anti_revoke_trigger(int64 handle, const char* sessionId, _Out_ void** outError)
|
||
int32 wcdb_uninstall_message_anti_revoke_trigger(int64 handle, const char* sessionId, _Out_ void** outError)
|
||
int32 wcdb_get_contact(int64 handle, const char* username, _Out_ void** outJson)
|
||
int32 wcdb_get_contact_status(int64 handle, const char* usernamesJson, _Out_ void** outJson)
|
||
int32 wcdb_get_contact_type_counts(int64 handle, _Out_ void** outJson)
|
||
int32 wcdb_get_contacts_compact(int64 handle, const char* usernamesJson, _Out_ void** outJson)
|
||
int32 wcdb_get_contact_alias_map(int64 handle, const char* usernamesJson, _Out_ void** outJson)
|
||
int32 wcdb_get_contact_friend_flags(int64 handle, const char* usernamesJson, _Out_ void** outJson)
|
||
int32 wcdb_get_chat_room_ext_buffer(int64 handle, const char* chatroomId, _Out_ void** outJson)
|
||
int32 wcdb_get_display_names(int64 handle, const char* usernamesJson, _Out_ void** outJson)
|
||
int32 wcdb_get_avatar_urls(int64 handle, const char* usernamesJson, _Out_ void** outJson)
|
||
int32 wcdb_get_head_image_buffers(int64 handle, const char* usernamesJson, _Out_ void** outJson)
|
||
int32 wcdb_get_group_member_count(int64 handle, const char* chatroomId, _Out_ int32* outCount)
|
||
int32 wcdb_get_group_member_counts(int64 handle, const char* chatroomIdsJson, _Out_ void** outJson)
|
||
int32 wcdb_get_group_members(int64 handle, const char* chatroomId, _Out_ void** outJson)
|
||
int32 wcdb_get_group_nicknames(int64 handle, const char* chatroomId, _Out_ void** outJson)
|
||
int32 wcdb_get_group_stats(int64 handle, const char* chatroomId, int32 begin, int32 end, _Out_ void** outJson)
|
||
int32 wcdb_get_aggregate_stats(int64 handle, const char* sessionIdsJson, int32 begin, int32 end, _Out_ void** outJson)
|
||
int32 wcdb_get_available_years(int64 handle, const char* sessionIdsJson, _Out_ void** outJson)
|
||
int32 wcdb_get_annual_report_stats(int64 handle, const char* sessionIdsJson, int32 begin, int32 end, _Out_ void** outJson)
|
||
int32 wcdb_get_annual_report_extras(int64 handle, const char* sessionIdsJson, int32 begin, int32 end, int32 peakBegin, int32 peakEnd, _Out_ void** outJson)
|
||
int32 wcdb_get_dual_report_stats(int64 handle, const char* sessionId, int32 begin, int32 end, _Out_ void** outJson)
|
||
int32 wcdb_get_my_footprint_stats(int64 handle, const char* optionsJson, _Out_ void** outJson)
|
||
int32 wcdb_get_message_tables(int64 handle, const char* sessionId, _Out_ void** outJson)
|
||
int32 wcdb_get_message_table_stats(int64 handle, const char* sessionId, _Out_ void** outJson)
|
||
int32 wcdb_get_message_dates(int64 handle, const char* sessionId, _Out_ void** outJson)
|
||
int32 wcdb_get_message_meta(int64 handle, const char* dbPath, const char* tableName, int32 limit, int32 offset, _Out_ void** outJson)
|
||
int32 wcdb_get_message_table_columns(int64 handle, const char* dbPath, const char* tableName, _Out_ void** outJson)
|
||
int32 wcdb_get_message_table_time_range(int64 handle, const char* dbPath, const char* tableName, _Out_ void** outJson)
|
||
int32 wcdb_list_tables(int64 handle, const char* kind, const char* dbPath, _Out_ void** outJson)
|
||
int32 wcdb_get_table_schema(int64 handle, const char* kind, const char* dbPath, const char* tableName, _Out_ void** outJson)
|
||
int32 wcdb_export_table_snapshot(int64 handle, const char* kind, const char* dbPath, const char* tableName, const char* outputPath, _Out_ void** outJson)
|
||
int32 wcdb_import_table_snapshot(int64 handle, const char* kind, const char* dbPath, const char* tableName, const char* inputPath, _Out_ void** outJson)
|
||
int32 wcdb_import_table_snapshot_with_schema(int64 handle, const char* kind, const char* dbPath, const char* tableName, const char* inputPath, const char* createTableSql, _Out_ void** outJson)
|
||
int32 wcdb_list_message_dbs(int64 handle, _Out_ void** outJson)
|
||
int32 wcdb_list_media_dbs(int64 handle, _Out_ void** outJson)
|
||
int32 wcdb_get_media_schema_summary(int64 handle, const char* dbPath, _Out_ void** outJson)
|
||
int32 wcdb_exec_query(int64 handle, const char* kind, const char* path, const char* sql, _Out_ void** outJson)
|
||
int32 wcdb_get_emoticon_cdn_url(int64 handle, const char* dbPath, const char* md5, _Out_ void** outUrl)
|
||
int32 wcdb_get_emoticon_caption(int64 handle, const char* dbPath, const char* md5, _Out_ void** outCaption)
|
||
int32 wcdb_get_emoticon_caption_strict(int64 handle, const char* md5, _Out_ void** outCaption)
|
||
int32 wcdb_get_voice_data(int64 handle, const char* sessionId, int32 createTime, int32 localId, int64 svrId, const char* candidatesJson, _Out_ void** outHex)
|
||
int32 wcdb_get_voice_data_batch(int64 handle, const char* requestsJson, _Out_ void** outJson)
|
||
int32 wcdb_resolve_image_hardlink(int64 handle, const char* md5, const char* accountDir, _Out_ void** outJson)
|
||
int32 wcdb_resolve_image_hardlink_batch(int64 handle, const char* requestsJson, _Out_ void** outJson)
|
||
int32 wcdb_resolve_video_hardlink_md5(int64 handle, const char* md5, const char* dbPath, _Out_ void** outJson)
|
||
int32 wcdb_resolve_video_hardlink_md5_batch(int64 handle, const char* requestsJson, _Out_ void** outJson)
|
||
int32 wcdb_scan_media_stream(int64 handle, const char* sessionIdsJson, int32 mediaType, int32 beginTimestamp, int32 endTimestamp, int32 limit, int32 offset, _Out_ void** outJson, _Out_ int32* outHasMore)
|
||
int32 wcdb_get_sns_timeline(int64 handle, int32 limit, int32 offset, const char* username, const char* keyword, int32 startTime, int32 endTime, _Out_ void** outJson)
|
||
int32 wcdb_get_sns_annual_stats(int64 handle, int32 begin, int32 end, _Out_ void** outJson)
|
||
int32 wcdb_get_sns_usernames(int64 handle, _Out_ void** outJson)
|
||
int32 wcdb_get_sns_export_stats(int64 handle, const char* myAccountId, _Out_ void** outJson)
|
||
int32 wcdb_check_sns_block_delete_trigger(int64 handle, _Out_ int32* outInstalled)
|
||
int32 wcdb_install_sns_block_delete_trigger(int64 handle, _Out_ void** outError)
|
||
int32 wcdb_uninstall_sns_block_delete_trigger(int64 handle, _Out_ void** outError)
|
||
int32 wcdb_delete_sns_post(int64 handle, const char* postId, _Out_ void** outError)
|
||
int32 wcdb_start_monitor_pipe()
|
||
void wcdb_stop_monitor_pipe()
|
||
int32 wcdb_get_monitor_pipe_name(_Out_ void** outName)
|
||
int32 wcdb_get_db_status(int64 handle, _Out_ void** outJson)
|
||
int32 wcdb_get_logs(_Out_ void** outJson)
|
||
int32 wcdb_cloud_init(int32 intervalSeconds)
|
||
int32 wcdb_cloud_report(const char* statsJson)
|
||
void wcdb_cloud_stop()
|
||
void VerifyUser(int64 hwnd, const char* message, _Out_ char* outResult, int maxLen)
|
||
```
|
||
|
||
上述五个生命周期与内存管理接口之外均为可选:缺失的符号对应功能会在应用里表现为"不可用",
|
||
不影响其他已实现的功能。消息游标需要同时提供 `wcdb_open_message_cursor`、
|
||
`wcdb_fetch_message_batch` 和 `wcdb_close_message_cursor`,以保证已打开的游标可以读取和释放。
|
||
JSON 载荷/出参的字段命名可参照 `electron/services/wcdbCore.ts` 里
|
||
每个函数调用点前后对返回值的解析逻辑。
|
||
|
||
## 2. 媒体解密插件(`imageNativeAddonPath`)
|
||
|
||
一个 Node 原生插件(`.node`,通过 `require()` 加载),对应 `electron/services/nativeImageDecrypt.ts`
|
||
里的 `NativeAddon` 接口:
|
||
|
||
```ts
|
||
{
|
||
decryptDatNative(inputPath: string, xorKey: number, aesKey?: string): {
|
||
data: Buffer
|
||
ext: string // 如 'jpg'/'png'/'mp4',不含点号也可
|
||
isWxgf?: boolean // 是否为 WXGF 容器格式,是则会再走一层 unwrap
|
||
version?: number
|
||
aesSize?: number
|
||
xorSize?: number
|
||
rawSize?: number
|
||
flag?: number
|
||
}
|
||
// 可选:编辑/重新加密场景使用
|
||
encryptDatNative?(inputPath: string, xorKey: number, aesKey?: string, meta?: object): Buffer
|
||
}
|
||
```
|
||
|
||
参照原始 `Wedecrypt/` Rust 工程(`napi`/`napi-derive` + `cdylib`)实现即可复用其思路。
|
||
|
||
## 3. WeLive 批量导出引擎(`welivePath`)
|
||
|
||
一个可执行文件,由 `electron/services/weliveBridge.ts` 的 `runWeliveExport()` 拉起,
|
||
用于会话的批量原始导出(文本 + 媒体)。协议:
|
||
|
||
- 请求:完整的 `WeliveExportRequest`(见 `weliveBridge.ts` 内类型定义,包含账号信息、
|
||
`sessionIds`、输出目录、媒体类型等)序列化为 JSON,写入子进程 stdin 后关闭。
|
||
- 响应:子进程通过 stdout 按行输出 `WeliveExportEvent` 的 NDJSON(`ready`/`progress`/
|
||
`created_file`/`created_dir`/`session_error`/`result` 等类型),最终以一条 `result` 事件
|
||
(含 `success`/`success_count`/`fail_count`/`session_output_paths`/`raw_export_manifests`
|
||
等字段)结束。进程以退出码 `0` 且最后一条事件为 `result` 且 `success !== false` 视为成功。
|
||
- 支持通过关闭 stdin/发送信号来响应取消(`AbortSignal`),进程应能在收到终止信号后尽快退出。
|