koishi-plugin-chat-patch 5.3.0 → 5.5.0

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.
Files changed (77) hide show
  1. package/client/web/dist/assets/Chat-Clqxn7CB.js +28 -0
  2. package/client/web/dist/assets/{Chat-CTdyeaX2.css → Chat-DTEsebnY.css} +1 -1
  3. package/client/web/dist/assets/{MsgBody-DDacjWJ9.js → MsgBody-C0TKsXhC.js} +1 -1
  4. package/client/web/dist/assets/{MsgBody.vue_vue_type_script_setup_true_lang-B1dWyCB0.js → MsgBody.vue_vue_type_script_setup_true_lang-CCdBwlN_.js} +2 -2
  5. package/client/web/dist/assets/{append_darwin-CqBNU62J.css → append_darwin-Cql-dV6d.css} +1 -1
  6. package/client/web/dist/assets/{append_full_vibrancy-j0D2LM9m.css → append_full_vibrancy-ih3loy1O.css} +1 -1
  7. package/client/web/dist/assets/{append_linux-uhxeBqeC.css → append_linux-B3LvR8KB.css} +1 -1
  8. package/client/web/dist/assets/{append_new-407Lo5_V.css → append_new-DfhN_NX9.css} +1 -1
  9. package/client/web/dist/assets/{append_vibrancy-6FHctkOY.css → append_vibrancy-D3pVsmAa.css} +1 -1
  10. package/client/web/dist/assets/{append_win32-srmD-78y.css → append_win32-Dh9JlmlE.css} +1 -1
  11. package/client/web/dist/assets/index-B71pPwae.css +1 -0
  12. package/client/web/dist/assets/{index-BlLut5xn.js → index-BA37EQGa.js} +97 -76
  13. package/client/web/dist/index.html +2 -2
  14. package/client/web/src/App.vue +2 -2
  15. package/client/web/src/assets/css/append/append_darwin.css +2 -2
  16. package/client/web/src/assets/css/append/append_full_vibrancy.css +2 -2
  17. package/client/web/src/assets/css/append/append_linux.css +2 -2
  18. package/client/web/src/assets/css/append/append_new.css +2 -2
  19. package/client/web/src/assets/css/append/append_vibrancy.css +1 -1
  20. package/client/web/src/assets/css/append/append_win32.css +2 -2
  21. package/client/web/src/assets/css/append/mobile/append_mobile_horizontal.css +1 -1
  22. package/client/web/src/assets/css/chat.css +4 -3
  23. package/client/web/src/assets/css/msg.css +7 -3
  24. package/client/web/src/assets/css/options.css +2 -2
  25. package/client/web/src/assets/css/view.css +14 -3
  26. package/client/web/src/assets/l10n/zh-CN.po +21 -0
  27. package/client/web/src/components/AboutPan.vue +7 -4
  28. package/client/web/src/components/BulletinBody.vue +1 -1
  29. package/client/web/src/components/DepPan.vue +1 -1
  30. package/client/web/src/components/FriendBody.vue +1 -0
  31. package/client/web/src/components/MsgBody.vue +1 -3
  32. package/client/web/src/components/ThemeColorPickerPan.vue +1 -1
  33. package/client/web/src/components/TinySessionBody.vue +1 -0
  34. package/client/web/src/components/UmamiInfoPan.vue +1 -1
  35. package/client/web/src/components/UpdatePan.vue +2 -2
  36. package/client/web/src/components/WelPan.vue +1 -1
  37. package/client/web/src/components/tooltip/UserInfoTooltip.vue +1 -1
  38. package/client/web/src/function/connect.ts +279 -86
  39. package/client/web/src/function/elements/information.ts +1 -0
  40. package/client/web/src/function/msg.ts +42 -23
  41. package/client/web/src/function/satori-model.ts +35 -13
  42. package/client/web/src/function/satori.ts +33 -2
  43. package/client/web/src/function/utils/appUtil.ts +3 -11
  44. package/client/web/src/function/utils/avatarUtil.ts +18 -3
  45. package/client/web/src/function/utils/localHistoryUtil.ts +36 -12
  46. package/client/web/src/function/utils/msgUtil.ts +32 -21
  47. package/client/web/src/function/utils/sessionUtil.ts +20 -18
  48. package/client/web/src/main.ts +5 -0
  49. package/client/web/src/pages/Chat.vue +50 -47
  50. package/client/web/src/pages/Friends.vue +28 -24
  51. package/client/web/src/pages/Info.vue +5 -5
  52. package/client/web/src/pages/Messages.vue +57 -36
  53. package/client/web/src/pages/Qzone.vue +2 -2
  54. package/client/web/src/pages/chat-view/ChatTerminal.vue +4 -1
  55. package/client/web/src/pages/chat-view/SystemNotice.vue +3 -3
  56. package/client/web/src/pages/options/OptAccount.vue +6 -4
  57. package/client/web/src/pages/options/OptDev.vue +45 -2
  58. package/lib/database.d.ts +58 -0
  59. package/lib/index.js +234 -82
  60. package/lib/media.d.ts +24 -0
  61. package/lib/recorder.d.ts +21 -0
  62. package/lib/self-message.d.ts +27 -0
  63. package/lib/types.d.ts +121 -0
  64. package/lib/web.d.ts +7 -0
  65. package/package.json +1 -1
  66. package/src/bootstrap.ts +1 -0
  67. package/src/cache.ts +1 -5
  68. package/src/config.ts +1 -1
  69. package/src/database.ts +52 -8
  70. package/src/index.ts +4 -4
  71. package/src/media.ts +97 -0
  72. package/src/recorder.ts +35 -26
  73. package/src/self-message.ts +68 -19
  74. package/src/types.ts +10 -0
  75. package/src/web.ts +57 -48
  76. package/client/web/dist/assets/Chat-B448YOeN.js +0 -28
  77. package/client/web/dist/assets/index-fW_zcub3.css +0 -1
