mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-20 14:39:25 +08:00
595 lines
21 KiB
TypeScript
595 lines
21 KiB
TypeScript
import type { ChatSession, Message, Contact, ContactInfo } from './models'
|
|
|
|
export interface ElectronAPI {
|
|
window: {
|
|
minimize: () => void
|
|
maximize: () => void
|
|
close: () => void
|
|
openAgreementWindow: () => Promise<boolean>
|
|
completeOnboarding: () => Promise<boolean>
|
|
openOnboardingWindow: () => Promise<boolean>
|
|
setTitleBarOverlay: (options: { symbolColor: string }) => void
|
|
openVideoPlayerWindow: (videoPath: string, videoWidth?: number, videoHeight?: number) => Promise<void>
|
|
resizeToFitVideo: (videoWidth: number, videoHeight: number) => Promise<void>
|
|
openImageViewerWindow: (imagePath: string, liveVideoPath?: string) => Promise<void>
|
|
openChatHistoryWindow: (sessionId: string, messageId: number) => Promise<boolean>
|
|
}
|
|
config: {
|
|
get: (key: string) => Promise<unknown>
|
|
set: (key: string, value: unknown) => Promise<void>
|
|
clear: () => Promise<boolean>
|
|
}
|
|
auth: {
|
|
hello: (message?: string) => Promise<{ success: boolean; error?: string }>
|
|
verifyEnabled: () => Promise<boolean>
|
|
unlock: (password: string) => Promise<{ success: boolean; error?: string }>
|
|
enableLock: (password: string) => Promise<{ success: boolean; error?: string }>
|
|
disableLock: (password: string) => Promise<{ success: boolean; error?: string }>
|
|
changePassword: (oldPassword: string, newPassword: string) => Promise<{ success: boolean; error?: string }>
|
|
setHelloSecret: (password: string) => Promise<{ success: boolean }>
|
|
clearHelloSecret: () => Promise<{ success: boolean }>
|
|
isLockMode: () => Promise<boolean>
|
|
}
|
|
dialog: {
|
|
openFile: (options?: Electron.OpenDialogOptions) => Promise<Electron.OpenDialogReturnValue>
|
|
openDirectory: (options?: Electron.OpenDialogOptions) => Promise<Electron.OpenDialogReturnValue>
|
|
saveFile: (options?: Electron.SaveDialogOptions) => Promise<Electron.SaveDialogReturnValue>
|
|
}
|
|
shell: {
|
|
openPath: (path: string) => Promise<string>
|
|
openExternal: (url: string) => Promise<void>
|
|
}
|
|
app: {
|
|
getDownloadsPath: () => Promise<string>
|
|
getVersion: () => Promise<string>
|
|
checkForUpdates: () => Promise<{ hasUpdate: boolean; version?: string; releaseNotes?: string }>
|
|
downloadAndInstall: () => Promise<void>
|
|
ignoreUpdate: (version: string) => Promise<{ success: boolean }>
|
|
onDownloadProgress: (callback: (progress: number) => void) => () => void
|
|
onUpdateAvailable: (callback: (info: { version: string; releaseNotes: string }) => void) => () => void
|
|
}
|
|
log: {
|
|
getPath: () => Promise<string>
|
|
read: () => Promise<{ success: boolean; content?: string; error?: string }>
|
|
}
|
|
dbPath: {
|
|
autoDetect: () => Promise<{ success: boolean; path?: string; error?: string }>
|
|
scanWxids: (rootPath: string) => Promise<WxidInfo[]>
|
|
scanWxidCandidates: (rootPath: string) => Promise<WxidInfo[]>
|
|
getDefault: () => Promise<string>
|
|
}
|
|
wcdb: {
|
|
testConnection: (dbPath: string, hexKey: string, wxid: string) => Promise<{ success: boolean; error?: string; sessionCount?: number }>
|
|
open: (dbPath: string, hexKey: string, wxid: string) => Promise<boolean>
|
|
close: () => Promise<boolean>
|
|
|
|
}
|
|
key: {
|
|
autoGetDbKey: () => Promise<{ success: boolean; key?: string; error?: string; logs?: string[] }>
|
|
autoGetImageKey: (manualDir?: string) => Promise<{ success: boolean; xorKey?: number; aesKey?: string; error?: string }>
|
|
onDbKeyStatus: (callback: (payload: { message: string; level: number }) => void) => () => void
|
|
onImageKeyStatus: (callback: (payload: { message: string }) => void) => () => void
|
|
}
|
|
chat: {
|
|
connect: () => Promise<{ success: boolean; error?: string }>
|
|
getSessions: () => Promise<{ success: boolean; sessions?: ChatSession[]; error?: string }>
|
|
enrichSessionsContactInfo: (usernames: string[]) => Promise<{
|
|
success: boolean
|
|
contacts?: Record<string, { displayName?: string; avatarUrl?: string }>
|
|
error?: string
|
|
}>
|
|
getMessages: (sessionId: string, offset?: number, limit?: number, startTime?: number, endTime?: number, ascending?: boolean) => Promise<{
|
|
success: boolean;
|
|
messages?: Message[];
|
|
hasMore?: boolean;
|
|
error?: string
|
|
}>
|
|
getLatestMessages: (sessionId: string, limit?: number) => Promise<{
|
|
success: boolean
|
|
messages?: Message[]
|
|
error?: string
|
|
}>
|
|
getNewMessages: (sessionId: string, minTime: number, limit?: number) => Promise<{
|
|
success: boolean
|
|
messages?: Message[]
|
|
error?: string
|
|
}>
|
|
getContact: (username: string) => Promise<Contact | null>
|
|
getContactAvatar: (username: string) => Promise<{ avatarUrl?: string; displayName?: string } | null>
|
|
updateMessage: (sessionId: string, localId: number, createTime: number, newContent: string) => Promise<{ success: boolean; error?: string }>
|
|
deleteMessage: (sessionId: string, localId: number, createTime: number, dbPathHint?: string) => Promise<{ success: boolean; error?: string }>
|
|
resolveTransferDisplayNames: (chatroomId: string, payerUsername: string, receiverUsername: string) => Promise<{ payerName: string; receiverName: string }>
|
|
getContacts: () => Promise<{
|
|
success: boolean
|
|
contacts?: ContactInfo[]
|
|
error?: string
|
|
}>
|
|
getMyAvatarUrl: () => Promise<{ success: boolean; avatarUrl?: string; error?: string }>
|
|
downloadEmoji: (cdnUrl: string, md5?: string) => Promise<{ success: boolean; localPath?: string; error?: string }>
|
|
close: () => Promise<boolean>
|
|
getSessionDetail: (sessionId: string) => Promise<{
|
|
success: boolean
|
|
detail?: {
|
|
wxid: string
|
|
displayName: string
|
|
remark?: string
|
|
nickName?: string
|
|
alias?: string
|
|
avatarUrl?: string
|
|
messageCount: number
|
|
firstMessageTime?: number
|
|
latestMessageTime?: number
|
|
messageTables: { dbName: string; tableName: string; count: number }[]
|
|
}
|
|
error?: string
|
|
}>
|
|
getImageData: (sessionId: string, msgId: string) => Promise<{ success: boolean; data?: string; error?: string }>
|
|
getVoiceData: (sessionId: string, msgId: string, createTime?: number, serverId?: string | number) => Promise<{ success: boolean; data?: string; error?: string }>
|
|
getAllVoiceMessages: (sessionId: string) => Promise<{ success: boolean; messages?: Message[]; error?: string }>
|
|
getAllImageMessages: (sessionId: string) => Promise<{
|
|
success: boolean
|
|
images?: { imageMd5?: string; imageDatName?: string; createTime?: number }[]
|
|
error?: string
|
|
}>
|
|
resolveVoiceCache: (sessionId: string, msgId: string) => Promise<{ success: boolean; hasCache: boolean; data?: string }>
|
|
getVoiceTranscript: (sessionId: string, msgId: string, createTime?: number) => Promise<{ success: boolean; transcript?: string; error?: string }>
|
|
onVoiceTranscriptPartial: (callback: (payload: { msgId: string; text: string }) => void) => () => void
|
|
execQuery: (kind: string, path: string | null, sql: string) => Promise<{ success: boolean; rows?: any[]; error?: string }>
|
|
getMessage: (sessionId: string, localId: number) => Promise<{ success: boolean; message?: Message; error?: string }>
|
|
onWcdbChange: (callback: (event: any, data: { type: string; json: string }) => void) => () => void
|
|
}
|
|
|
|
image: {
|
|
decrypt: (payload: { sessionId?: string; imageMd5?: string; imageDatName?: string; force?: boolean }) => Promise<{ success: boolean; localPath?: string; error?: string }>
|
|
resolveCache: (payload: { sessionId?: string; imageMd5?: string; imageDatName?: string }) => Promise<{ success: boolean; localPath?: string; hasUpdate?: boolean; liveVideoPath?: string; error?: string }>
|
|
preload: (payloads: Array<{ sessionId?: string; imageMd5?: string; imageDatName?: string }>) => Promise<boolean>
|
|
onUpdateAvailable: (callback: (payload: { cacheKey: string; imageMd5?: string; imageDatName?: string }) => void) => () => void
|
|
onCacheResolved: (callback: (payload: { cacheKey: string; imageMd5?: string; imageDatName?: string; localPath: string }) => void) => () => void
|
|
}
|
|
video: {
|
|
getVideoInfo: (videoMd5: string) => Promise<{
|
|
success: boolean
|
|
exists: boolean
|
|
videoUrl?: string
|
|
coverUrl?: string
|
|
thumbUrl?: string
|
|
error?: string
|
|
}>
|
|
parseVideoMd5: (content: string) => Promise<{
|
|
success: boolean
|
|
md5?: string
|
|
error?: string
|
|
}>
|
|
}
|
|
analytics: {
|
|
getOverallStatistics: (force?: boolean) => Promise<{
|
|
success: boolean
|
|
data?: {
|
|
totalMessages: number
|
|
textMessages: number
|
|
imageMessages: number
|
|
voiceMessages: number
|
|
videoMessages: number
|
|
emojiMessages: number
|
|
otherMessages: number
|
|
sentMessages: number
|
|
receivedMessages: number
|
|
firstMessageTime: number | null
|
|
lastMessageTime: number | null
|
|
activeDays: number
|
|
messageTypeCounts: Record<number, number>
|
|
}
|
|
error?: string
|
|
}>
|
|
getContactRankings: (limit?: number, beginTimestamp?: number, endTimestamp?: number) => Promise<{
|
|
success: boolean
|
|
data?: Array<{
|
|
username: string
|
|
displayName: string
|
|
avatarUrl?: string
|
|
wechatId?: string
|
|
messageCount: number
|
|
sentCount: number
|
|
receivedCount: number
|
|
lastMessageTime: number | null
|
|
}>
|
|
error?: string
|
|
}>
|
|
getTimeDistribution: () => Promise<{
|
|
success: boolean
|
|
data?: {
|
|
hourlyDistribution: Record<number, number>
|
|
weekdayDistribution: Record<number, number>
|
|
monthlyDistribution: Record<string, number>
|
|
}
|
|
error?: string
|
|
}>
|
|
getExcludedUsernames: () => Promise<{
|
|
success: boolean
|
|
data?: string[]
|
|
error?: string
|
|
}>
|
|
setExcludedUsernames: (usernames: string[]) => Promise<{
|
|
success: boolean
|
|
data?: string[]
|
|
error?: string
|
|
}>
|
|
getExcludeCandidates: () => Promise<{
|
|
success: boolean
|
|
data?: Array<{
|
|
username: string
|
|
displayName: string
|
|
avatarUrl?: string
|
|
wechatId?: string
|
|
}>
|
|
error?: string
|
|
}>
|
|
onProgress: (callback: (payload: { status: string; progress: number }) => void) => () => void
|
|
}
|
|
cache: {
|
|
clearAnalytics: () => Promise<{ success: boolean; error?: string }>
|
|
clearImages: () => Promise<{ success: boolean; error?: string }>
|
|
clearAll: () => Promise<{ success: boolean; error?: string }>
|
|
}
|
|
groupAnalytics: {
|
|
getGroupChats: () => Promise<{
|
|
success: boolean
|
|
data?: Array<{
|
|
username: string
|
|
displayName: string
|
|
memberCount: number
|
|
avatarUrl?: string
|
|
}>
|
|
error?: string
|
|
}>
|
|
getGroupMembers: (chatroomId: string) => Promise<{
|
|
success: boolean
|
|
data?: Array<{
|
|
username: string
|
|
displayName: string
|
|
avatarUrl?: string
|
|
nickname?: string
|
|
alias?: string
|
|
remark?: string
|
|
groupNickname?: string
|
|
}>
|
|
error?: string
|
|
}>
|
|
getGroupMessageRanking: (chatroomId: string, limit?: number, startTime?: number, endTime?: number) => Promise<{
|
|
success: boolean
|
|
data?: Array<{
|
|
member: {
|
|
username: string
|
|
displayName: string
|
|
avatarUrl?: string
|
|
}
|
|
messageCount: number
|
|
}>
|
|
error?: string
|
|
}>
|
|
getGroupActiveHours: (chatroomId: string, startTime?: number, endTime?: number) => Promise<{
|
|
success: boolean
|
|
data?: {
|
|
hourlyDistribution: Record<number, number>
|
|
}
|
|
error?: string
|
|
}>
|
|
getGroupMediaStats: (chatroomId: string, startTime?: number, endTime?: number) => Promise<{
|
|
success: boolean
|
|
data?: {
|
|
typeCounts: Array<{
|
|
type: number
|
|
name: string
|
|
count: number
|
|
}>
|
|
total: number
|
|
}
|
|
error?: string
|
|
}>
|
|
exportGroupMembers: (chatroomId: string, outputPath: string) => Promise<{
|
|
success: boolean
|
|
count?: number
|
|
error?: string
|
|
}>
|
|
exportGroupMemberMessages: (
|
|
chatroomId: string,
|
|
memberUsername: string,
|
|
outputPath: string,
|
|
startTime?: number,
|
|
endTime?: number
|
|
) => Promise<{
|
|
success: boolean
|
|
count?: number
|
|
error?: string
|
|
}>
|
|
}
|
|
annualReport: {
|
|
getAvailableYears: () => Promise<{
|
|
success: boolean
|
|
data?: number[]
|
|
error?: string
|
|
}>
|
|
generateReport: (year: number) => Promise<{
|
|
success: boolean
|
|
data?: {
|
|
year: number
|
|
totalMessages: number
|
|
totalFriends: number
|
|
coreFriends: Array<{
|
|
username: string
|
|
displayName: string
|
|
avatarUrl?: string
|
|
messageCount: number
|
|
sentCount: number
|
|
receivedCount: number
|
|
}>
|
|
monthlyTopFriends: Array<{
|
|
month: number
|
|
displayName: string
|
|
avatarUrl?: string
|
|
messageCount: number
|
|
}>
|
|
peakDay: {
|
|
date: string
|
|
messageCount: number
|
|
topFriend?: string
|
|
topFriendCount?: number
|
|
} | null
|
|
longestStreak: {
|
|
friendName: string
|
|
days: number
|
|
startDate: string
|
|
endDate: string
|
|
} | null
|
|
activityHeatmap: {
|
|
data: number[][]
|
|
}
|
|
midnightKing: {
|
|
displayName: string
|
|
count: number
|
|
percentage: number
|
|
} | null
|
|
selfAvatarUrl?: string
|
|
mutualFriend: {
|
|
displayName: string
|
|
avatarUrl?: string
|
|
sentCount: number
|
|
receivedCount: number
|
|
ratio: number
|
|
} | null
|
|
socialInitiative: {
|
|
initiatedChats: number
|
|
receivedChats: number
|
|
initiativeRate: number
|
|
} | null
|
|
responseSpeed: {
|
|
avgResponseTime: number
|
|
fastestFriend: string
|
|
fastestTime: number
|
|
} | null
|
|
topPhrases: Array<{
|
|
phrase: string
|
|
count: number
|
|
}>
|
|
}
|
|
error?: string
|
|
}>
|
|
exportImages: (payload: { baseDir: string; folderName: string; images: Array<{ name: string; dataUrl: string }> }) => Promise<{
|
|
success: boolean
|
|
dir?: string
|
|
error?: string
|
|
}>
|
|
onProgress: (callback: (payload: { status: string; progress: number }) => void) => () => void
|
|
}
|
|
dualReport: {
|
|
generateReport: (payload: { friendUsername: string; year: number }) => Promise<{
|
|
success: boolean
|
|
data?: {
|
|
year: number
|
|
selfName: string
|
|
selfAvatarUrl?: string
|
|
friendUsername: string
|
|
friendName: string
|
|
friendAvatarUrl?: string
|
|
firstChat: {
|
|
createTime: number
|
|
createTimeStr: string
|
|
content: string
|
|
isSentByMe: boolean
|
|
senderUsername?: string
|
|
} | null
|
|
firstChatMessages?: Array<{
|
|
content: string
|
|
isSentByMe: boolean
|
|
createTime: number
|
|
createTimeStr: string
|
|
}>
|
|
yearFirstChat?: {
|
|
createTime: number
|
|
createTimeStr: string
|
|
content: string
|
|
isSentByMe: boolean
|
|
friendName: string
|
|
firstThreeMessages: Array<{
|
|
content: string
|
|
isSentByMe: boolean
|
|
createTime: number
|
|
createTimeStr: string
|
|
}>
|
|
} | null
|
|
stats: {
|
|
totalMessages: number
|
|
totalWords: number
|
|
imageCount: number
|
|
voiceCount: number
|
|
emojiCount: number
|
|
myTopEmojiMd5?: string
|
|
friendTopEmojiMd5?: string
|
|
myTopEmojiUrl?: string
|
|
topPhrases: Array<{ phrase: string; count: number }>
|
|
myExclusivePhrases: Array<{ phrase: string; count: number }>
|
|
friendExclusivePhrases: Array<{ phrase: string; count: number }>
|
|
heatmap?: number[][]
|
|
initiative?: { initiated: number; received: number }
|
|
response?: { avg: number; fastest: number; count: number }
|
|
monthly?: Record<string, number>
|
|
streak?: { days: number; startDate: string; endDate: string }
|
|
}
|
|
}
|
|
error?: string
|
|
}>
|
|
onProgress: (callback: (payload: { status: string; progress: number }) => void) => () => void
|
|
}
|
|
export: {
|
|
getExportStats: (sessionIds: string[], options: any) => Promise<{
|
|
totalMessages: number
|
|
voiceMessages: number
|
|
cachedVoiceCount: number
|
|
needTranscribeCount: number
|
|
mediaMessages: number
|
|
estimatedSeconds: number
|
|
sessions: Array<{ sessionId: string; displayName: string; totalCount: number; voiceCount: number }>
|
|
}>
|
|
exportSessions: (sessionIds: string[], outputDir: string, options: ExportOptions) => Promise<{
|
|
success: boolean
|
|
successCount?: number
|
|
failCount?: number
|
|
error?: string
|
|
}>
|
|
exportSession: (sessionId: string, outputPath: string, options: ExportOptions) => Promise<{
|
|
success: boolean
|
|
error?: string
|
|
}>
|
|
exportContacts: (outputDir: string, options: { format: 'json' | 'csv' | 'vcf'; exportAvatars: boolean; contactTypes: { friends: boolean; groups: boolean; officials: boolean }; selectedUsernames?: string[] }) => Promise<{
|
|
success: boolean
|
|
successCount?: number
|
|
error?: string
|
|
}>
|
|
onProgress: (callback: (payload: ExportProgress) => void) => () => void
|
|
}
|
|
whisper: {
|
|
downloadModel: () => Promise<{ success: boolean; modelPath?: string; tokensPath?: string; error?: string }>
|
|
getModelStatus: () => Promise<{ success: boolean; exists?: boolean; modelPath?: string; tokensPath?: string; sizeBytes?: number; error?: string }>
|
|
onDownloadProgress: (callback: (payload: { modelName: string; downloadedBytes: number; totalBytes?: number; percent?: number }) => void) => () => void
|
|
}
|
|
sns: {
|
|
getTimeline: (limit: number, offset: number, usernames?: string[], keyword?: string, startTime?: number, endTime?: number) => Promise<{
|
|
success: boolean
|
|
timeline?: Array<{
|
|
id: string
|
|
username: string
|
|
nickname: string
|
|
avatarUrl?: string
|
|
createTime: number
|
|
contentDesc: string
|
|
type?: number
|
|
media: Array<{
|
|
url: string
|
|
thumb: string
|
|
md5?: string
|
|
token?: string
|
|
key?: string
|
|
encIdx?: string
|
|
livePhoto?: {
|
|
url: string
|
|
thumb: string
|
|
md5?: string
|
|
token?: string
|
|
key?: string
|
|
encIdx?: string
|
|
}
|
|
}>
|
|
likes: Array<string>
|
|
comments: Array<{ id: string; nickname: string; content: string; refCommentId: string; refNickname?: string }>
|
|
rawXml?: string
|
|
}>
|
|
error?: string
|
|
}>
|
|
debugResource: (url: string) => Promise<{ success: boolean; status?: number; headers?: any; error?: string }>
|
|
proxyImage: (payload: { url: string; key?: string | number }) => Promise<{ success: boolean; dataUrl?: string; error?: string }>
|
|
downloadImage: (payload: { url: string; key?: string | number }) => Promise<{ success: boolean; data?: any; contentType?: string; error?: string }>
|
|
exportTimeline: (options: {
|
|
outputDir: string
|
|
format: 'json' | 'html'
|
|
usernames?: string[]
|
|
keyword?: string
|
|
exportMedia?: boolean
|
|
startTime?: number
|
|
endTime?: number
|
|
}) => Promise<{ success: boolean; filePath?: string; postCount?: number; mediaCount?: number; error?: string }>
|
|
onExportProgress: (callback: (payload: { current: number; total: number; status: string }) => void) => () => void
|
|
selectExportDir: () => Promise<{ canceled: boolean; filePath?: string }>
|
|
getSnsUsernames: () => Promise<{ success: boolean; usernames?: string[]; error?: string }>
|
|
}
|
|
http: {
|
|
start: (port?: number) => Promise<{ success: boolean; port?: number; error?: string }>
|
|
stop: () => Promise<{ success: boolean }>
|
|
status: () => Promise<{ running: boolean; port: number; mediaExportPath: string }>
|
|
}
|
|
}
|
|
|
|
export interface ExportOptions {
|
|
format: 'chatlab' | 'chatlab-jsonl' | 'json' | 'html' | 'txt' | 'excel' | 'weclone' | 'sql'
|
|
dateRange?: { start: number; end: number } | null
|
|
senderUsername?: string
|
|
fileNameSuffix?: string
|
|
exportMedia?: boolean
|
|
exportAvatars?: boolean
|
|
exportImages?: boolean
|
|
exportVoices?: boolean
|
|
exportVideos?: boolean
|
|
exportEmojis?: boolean
|
|
exportVoiceAsText?: boolean
|
|
excelCompactColumns?: boolean
|
|
txtColumns?: string[]
|
|
sessionLayout?: 'shared' | 'per-session'
|
|
displayNamePreference?: 'group-nickname' | 'remark' | 'nickname'
|
|
exportConcurrency?: number
|
|
}
|
|
|
|
export interface ExportProgress {
|
|
current: number
|
|
total: number
|
|
currentSession: string
|
|
phase: 'preparing' | 'exporting' | 'exporting-media' | 'exporting-voice' | 'writing' | 'complete'
|
|
phaseProgress?: number
|
|
phaseTotal?: number
|
|
phaseLabel?: string
|
|
}
|
|
|
|
export interface WxidInfo {
|
|
wxid: string
|
|
modifiedTime: number
|
|
}
|
|
|
|
declare global {
|
|
interface Window {
|
|
electronAPI: ElectronAPI
|
|
}
|
|
|
|
// Electron 类型声明
|
|
namespace Electron {
|
|
interface OpenDialogOptions {
|
|
title?: string
|
|
defaultPath?: string
|
|
filters?: { name: string; extensions: string[] }[]
|
|
properties?: ('openFile' | 'openDirectory' | 'multiSelections' | 'createDirectory')[]
|
|
}
|
|
interface OpenDialogReturnValue {
|
|
canceled: boolean
|
|
filePaths: string[]
|
|
}
|
|
interface SaveDialogOptions {
|
|
title?: string
|
|
defaultPath?: string
|
|
filters?: { name: string; extensions: string[] }[]
|
|
}
|
|
interface SaveDialogReturnValue {
|
|
canceled: boolean
|
|
filePath?: string
|
|
}
|
|
}
|
|
}
|
|
|
|
export { }
|