@@ -10,7 +10,7 @@
10
10
  -->
11
11
 
12
12
  <template>
13
- <div class="friend-view">
13
+ <div class="friend-view" :class="{ 'empty-list': messageListEmpty }">
14
14
  <div class="friend-list-container">
15
15
  <div id="message-list"
16
16
  :class="'friend-list' +
@@ -18,39 +18,28 @@
18
18
  (showGroupAssist ? ' show' : '')">
19
19
  <div>
20
20
  <div class="base only">
21
- <span>{{ $t('消息') }}</span>
21
+ <span>{{ $t('消息列表') }}</span>
22
22
  <div style="flex: 1" />
23
23
  <font-awesome-icon
24
24
  :icon="['fas', 'clock-rotate-left']"
25
25
  @click="openHistory" />
26
26
  <font-awesome-icon :icon="['fas', 'trash-can']" @click="cleanList" />
27
27
  </div>
28
- <div class="small">
29
- <span>{{ $t('消息') }}</span>
30
- <div v-if="showGroupAssist"
31
- style="margin-right: -5px;margin-left: 5px;"
32
- @click="showGroupAssist = !showGroupAssist">
33
- <font-awesome-icon :icon="['fas', 'angle-left']" />
34
- </div>
35
- <div @click="openLeftBar">
36
- <font-awesome-icon :icon="['fas', 'bars-staggered']" />
37
- </div>
38
- </div>
39
28
  </div>
40
29
  <div id="message-list-body" class="robot-accordion-list">
41
- <div v-for="bot in satoriLogins" :key="'bot-' + bot.selfId"
42
- :class="['robot-accordion', { expanded: bot.selfId === activeBotId }]">
30
+ <div v-for="bot in satoriLogins" :key="'bot-' + botKey(bot.platform, bot.selfId)"
31
+ :class="['robot-accordion', { expanded: botKey(bot.platform, bot.selfId) === activeBotId }]">
43
32
  <div class="robot-accordion-header" @click="toggleRobot(bot)">
44
- <img :src="bot.avatar || '/img/icons/icon.svg'" :alt="bot.name" @error="avatarError">
33
+ <img data-avatar :src="bot.avatar || '/img/icons/icon.svg'" :alt="bot.name" @error="avatarError">
45
34
  <div>
46
35
  <span :title="bot.name">{{ bot.name }}</span>
47
36
  <small>{{ bot.platform }}</small>
48
37
  </div>
49
- <font-awesome-icon :icon="['fas', bot.selfId === activeBotId ? 'angle-up' : 'angle-down']" />
38
+ <font-awesome-icon :icon="['fas', botKey(bot.platform, bot.selfId) === activeBotId ? 'angle-up' : 'angle-down']" />
50
39
  </div>
51
- <div v-if="bot.selfId === activeBotId" class="robot-accordion-content">
40
+ <div v-if="botKey(bot.platform, bot.selfId) === activeBotId" class="robot-accordion-content">
52
41
  <div v-if="!showGroupAssist &&
53
- !contactStore.systemNoticesList &&
42
+ !hasSystemNotices &&
54
43
  (!contactStore.groupAssistList || contactStore.groupAssistList.length === 0) &&
55
44
  contactStore.onMsgList.length === 0"
56
45
  class="empty-state">
@@ -63,8 +52,7 @@
63
52
  style="overflow-x: hidden">
64
53
  <!-- 系统信息 -->
65
54
  <FriendBody v-if="!showGroupAssist &&
66
- contactStore.systemNoticesList &&
67
- Object.keys(contactStore.systemNoticesList).length > 0"
55
+ hasSystemNotices"
68
56
  key="inMessage--10000"
69
57
  :select="chat.show.id === -10000"
70
58
  :menu="menu.select && menu.select.user_id === -10000"
@@ -127,15 +115,15 @@
127
115
  <a v-if="contactStore.newMsgCount > 0">{{ contactStore.newMsgCount }}</a>
128
116
  </div>
129
117
  <div class="small">
130
- <span style="cursor: pointer;">
131
- {{ $t('群收纳盒') }}
132
- <a v-if="contactStore.newMsgCount > 0">{{ contactStore.newMsgCount }}</a>
133
- </span>
134
118
  <div v-if="showGroupAssist"
135
119
  style="margin-right: -5px;margin-left: 5px;"
136
120
  @click="showGroupAssist = !showGroupAssist">
137
121
  <font-awesome-icon :icon="['fas', 'angle-left']" />
138
122
  </div>
123
+ <span style="cursor: pointer;">
124
+ {{ $t('群收纳盒') }}
125
+ <a v-if="contactStore.newMsgCount > 0">{{ contactStore.newMsgCount }}</a>
126
+ </span>
139
127
  <div @click="openLeftBar">
140
128
  <font-awesome-icon :icon="['fas', 'bars-staggered']" />
141
129
  </div>
@@ -218,7 +206,7 @@
218
206
  import { library } from '@fortawesome/fontawesome-svg-core'
219
207
  import { login as loginInfo } from '../function/connect'
220
208
  import { Connector, flushPendingBotEvents, loadContactsFromCache, restoreBotStateFromMessageCache } from '../function/connect'
221
- import { getActiveBot, getLogins, setActiveBot } from '../function/satori'
209
+ import { botKey, getActiveBot, getLogins, setActiveBot } from '../function/satori'
222
210
  import { getShowName, updateBaseOnMsgList } from '../function/utils/msgUtil'
223
211
 
224
212
  import {
@@ -249,7 +237,12 @@
249
237
  const chatStore = useChatStore()
250
238
  const settingsStore = useSettingsStore()
251
239
  const satoriLogins = ref<Array<{ platform: string; selfId: string; name: string; avatar?: string; status?: number; features?: string[] }>>(getLogins())
252
- const activeBotId = ref(getActiveBot()?.selfId ?? loginInfo.selectedSatoriBot ?? '')
240
+ const active = getActiveBot()
241
+ const activeBotId = ref(
242
+ active?.platform && active.selfId
243
+ ? botKey(active.platform, active.selfId)
244
+ : loginInfo.selectedSatoriBot ?? '',
245
+ )
253
246
 
254
247
  watch(() => loginInfo.satoriLogins, (list) => {
255
248
  satoriLogins.value = list ?? []
@@ -259,7 +252,7 @@
259
252
  }, { immediate: true })
260
253
 
261
254
  const currentBotName = computed(() => {
262
- return satoriLogins.value.find((item) => item.selfId === activeBotId.value)?.name ?? ''
255
+ return satoriLogins.value.find((item) => botKey(item.platform, item.selfId) === activeBotId.value)?.name ?? ''
263
256
  })
264
257
 
265
258
  function backToRobots() {
@@ -280,7 +273,7 @@
280
273
  }
281
274
 
282
275
  function restoreBotStateUi(bot: { platform: string; selfId: string }) {
283
- const restored = contactStore.botStates.get(bot.selfId)
276
+ const restored = contactStore.botStates.get(botKey(bot.platform, bot.selfId))
284
277
  if (!restored) return
285
278
  contactStore.baseOnMsgList.clear()
286
279
  for (const [, value] of restored.baseList) {
@@ -309,9 +302,10 @@
309
302
  }
310
303
 
311
304
  function selectRobot(bot: { platform: string; selfId: string; name: string; avatar?: string; features?: string[] }) {
312
- if (bot.selfId === activeBotId.value) return
305
+ const key = botKey(bot.platform, bot.selfId)
306
+ if (key === activeBotId.value) return
313
307
  snapshotCurrentBot()
314
- activeBotId.value = bot.selfId
308
+ activeBotId.value = key
315
309
  setActiveBot(bot.platform, bot.selfId)
316
310
  loginInfo.uin = bot.selfId
317
311
  loginInfo.nickname = bot.name
@@ -324,9 +318,9 @@
324
318
  platform: bot.platform,
325
319
  avatar: bot.avatar,
326
320
  satoriLogins: satoriLogins.value,
327
- selectedSatoriBot: bot.selfId,
321
+ selectedSatoriBot: key,
328
322
  }
329
- const saved = contactStore.botStates.get(bot.selfId)
323
+ const saved = contactStore.botStates.get(key)
330
324
  if (saved) {
331
325
  contactStore.userList = saved.userList
332
326
  contactStore.baseOnMsgList.clear()
@@ -354,7 +348,7 @@
354
348
  }
355
349
 
356
350
  function toggleRobot(bot: { platform: string; selfId: string; name: string; avatar?: string; features?: string[] }) {
357
- if (activeBotId.value === bot.selfId) {
351
+ if (activeBotId.value === botKey(bot.platform, bot.selfId)) {
358
352
  backToRobots()
359
353
  } else {
360
354
  selectRobot(bot)
@@ -374,6 +368,17 @@
374
368
  const menu = Menu.append
375
369
  const showMenu = ref(false)
376
370
  const showGroupAssist = ref(false)
371
+ const hasSystemNotices = computed(() => {
372
+ const value = contactStore.systemNoticesList
373
+ if (Array.isArray(value)) return value.length > 0
374
+ return Boolean(value && Object.keys(value).length > 0)
375
+ })
376
+ const messageListEmpty = computed(() => {
377
+ return !showGroupAssist.value &&
378
+ !hasSystemNotices.value &&
379
+ (!contactStore.groupAssistList || contactStore.groupAssistList.length === 0) &&
380
+ contactStore.onMsgList.length === 0
381
+ })
377
382
 
378
383
  onMounted(() => {
379
384
  library.add(faCheckToSlot, faThumbTack, faTrashCan, faGripLines, faBroom)
@@ -389,6 +394,10 @@
389
394
  function userClick(data: UserFriendElem & UserGroupElem) {
390
395
  const id = data.group_id || data.user_id
391
396
  if (id === undefined || id === null || String(id) === '' || String(id) === '0') return
397
+ // 从群收纳盒进入群时先收起收纳盒,避免头部切换导致返回标记闪烁
398
+ if (showGroupAssist.value) {
399
+ showGroupAssist.value = false
400
+ }
392
401
  if (!trRead.value && id != props.chat.show.id) {
393
402
  if (uiStore.openSideBar) {
394
403
  openLeftBar()
@@ -889,16 +898,28 @@
889
898
  background: transparent !important;
890
899
  }
891
900
 
892
- @media (max-width: 700px) {
901
+ @media (max-width: 800px) {
893
902
  .friend-list-container {
894
903
  overflow: unset;
895
904
  }
905
+ .friend-view.empty-list .friend-list-container {
906
+ flex: 1;
907
+ min-width: 100%;
908
+ width: 100%;
909
+ }
910
+ .friend-view.empty-list #message-list {
911
+ flex: 1;
912
+ width: 100% !important;
913
+ }
914
+ .friend-view.empty-list .friend-list-space {
915
+ display: none !important;
916
+ }
896
917
  .menu {
897
918
  width: 140px !important;
898
919
  }
899
920
  }
900
921
 
901
- @media (max-width: 500px) {
922
+ @media (max-width: 800px) {
902
923
  .friend-list-container {
903
924
  overflow: hidden;
904
925
  }
@@ -65,7 +65,7 @@
65
65
  class="qzone-feed-card ss-card">
66
66
  <article>
67
67
  <header class="qzone-feed-card-header">
68
- <img :src="item.avatar" :alt="item.nickname">
68
+ <img data-avatar :src="item.avatar" :alt="item.nickname">
69
69
  <div class="qzone-feed-meta">
70
70
  <a>{{ item.nickname }}</a>
71
71
  <span>{{ item.timeText }}</span>
@@ -149,7 +149,7 @@
149
149
  </template>
150
150
  </div>
151
151
  <div class="qzone-feed-reply">
152
- <img :src="authStore.loginInfo.avatar || '/img/icons/icon.svg'">
152
+ <img data-avatar :src="authStore.loginInfo.avatar || '/img/icons/icon.svg'">
153
153
  <label :for="`qzone-reply-input-${item.id}`" class="sr-only">{{ $t('评论输入框') }}</label>
154
154
  <input :id="`qzone-reply-input-${item.id}`"
155
155
  v-model="getReplyDraft(item.id).content"
@@ -966,7 +966,10 @@ import packageInfo from '../../../package.json'
966
966
  border-radius: 7px;
967
967
  }
968
968
  .shell-msg.revoke {
969
- display: none;
969
+ display: flex;
970
+ opacity: 1;
971
+ border: 2px solid var(--color-red);
972
+ background: rgba(255, 80, 80, 0.08);
970
973
  }
971
974
  .shell-msg.reply {
972
975
  background: var(--color-card-1);
@@ -20,7 +20,7 @@
20
20
  :key="'sysNot-' + index">
21
21
  <div v-if="notice.request_type == 'friend'">
22
22
  <div>
23
- <img :src="notice.avatar || '/img/icons/icon.svg'">
23
+ <img data-avatar :src="notice.avatar || '/img/icons/icon.svg'">
24
24
  <div>
25
25
  <span>{{ notice.user_id }}
26
26
  {{ $t('请求加为好友') }}</span>
@@ -49,7 +49,7 @@
49
49
  </div>
50
50
  <div v-else-if="notice.request_type == 'group'">
51
51
  <div v-if="notice.sub_type == 'add'">
52
- <img :src="notice.avatar || '/img/icons/icon.svg'">
52
+ <img data-avatar :src="notice.avatar || '/img/icons/icon.svg'">
53
53
  <div>
54
54
  <span>{{ getName(notice.user_id) }}
55
55
  {{ $t('申请加入群聊') }}
@@ -68,7 +68,7 @@
68
68
  </div>
69
69
  <div v-else>
70
70
  <!-- TODO:这情况会出现在 notice 里?记不太清了,先放着吧 😭 -->
71
- <img :src="notice.group_avatar || '/img/icons/icon.svg'">
71
+ <img data-avatar :src="notice.group_avatar || '/img/icons/icon.svg'">
72
72
  <div>
73
73
  <span>{{ getName(notice.user_id) }}
74
74
  {{ $t('邀请你加入群聊') }}
@@ -13,7 +13,7 @@
13
13
  <div v-for="account in accounts"
14
14
  :key="account.platform + ':' + account.selfId"
15
15
  :class="['ss-card', 'account-info', { active: isActive(account) }]">
16
- <img :src="account.avatar || '/img/icons/icon.svg'">
16
+ <img data-avatar :src="account.avatar || '/img/icons/icon.svg'">
17
17
  <div>
18
18
  <div>
19
19
  <span>{{ account.name || account.selfId }}</span>
@@ -38,7 +38,7 @@
38
38
  <script setup lang="ts">
39
39
  import { computed } from 'vue'
40
40
  import { login as loginInfo } from '../../function/connect'
41
- import { getActiveBot } from '../../function/satori'
41
+ import { botKey, getActiveBot, getLogins } from '../../function/satori'
42
42
  import { useAuthStore } from '../../state/auth'
43
43
  import { i18n } from '../../main'
44
44
 
@@ -63,9 +63,11 @@ const accounts = computed<SatoriAccount[]>(() => {
63
63
  const activeBot = computed(() => {
64
64
  const current = getActiveBot()
65
65
  if (current?.platform && current.selfId) return current
66
+ const selectedKey = String(authStore.loginInfo.selectedSatoriBot ?? '')
67
+ const selected = getLogins().find((item) => botKey(item.platform, item.selfId) === selectedKey)
66
68
  return {
67
- platform: String(authStore.loginInfo.platform ?? ''),
68
- selfId: String(authStore.loginInfo.uin ?? authStore.loginInfo.selectedSatoriBot ?? ''),
69
+ platform: String(selected?.platform ?? authStore.loginInfo.platform ?? ''),
70
+ selfId: String(selected?.selfId ?? authStore.loginInfo.uin ?? ''),
69
71
  }
70
72
  })
71
73
 
@@ -52,12 +52,25 @@
52
52
  <span>{{ $t('将所有 WebUI 配置恢复为默认值') }}</span>
53
53
  </div>
54
54
  <button
55
- style="width: 100px; font-size: 0.8rem"
56
55
  class="ss-button"
56
+ style="width: 100px; font-size: 0.8rem; background: var(--color-red); border-color: var(--color-red); color: #fff"
57
57
  @click="resetDefaults">
58
58
  {{ $t('恢复') }}
59
59
  </button>
60
60
  </div>
61
+ <div class="opt-item">
62
+ <font-awesome-icon :icon="['fas', 'trash-can']" />
63
+ <div>
64
+ <span>{{ $t('删除数据库全部缓存') }}</span>
65
+ <span>{{ $t('清空媒体缓存、内容缓存和数据库历史记录') }}</span>
66
+ </div>
67
+ <button
68
+ style="width: 100px; font-size: 0.8rem; background: var(--color-red); border-color: var(--color-red); color: #fff"
69
+ class="ss-button"
70
+ @click="deleteAllCache">
71
+ {{ $t('删除') }}
72
+ </button>
73
+ </div>
61
74
  </div>
62
75
  </div>
63
76
  </template>
@@ -77,7 +90,7 @@ import packageInfo from '../../../package.json'
77
90
  get,
78
91
  getRaw,
79
92
  } from '../../function/option'
80
- import { Connector } from '../../function/connect'
93
+ import { clearAllCache, Connector } from '../../function/connect'
81
94
  import { PopInfo, PopType } from '../../function/base'
82
95
  import { isDebugMode } from '../../function/debug'
83
96
  import { dispatch } from '../../function/msg'
@@ -151,6 +164,36 @@ import packageInfo from '../../../package.json'
151
164
  uiStore.popBoxList.push(popInfo)
152
165
  }
153
166
 
167
+ function deleteAllCache() {
168
+ const popInfo = {
169
+ title: $t('删除数据库全部缓存'),
170
+ html: `<span>${$t('确认要删除全部缓存吗?删除后媒体图片、消息内容和数据库历史记录都会被清空。')}</span>`,
171
+ button: [
172
+ {
173
+ text: $t('确认'),
174
+ fun: async () => {
175
+ uiStore.popBoxList.shift()
176
+ const ok = await clearAllCache()
177
+ if (ok) {
178
+ new PopInfo().add(PopType.INFO, $t('缓存已全部删除'))
179
+ location.reload()
180
+ } else {
181
+ new PopInfo().add(PopType.ERR, $t('删除缓存失败'))
182
+ }
183
+ },
184
+ },
185
+ {
186
+ text: $t('取消'),
187
+ master: true,
188
+ fun: () => {
189
+ uiStore.popBoxList.shift()
190
+ },
191
+ },
192
+ ],
193
+ }
194
+ uiStore.popBoxList.push(popInfo)
195
+ }
196
+
154
197
  function sendTestWs(event: KeyboardEvent) {
155
198
  // 发送测试 WS 消息
156
199
  if (event.keyCode === 13 && ws_text.value !== '') {
@@ -0,0 +1,58 @@
1
+ import { Context } from 'koishi';
2
+ import { Config } from './config';
3
+ import { ContactCacheItem, MessageRecord, PinnedState, SelfMessageRecord } from './types';
4
+ import { PluginLogger } from './logger';
5
+ export declare class ChatDatabase {
6
+ private ctx;
7
+ private config;
8
+ private logger;
9
+ private db;
10
+ private opened;
11
+ constructor(ctx: Context, config: Config, logger: PluginLogger);
12
+ initialize(): Promise<void>;
13
+ dispose(): Promise<void>;
14
+ clearAll(): Promise<void>;
15
+ appendMessage(record: MessageRecord): Promise<void>;
16
+ upsertSelfMessage(record: SelfMessageRecord): Promise<void>;
17
+ listSelfMessages(platform: string, selfId: string, channelId: string, limit?: number): Promise<SelfMessageRecord[]>;
18
+ listSelfMessagesBefore(platform: string, selfId: string, channelId: string, beforeTime: number, limit?: number): Promise<SelfMessageRecord[]>;
19
+ updateSelfMessageByMessageId(platform: string, selfId: string, _channelId: string, messageId: string, patch: Partial<SelfMessageRecord>): Promise<boolean>;
20
+ updateMessageRevoked(platform: string, selfId: string, channelId: string, messageId: string, patch: {
21
+ revoked: boolean;
22
+ revokedAt: number;
23
+ }): Promise<boolean>;
24
+ findSelfForwardContent(platform: string, selfId: string, channelId: string, id: string): Promise<unknown[] | null>;
25
+ private removeSelfMessageByMessageId;
26
+ private parseSelfMessage;
27
+ listMessages(platform: string, selfId: string, channelId: string, limit?: number): Promise<MessageRecord[]>;
28
+ listMessagesBefore(platform: string, selfId: string, channelId: string, beforeTime: number, limit?: number): Promise<MessageRecord[]>;
29
+ clearChannel(platform: string, selfId: string, channelId: string): Promise<void>;
30
+ getPinned(): Promise<PinnedState>;
31
+ setPinned(state: PinnedState): Promise<void>;
32
+ getMeta(key: string): Promise<unknown>;
33
+ setMeta(key: string, value: unknown): Promise<void>;
34
+ recordMedia(url: string, filePath: string, channelId?: string): Promise<void>;
35
+ getMediaPath(url: string): Promise<string | undefined>;
36
+ getAllMedia(): Promise<Array<{
37
+ filePath: string;
38
+ channelId: string;
39
+ }>>;
40
+ removeMediaByPath(filePath: string): Promise<void>;
41
+ getContacts(platform: string, selfId: string, type: string): Promise<ContactCacheItem[]>;
42
+ getContact(platform: string, selfId: string, type: string, id: string): Promise<ContactCacheItem | null>;
43
+ setContacts(platform: string, selfId: string, type: string, contacts: ContactCacheItem[]): Promise<void>;
44
+ appendContact(platform: string, selfId: string, type: string, contact: ContactCacheItem): Promise<void>;
45
+ getContactsLegacy(platform: string, selfId: string, type: string): Promise<ContactCacheItem[]>;
46
+ getGroupMembers(platform: string, selfId: string, groupId: string): Promise<ContactCacheItem[]>;
47
+ setGroupMembers(platform: string, selfId: string, groupId: string, members: ContactCacheItem[]): Promise<void>;
48
+ getGroupMember(platform: string, selfId: string, groupId: string, userId: string): Promise<ContactCacheItem | null>;
49
+ appendGroupMember(platform: string, selfId: string, groupId: string, member: ContactCacheItem): Promise<void>;
50
+ getAllContacts(): Promise<Array<{
51
+ platform: string;
52
+ selfId: string;
53
+ type: string;
54
+ contacts: ContactCacheItem[];
55
+ }>>;
56
+ private trimMessages;
57
+ private trimSelfMessages;
58
+ }