@wirecat/cli-core 0.380.0 → 0.382.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.
- package/CHANGELOG.md +63 -1
- package/dist/cli/bot/watch.js +4 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/messenger/chat-answers.d.ts +2 -0
- package/dist/cli/messenger/chat-answers.js +2 -0
- package/dist/cli/messenger/chat-lists.d.ts +2 -0
- package/dist/cli/messenger/context.d.ts +2 -2
- package/dist/cli/messenger/context.js +2 -1
- package/dist/cli/messenger/conversation-answers.d.ts +1 -0
- package/dist/cli/messenger/message-answers.d.ts +1 -0
- package/dist/cli/messenger/message-items.js +1 -0
- package/dist/cli/messenger/message-writes.d.ts +1 -0
- package/dist/cli/messenger/serve-relay.d.ts +1 -0
- package/dist/cli/messenger/stored.d.ts +3 -1
- package/dist/cli/messenger/stored.js +24 -12
- package/dist/cli/messenger/watch-command.js +8 -0
- package/dist/domain/models.d.ts +52 -4
- package/dist/entities/chat.d.ts +4 -0
- package/dist/entities/chat.js +4 -0
- package/dist/entities/contact.d.ts +4 -0
- package/dist/entities/evidence.d.ts +8 -0
- package/dist/entities/index.d.ts +17 -0
- package/dist/entities/message.d.ts +2 -0
- package/dist/entities/message.js +2 -0
- package/dist/errors/reasons.js +1 -0
- package/dist/meetings/answers.d.ts +1 -0
- package/dist/meetings/import.js +1 -0
- package/dist/meetings/index.d.ts +1 -1
- package/dist/meetings/index.js +1 -1
- package/dist/meetings/item.d.ts +10 -0
- package/dist/meetings/item.js +34 -18
- package/dist/meetings/store.d.ts +6 -0
- package/dist/ports/messenger.d.ts +10 -3
- package/dist/ports/traits.d.ts +6 -0
- package/dist/resolve.d.ts +6 -0
- package/dist/resolve.js +13 -4
- package/dist/search/garbled.d.ts +2 -1
- package/dist/search/garbled.js +6 -1
- package/dist/services/chats.js +16 -2
- package/dist/services/deps.d.ts +2 -0
- package/dist/services/deps.js +2 -0
- package/dist/services/inbox.d.ts +1 -0
- package/dist/services/inbox.js +10 -3
- package/dist/store/keys.d.ts +1 -1
- package/dist/store/messages.d.ts +22 -3
- package/dist/store/messages.js +22 -3
- package/dist/store/sqlite/accounts.js +2 -1
- package/dist/store/sqlite/chat-rekey.js +18 -2
- package/dist/store/sqlite/chats.d.ts +2 -2
- package/dist/store/sqlite/chats.js +39 -9
- package/dist/store/sqlite/manifest.js +3 -0
- package/dist/store/sqlite/meeting-hit-query.js +18 -3
- package/dist/store/sqlite/meetings.js +56 -1
- package/dist/store/sqlite/messages.d.ts +19 -4
- package/dist/store/sqlite/messages.js +103 -5
- package/dist/store/sqlite/migrations.generated.js +23 -0
- package/dist/store/sqlite/open-store.js +16 -5
- package/dist/store/sqlite/reads.d.ts +50 -0
- package/dist/store/sqlite/reads.js +3 -1
- package/dist/store/sqlite/schema.d.ts +251 -0
- package/dist/store/sqlite/schema.js +28 -0
- package/dist/store/sqlite/search.d.ts +33 -0
- package/dist/store/sqlite/values.d.ts +4 -0
- package/dist/store/sqlite/values.js +3 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,12 +5,73 @@ Notable changes to `@wirecat/cli-core` (`@wirecat/cli-messaging` up to 0.261.0,
|
|
|
5
5
|
minor version may break callers, and says how under "Changed — may break callers". `pnpm docs:check` checks the
|
|
6
6
|
shape of this file.
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## 0.382.0 — 22.10.2026
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **A chat's state from the phone (store version 28).** The store keeps `Chat.muted`, `Chat.archived` and two new
|
|
13
|
+
fields: `mutedUntil` (when a mute ends, UTC; none is for good) and `markedUnread` (the owner marked the chat unread).
|
|
14
|
+
A `ChatUpdate` that leaves one out keeps the stored value, and a mute past its end reads as over. Stored chats show
|
|
15
|
+
them, and `chat` gains `muted_until` and `marked_unread`. So `inbox` and `review` over the store now leave out muted
|
|
16
|
+
and archived chats, as they do for a messenger that answers live, and `inbox` takes in a chat marked unread with its
|
|
17
|
+
newest message from someone else. tg and max send `muted` and `archived` in their chat lists, so their stored chats
|
|
18
|
+
now show them too.
|
|
19
|
+
- **The store can count unread messages** for a messenger that sets `unreadCounts: "store"`: each new message from
|
|
20
|
+
someone else that `watch` or `listen` saves after the messenger's last count adds one, and a whole-chat `chats read`
|
|
21
|
+
stores 0. `store.messages.saveMessages` takes `countUnread`. tg and max leave it unset and count as before. See
|
|
22
|
+
[adapters](docs/dev/ADAPTERS.md).
|
|
23
|
+
- **Delivered and read on the owner's own messages (store version 27).** `Message.delivery` (`delivered` or `read`)
|
|
24
|
+
says how far the owner's message in a one-to-one chat got; a `watch` event `{ event: "delivery", chatId, chatTitle,
|
|
25
|
+
messageId, delivery, at }` (`MessageDeliveryEvent`) carries a receipt as it comes. `store.messages.saveDelivery` and
|
|
26
|
+
a saved message's own `delivery` keep it in the new `messages.delivery` column, only on the owner's messages and
|
|
27
|
+
only ever forward. Stored messages show it as `delivery`. tg and max send none and see no change. See
|
|
28
|
+
[adapters](docs/dev/ADAPTERS.md).
|
|
29
|
+
|
|
30
|
+
## 0.381.0 — 22.10.2026
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- **Meeting search finds words speech recognition cut off.** A stored word of four letters or more that begins a
|
|
35
|
+
query word, and that the Russian dictionary does not know, widens it: «може» for «может», «напри» for «например».
|
|
36
|
+
Real shorter words («после» for «последующих») still do not. This is ztx's rule, behind the dictionary.
|
|
37
|
+
- **A meeting answer names what about it is doubtful, in `issues`.** `MEETING_ISSUES` lists the values; today one,
|
|
38
|
+
`time_without_zone`: the provider sent a time with no zone, and it was read in the computer's zone. A provider
|
|
39
|
+
adapter keeps the data and puts the issue in the meeting's `metadata.issues`; `meetingItem` shows the known ones and
|
|
40
|
+
leaves the field out when there are none. No store change.
|
|
41
|
+
|
|
42
|
+
- **People's reactions in the store (store version 26).** For a messenger that sends one person's reaction change at a
|
|
43
|
+
time (WhatsApp), a `watch` event `{ event: "person_reaction", chatId, chatTitle, messageId, reaction }`
|
|
44
|
+
(`PersonReactionEvent`) and a pushed batch's `reactions` (`HistoryReaction`) carry `PersonReaction`
|
|
45
|
+
(`{ person, own, reaction, reactedAt }`, `reaction: null` a take-back). `store.messages.saveReaction` and
|
|
46
|
+
`saveMessages({ reactions })` keep each person's newest in the new `message_reactions` table, so an older history
|
|
47
|
+
push never undoes a newer live change, and write the message's `reactions` totals from them: readers, output and
|
|
48
|
+
MCP see the same shape. tg and max keep sending totals; a message with people's reactions keeps the derived ones.
|
|
49
|
+
See [adapters](docs/dev/ADAPTERS.md).
|
|
50
|
+
|
|
51
|
+
### Fixed
|
|
52
|
+
|
|
53
|
+
- **A chat or person is found by a name copied with its emoji.** A copied emoji often carries an invisible mark
|
|
54
|
+
(U+FE0F, U+FE0E, or the U+200D joiner) that a typed one lacks, so "Семья❤️" did not find the chat "Семья❤". Names
|
|
55
|
+
now compare without those marks and with accented letters in one form, still ignoring case, wherever a chat or a
|
|
56
|
+
person is named (`pickChat`, `pickPerson`, a stored alias).
|
|
57
|
+
- **`from:` finds a speaker known only by name across meetings.** A participant keyed by name in one meeting
|
|
58
|
+
(`name:…@account/occurrence:n`, as zoom-cli's `.txt` speakers and nameless API participants are) is grouped with
|
|
59
|
+
the same name elsewhere, and with the one identified speaker of that name when there is exactly one. Before,
|
|
60
|
+
each meeting's copy was a separate candidate, so `from:"Name"` was ambiguous. Candidates with an email show it.
|
|
61
|
+
|
|
62
|
+
- **A store the process may not write is a permission error, not a crash.** Opening the store for writing where the
|
|
63
|
+
file or its folder is read-only (`EROFS`, `EACCES`, `EPERM`) was reported as `internal_error` "this is a bug".
|
|
64
|
+
It is now `permission_error` (exit 5) with reason `store.not-writable`, and the message names no path.
|
|
9
65
|
|
|
10
66
|
## 0.380.0 — 21.10.2026
|
|
11
67
|
|
|
12
68
|
### Added
|
|
13
69
|
|
|
70
|
+
- **A file's copy and the provider's copy of one meeting are one record.** `MeetingSave.fromFile` marks a save read
|
|
71
|
+
from a file; it joins the provider's record of the same occurrence (same series key, start within 15 minutes)
|
|
72
|
+
and only fills a missing transcript there. A provider record saved after a file takes over that record and its
|
|
73
|
+
key, and a provider transcript supersedes transcripts with source `file`. Two provider records never merge.
|
|
74
|
+
See [meetings](docs/dev/MEETINGS.md).
|
|
14
75
|
- **Meetings import text transcripts.** `parseTranscriptText` reads the text form zoom-searcher wrote: the header
|
|
15
76
|
(`Встреча:` title, `Дата:` start as written, `Zoom ID:`, `Говорят:` speakers) and `[hh:mm:ss] Speaker: text`
|
|
16
77
|
blocks, a block running over several lines. `ImportFile.format: "text"` makes `importFiles` use it; `vtt` stays
|
|
@@ -18,6 +79,7 @@ shape of this file.
|
|
|
18
79
|
- **An import says the zone it read file times in, and a host can explain its file names.** `RunReport.timezone` is
|
|
19
80
|
set when every imported file's meeting carries one zone; `MeetingCommandDeps.importHelp` adds the host's note
|
|
20
81
|
(file name patterns, how their time is read) under `meetings import --help`.
|
|
82
|
+
||||||| Stash base
|
|
21
83
|
- **Meeting search finds words spread over neighbouring lines.** `"циан риелтор"~3` in a meeting query finds a
|
|
22
84
|
transcript line with one of the words when the others are at most three lines away in the same transcript; `~0`
|
|
23
85
|
is one line, any order; at most 20. The words widen to garbled spellings as single words do. It needs
|
package/dist/cli/bot/watch.js
CHANGED
|
@@ -131,7 +131,7 @@ export const botWatchCommand = (bot) => annotate(new Command("watch"), { effects
|
|
|
131
131
|
else if (event.event === "delete") {
|
|
132
132
|
context.streams.data(`deleted in ${title(event.chatId)}: message ${event.messageId}\n`);
|
|
133
133
|
}
|
|
134
|
-
else if (event.event === "reaction") {
|
|
134
|
+
else if (event.event === "reaction" || event.event === "person_reaction") {
|
|
135
135
|
context.streams.data(`reactions in ${title(event.chatId)} on message ${event.messageId}\n`);
|
|
136
136
|
}
|
|
137
137
|
else if (event.event === "vote") {
|
|
@@ -140,6 +140,9 @@ export const botWatchCommand = (bot) => annotate(new Command("watch"), { effects
|
|
|
140
140
|
else if (event.event === "star") {
|
|
141
141
|
context.streams.data(`${event.starred ? "starred" : "unstarred"} in ${title(event.chatId)}: message ${event.messageId}\n`);
|
|
142
142
|
}
|
|
143
|
+
else if (event.event === "delivery") {
|
|
144
|
+
context.streams.data(`${event.delivery} in ${title(event.chatId)}: message ${event.messageId}\n`);
|
|
145
|
+
}
|
|
143
146
|
else if (event.event === "chat_event") {
|
|
144
147
|
context.streams.data(`${event.change.event} in ${title(event.chatId)}\n`);
|
|
145
148
|
}
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export { callMeetingSeriesInventoryTool, meetingSeriesInventoryTool } from "../m
|
|
|
11
11
|
export { registerLinkConversationsPrompt } from "../mcp/prompts.js";
|
|
12
12
|
export { agentBody, agentJson, agentResult, UNTRUSTED, UNTRUSTED_INSTRUCTION } from "../mcp/text.js";
|
|
13
13
|
export { type AppIdentity, envName, readOnlyLockOf, readOnlyRefusal } from "../ports/app.js";
|
|
14
|
-
export type { AccountEditing, AccountHealth, AccountRecords, AccountSettings, AccountStanding, AccountTools, After, BotChats, ChannelComments, ChatDeletion, ChatFolders, ChatReading, ContactBook, Download, ForumControl, ForumState, GroupAdmin, GroupModeration, HistoryBatch, HistoryChatEvent, HistoryStar, HistoryVote, InviteLinks, JoinRequests, LiveUpdates, MessageButtons, MessageEditing, MessageMedia, MessagePermalinks, MessagePins, MessagePolls, MessageReactions, MessageSearch, MessageStars, MessengerAdapter, MessengerCore, NewPoll, OfficialStats, PassiveUpdates, PersonProfiles, ProfileChange, ProfilePhotos, PushedHistory, ReadState, RemoteFile, ScheduledMessages, SenderIdentities, SenderSearch, SendOptions, Sent, ServerQuery, ServerReads, ThreadAddressing, TopicEditing, TopicHistory, TopicReadState, Transcript, } from "../ports/messenger.js";
|
|
14
|
+
export type { AccountEditing, AccountHealth, AccountRecords, AccountSettings, AccountStanding, AccountTools, After, BotChats, ChannelComments, ChatDeletion, ChatFolders, ChatReading, ContactBook, Download, ForumControl, ForumState, GroupAdmin, GroupModeration, HistoryBatch, HistoryChatEvent, HistoryReaction, HistoryStar, HistoryVote, InviteLinks, JoinRequests, LiveUpdates, MessageButtons, MessageEditing, MessageMedia, MessagePermalinks, MessagePins, MessagePolls, MessageReactions, MessageSearch, MessageStars, MessengerAdapter, MessengerCore, NewPoll, OfficialStats, PassiveUpdates, PersonProfiles, ProfileChange, ProfilePhotos, PushedHistory, ReadState, RemoteFile, ScheduledMessages, SenderIdentities, SenderSearch, SendOptions, Sent, ServerQuery, ServerReads, ThreadAddressing, TopicEditing, TopicHistory, TopicReadState, Transcript, } from "../ports/messenger.js";
|
|
15
15
|
export type { Fetching, MediaOption, MessengerTraits } from "../ports/traits.js";
|
|
16
16
|
export { senderFacts } from "../replies/dry-run.js";
|
|
17
17
|
export { type ReplyRender, replyRenderer } from "../replies/rendering.js";
|
|
@@ -61,7 +61,9 @@ export declare const chatShown: (account: AccountKey, card: Parameters<typeof ch
|
|
|
61
61
|
last_message_at: string | null;
|
|
62
62
|
participants_count: number | null;
|
|
63
63
|
muted?: boolean | undefined;
|
|
64
|
+
muted_until?: string | undefined;
|
|
64
65
|
archived?: boolean | undefined;
|
|
66
|
+
marked_unread?: boolean | undefined;
|
|
65
67
|
membership_state?: "archived" | "external" | "imported" | "joined" | "left" | "public" | undefined;
|
|
66
68
|
parent_chat_id?: string | undefined;
|
|
67
69
|
scope?: "personal" | "work" | undefined;
|
|
@@ -28,7 +28,9 @@ export const chatAnswer = (account, chat) => defined({
|
|
|
28
28
|
last_message_at: chat.lastMessageAt,
|
|
29
29
|
participants_count: chat.participantsCount,
|
|
30
30
|
muted: chat.muted,
|
|
31
|
+
muted_until: chat.mutedUntil ?? undefined,
|
|
31
32
|
archived: chat.archived,
|
|
33
|
+
marked_unread: chat.markedUnread,
|
|
32
34
|
membership_state: chat.membershipState,
|
|
33
35
|
parent_chat_id: chat.parentChatId ?? undefined,
|
|
34
36
|
scope: chat.scope,
|
|
@@ -21,7 +21,9 @@ export declare const chatsList: (services: Services, query: QueryWords, paging:
|
|
|
21
21
|
last_message_at: string | null;
|
|
22
22
|
participants_count: number | null;
|
|
23
23
|
muted?: boolean | undefined;
|
|
24
|
+
muted_until?: string | undefined;
|
|
24
25
|
archived?: boolean | undefined;
|
|
26
|
+
marked_unread?: boolean | undefined;
|
|
25
27
|
membership_state?: "archived" | "external" | "imported" | "joined" | "left" | "public" | undefined;
|
|
26
28
|
parent_chat_id?: string | undefined;
|
|
27
29
|
scope?: "personal" | "work" | undefined;
|
|
@@ -236,12 +236,12 @@ type ConnectionWaits = Pick<BaseEnvironment, "closeWaitMs" | "rekeyPacing">;
|
|
|
236
236
|
* does not `watch` is open: what it queued while nothing was connected is delivered once and cannot be fetched again.
|
|
237
237
|
* A connection opened with `listen: true` is left to its `watch` and `feed`, which save the same.
|
|
238
238
|
*/
|
|
239
|
-
export declare const connected: (connection: MessengerAdapter, { app, provider, name, deletedWithoutChat, pace, history, savedChatId, }: Pick<Messenger, "app" | "provider" | "name" | "deletedWithoutChat" | "pace" | "history" | "savedChatId">, { settings, env, renderer }: Pick<BaseContext, "settings" | "env" | "renderer">, events: EventSink, store?: LazyStore, { listen: watching, closeWaitMs, rekeyPacing, }?: Pick<ConnectOptions, "listen"> & ConnectionWaits) => {
|
|
239
|
+
export declare const connected: (connection: MessengerAdapter, { app, provider, name, deletedWithoutChat, pace, history, savedChatId, unreadCounts, }: Pick<Messenger, "app" | "provider" | "name" | "deletedWithoutChat" | "pace" | "history" | "savedChatId" | "unreadCounts">, { settings, env, renderer }: Pick<BaseContext, "settings" | "env" | "renderer">, events: EventSink, store?: LazyStore, { listen: watching, closeWaitMs, rekeyPacing, }?: Pick<ConnectOptions, "listen"> & ConnectionWaits) => {
|
|
240
240
|
adapter: MessengerAdapter;
|
|
241
241
|
close: () => Promise<void>;
|
|
242
242
|
};
|
|
243
243
|
/** `connectFor` and then `connected`, over one store handle: what the reads save and what the adapter looks up. */
|
|
244
|
-
export declare const connectedFor: (command: Command, messenger: Pick<Messenger, "connect" | "app" | "provider" | "name" | "deletedWithoutChat" | "pace" | "history" | "savedChatId">, base: BaseContext, options: ConnectOptions & {
|
|
244
|
+
export declare const connectedFor: (command: Command, messenger: Pick<Messenger, "connect" | "app" | "provider" | "name" | "deletedWithoutChat" | "pace" | "history" | "savedChatId" | "unreadCounts">, base: BaseContext, options: ConnectOptions & {
|
|
245
245
|
events: EventSink;
|
|
246
246
|
}) => Promise<{
|
|
247
247
|
connection: MessengerAdapter;
|
|
@@ -189,7 +189,7 @@ const waitsOf = (command) => {
|
|
|
189
189
|
* does not `watch` is open: what it queued while nothing was connected is delivered once and cannot be fetched again.
|
|
190
190
|
* A connection opened with `listen: true` is left to its `watch` and `feed`, which save the same.
|
|
191
191
|
*/
|
|
192
|
-
export const connected = (connection, { app, provider, name, deletedWithoutChat, pace, history, savedChatId, }, { settings, env, renderer }, events, store = lazyStore(env, app.command), { listen: watching = false, closeWaitMs = SAVES_WAIT_MS, rekeyPacing, } = {}) => {
|
|
192
|
+
export const connected = (connection, { app, provider, name, deletedWithoutChat, pace, history, savedChatId, unreadCounts, }, { settings, env, renderer }, events, store = lazyStore(env, app.command), { listen: watching = false, closeWaitMs = SAVES_WAIT_MS, rekeyPacing, } = {}) => {
|
|
193
193
|
const self = connection.self();
|
|
194
194
|
if (self !== null)
|
|
195
195
|
rememberAccount(app, settings.profile, self, env);
|
|
@@ -220,6 +220,7 @@ export const connected = (connection, { app, provider, name, deletedWithoutChat,
|
|
|
220
220
|
rekeyed: (from, to) => rekeyRecipients(app, settings.profile, env, renderer.warn, from, to),
|
|
221
221
|
recipientIds: () => (new RecipientList(recipientsPathFor(app, settings.profile, env), app.command).read() ?? []).flatMap((recipient) => [recipient.id, ...(recipient.partnerId ? [recipient.partnerId] : [])]),
|
|
222
222
|
...(history === "store" ? { namesFromStore: savedChatId ? { savedChatId } : {} } : {}),
|
|
223
|
+
...(unreadCounts === "store" ? { countsUnread: true } : {}),
|
|
223
224
|
});
|
|
224
225
|
const passives = history === "store" && self !== null && !watching
|
|
225
226
|
? passivesOf(saving).map((passive) => listened(passive, events, renderer.warn, closeWaitMs))
|
|
@@ -175,6 +175,7 @@ export declare const conversationShown: (account: AccountKey, { summary, message
|
|
|
175
175
|
} | null | undefined;
|
|
176
176
|
scheduled_for?: string | undefined;
|
|
177
177
|
starred?: true | undefined;
|
|
178
|
+
delivery?: "delivered" | "read" | undefined;
|
|
178
179
|
email?: {
|
|
179
180
|
subject: string | null;
|
|
180
181
|
from: {
|
|
@@ -152,6 +152,7 @@ export declare const threadAnswer: ({ items, ...thread }: ThreadContext, reader:
|
|
|
152
152
|
} | null | undefined;
|
|
153
153
|
scheduled_for?: string | undefined;
|
|
154
154
|
starred?: true | undefined;
|
|
155
|
+
delivery?: "delivered" | "read" | undefined;
|
|
155
156
|
email?: {
|
|
156
157
|
subject: string | null;
|
|
157
158
|
from: {
|
|
@@ -59,6 +59,7 @@ export const messageItem = (message, reader) => {
|
|
|
59
59
|
reactions: message.reactions,
|
|
60
60
|
scheduled_for: message.scheduledFor,
|
|
61
61
|
starred: message.starred === true ? true : undefined,
|
|
62
|
+
delivery: message.delivery,
|
|
62
63
|
email: message.email === undefined
|
|
63
64
|
? undefined
|
|
64
65
|
: {
|
|
@@ -154,6 +154,7 @@ export declare const writtenAnswer: ({ operationId, sendId, message, scheduledFo
|
|
|
154
154
|
} | null | undefined;
|
|
155
155
|
scheduled_for?: string | undefined;
|
|
156
156
|
starred?: true | undefined;
|
|
157
|
+
delivery?: "delivered" | "read" | undefined;
|
|
157
158
|
email?: {
|
|
158
159
|
subject: string | null;
|
|
159
160
|
from: {
|
|
@@ -32,6 +32,7 @@ export declare const serveRelay: (command: Command, messenger: Messenger) => {
|
|
|
32
32
|
fetching?: import("../index.js").Fetching;
|
|
33
33
|
history?: "server" | "store";
|
|
34
34
|
historyOnDemand?: boolean;
|
|
35
|
+
unreadCounts?: "messenger" | "store";
|
|
35
36
|
serverSearch?: boolean | "chat";
|
|
36
37
|
services?: import("../../services/index.js").Override;
|
|
37
38
|
connection?: "exclusive";
|
|
@@ -39,6 +39,8 @@ export interface Saving {
|
|
|
39
39
|
* titles `watch` leaves out, are answered from the store first. Its server has no directory to ask.
|
|
40
40
|
*/
|
|
41
41
|
namesFromStore?: Pick<MessengerTraits, "savedChatId">;
|
|
42
|
+
/** `MessengerTraits.unreadCounts: "store"`: a message `watch` or `listen` saves raises its chat's unread count. */
|
|
43
|
+
countsUnread?: boolean;
|
|
42
44
|
}
|
|
43
45
|
/**
|
|
44
46
|
* The adapter, with what each read answers written to the store. **A failed write never fails the
|
|
@@ -48,4 +50,4 @@ export interface Saving {
|
|
|
48
50
|
* would erase what `chats list` stored. Nor are `chat` and `contact`: a card's member list is not
|
|
49
51
|
* known to be whole, and `saveMembers` replaces the list.
|
|
50
52
|
*/
|
|
51
|
-
export declare const stored: (messenger: MessengerAdapter, { account, store, warn, events, pending, announcing, deletedWithoutChat, profile, rekeyed, rekeyPacing, closing, namesFromStore, recipientIds, }: Saving) => MessengerAdapter;
|
|
53
|
+
export declare const stored: (messenger: MessengerAdapter, { account, store, warn, events, pending, announcing, deletedWithoutChat, profile, rekeyed, rekeyPacing, closing, namesFromStore, recipientIds, countsUnread, }: Saving) => MessengerAdapter;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CliError } from "@wirecat/cli-base";
|
|
2
2
|
import { capability, throughWrapper } from "../../ports/messenger.js";
|
|
3
|
-
import { isId, pickPerson } from "../../resolve.js";
|
|
3
|
+
import { foldName, isId, pickPerson } from "../../resolve.js";
|
|
4
4
|
import { codeOf } from "../../sends/guarded.js";
|
|
5
5
|
import { chatIdIn } from "../../services/message-resolution.js";
|
|
6
6
|
const REKEY_PACING = { lockMs: 50, pauseMs: 25 };
|
|
@@ -12,7 +12,7 @@ const REKEY_PACING = { lockMs: 50, pauseMs: 25 };
|
|
|
12
12
|
* would erase what `chats list` stored. Nor are `chat` and `contact`: a card's member list is not
|
|
13
13
|
* known to be whole, and `saveMembers` replaces the list.
|
|
14
14
|
*/
|
|
15
|
-
export const stored = (messenger, { account, store, warn, events, pending, announcing, deletedWithoutChat, profile, rekeyed, rekeyPacing = REKEY_PACING, closing, namesFromStore, recipientIds, }) => {
|
|
15
|
+
export const stored = (messenger, { account, store, warn, events, pending, announcing, deletedWithoutChat, profile, rekeyed, rekeyPacing = REKEY_PACING, closing, namesFromStore, recipientIds, countsUnread = false, }) => {
|
|
16
16
|
let warned = false;
|
|
17
17
|
let recorded = profile === undefined;
|
|
18
18
|
const notWritten = (operation, error) => {
|
|
@@ -212,8 +212,8 @@ export const stored = (messenger, { account, store, warn, events, pending, annou
|
|
|
212
212
|
const { id, held } = namesFromStore ? await storedChat(opened, scoped, namesFromStore, reference) : {};
|
|
213
213
|
if (!isId(reference)) {
|
|
214
214
|
const people = await opened.people.people(scoped.provider, { account: scoped.account });
|
|
215
|
-
const wanted = reference.trim()
|
|
216
|
-
if (people.all().some((person) => person.alias
|
|
215
|
+
const wanted = foldName(reference.trim());
|
|
216
|
+
if (people.all().some((person) => person.alias && foldName(person.alias).includes(wanted))) {
|
|
217
217
|
const person = pickPerson(reference, people);
|
|
218
218
|
const chats = (await opened.chats.chatsWith(scoped, person.id)).filter((chat) => chat.kind === "dialog");
|
|
219
219
|
if (chats.length !== 1 || !chats[0])
|
|
@@ -318,7 +318,7 @@ export const stored = (messenger, { account, store, warn, events, pending, annou
|
|
|
318
318
|
await rememberTitles(store, account, titles);
|
|
319
319
|
return (messenger.watch?.((event) => {
|
|
320
320
|
const seenAt = Date.now();
|
|
321
|
-
void save("messages.watch", (opened) => keep(opened, account, event, seenAt, deletedWithoutChat));
|
|
321
|
+
void save("messages.watch", (opened) => keep(opened, account, event, seenAt, deletedWithoutChat, countsUnread));
|
|
322
322
|
onEvent(namesFromStore ? titled(event, titles) : event);
|
|
323
323
|
}, signal, onReady) ?? Promise.resolve());
|
|
324
324
|
},
|
|
@@ -327,7 +327,7 @@ export const stored = (messenger, { account, store, warn, events, pending, annou
|
|
|
327
327
|
...(messenger.listen
|
|
328
328
|
? {
|
|
329
329
|
listen: (onEvent, signal) => messenger.listen?.((event) => {
|
|
330
|
-
void save("messages.listen", (opened) => keep(opened, account, event, Date.now(), deletedWithoutChat));
|
|
330
|
+
void save("messages.listen", (opened) => keep(opened, account, event, Date.now(), deletedWithoutChat, countsUnread));
|
|
331
331
|
onEvent(event);
|
|
332
332
|
}, signal) ?? Promise.resolve(),
|
|
333
333
|
}
|
|
@@ -517,7 +517,7 @@ const fill = async (store, account, batch) => {
|
|
|
517
517
|
await store.people.savePeople(account, batch.people);
|
|
518
518
|
const byChat = new Map();
|
|
519
519
|
const of = (chatId) => {
|
|
520
|
-
const held = byChat.get(chatId) ?? { messages: [], votes: [], stars: [] };
|
|
520
|
+
const held = byChat.get(chatId) ?? { messages: [], votes: [], reactions: [], stars: [] };
|
|
521
521
|
byChat.set(chatId, held);
|
|
522
522
|
return held;
|
|
523
523
|
};
|
|
@@ -525,10 +525,12 @@ const fill = async (store, account, batch) => {
|
|
|
525
525
|
of(message.chatId).messages.push(message);
|
|
526
526
|
for (const { chatId, messageId, vote } of batch.votes ?? [])
|
|
527
527
|
of(chatId).votes.push({ messageId, vote });
|
|
528
|
+
for (const { chatId, messageId, reaction } of batch.reactions ?? [])
|
|
529
|
+
of(chatId).reactions.push({ messageId, reaction });
|
|
528
530
|
for (const { chatId, messageId, starred } of batch.stars ?? [])
|
|
529
531
|
of(chatId).stars.push({ messageId, starred });
|
|
530
|
-
for (const [chatId, { messages, votes, stars }] of byChat)
|
|
531
|
-
await store.messages.saveMessages(account, chatId, messages, { via: "history", votes, stars });
|
|
532
|
+
for (const [chatId, { messages, votes, reactions, stars }] of byChat)
|
|
533
|
+
await store.messages.saveMessages(account, chatId, messages, { via: "history", votes, reactions, stars });
|
|
532
534
|
const changes = new Map();
|
|
533
535
|
for (const { chatId, change } of batch.events ?? [])
|
|
534
536
|
changes.set(chatId, [...(changes.get(chatId) ?? []), change]);
|
|
@@ -537,14 +539,18 @@ const fill = async (store, account, batch) => {
|
|
|
537
539
|
};
|
|
538
540
|
/**
|
|
539
541
|
* Each change as the store keeps it: a message or an edit upserted, a deletion a tombstone, reactions replaced, a
|
|
540
|
-
* voter's vote replacing their older one, a star set or taken off, a chat event kept once.
|
|
542
|
+
* voter's vote or a person's reaction replacing their older one, a star set or taken off, a chat event kept once.
|
|
541
543
|
*/
|
|
542
|
-
const keep = async (store, account, event, seenAt, among) => {
|
|
544
|
+
const keep = async (store, account, event, seenAt, among, countsUnread) => {
|
|
543
545
|
switch (event.event) {
|
|
544
546
|
case "message":
|
|
545
547
|
case "edit": {
|
|
546
548
|
const { chatTitle, ...message } = event.message;
|
|
547
|
-
await store.messages.saveMessages(account, message.chatId, [message], {
|
|
549
|
+
await store.messages.saveMessages(account, message.chatId, [message], {
|
|
550
|
+
via: "update",
|
|
551
|
+
seenAt,
|
|
552
|
+
...(countsUnread && event.event === "message" ? { countUnread: true } : {}),
|
|
553
|
+
});
|
|
548
554
|
return;
|
|
549
555
|
}
|
|
550
556
|
case "delete":
|
|
@@ -553,9 +559,15 @@ const keep = async (store, account, event, seenAt, among) => {
|
|
|
553
559
|
case "vote":
|
|
554
560
|
await store.messages.saveVote(account, event.chatId, event.messageId, event.vote);
|
|
555
561
|
return;
|
|
562
|
+
case "person_reaction":
|
|
563
|
+
await store.messages.saveReaction(account, event.chatId, event.messageId, event.reaction);
|
|
564
|
+
return;
|
|
556
565
|
case "star":
|
|
557
566
|
await store.messages.saveStar(account, event.chatId, event.messageId, event.starred);
|
|
558
567
|
return;
|
|
568
|
+
case "delivery":
|
|
569
|
+
await store.messages.saveDelivery(account, event.chatId, event.messageId, event.delivery);
|
|
570
|
+
return;
|
|
559
571
|
case "chat_event":
|
|
560
572
|
await store.roster.saveChatEvents(account, event.chatId, [event.change]);
|
|
561
573
|
return;
|
|
@@ -110,8 +110,16 @@ const describe = (event, render) => {
|
|
|
110
110
|
const choice = answers.length > 0 ? answers.join(", ") : "took it back";
|
|
111
111
|
return `vote in ${event.chatTitle ?? event.chatId} on poll ${event.messageId}: ${person.name ?? person.id} — ${choice}\n`;
|
|
112
112
|
}
|
|
113
|
+
case "person_reaction": {
|
|
114
|
+
const { person, reaction } = event.reaction;
|
|
115
|
+
const who = person.name ?? person.id;
|
|
116
|
+
const what = reaction === null ? "took their reaction back" : `reacted ${reaction}`;
|
|
117
|
+
return `${who} ${what} in ${event.chatTitle ?? event.chatId} on message ${event.messageId}\n`;
|
|
118
|
+
}
|
|
113
119
|
case "star":
|
|
114
120
|
return `${event.starred ? "starred" : "unstarred"} in ${event.chatTitle ?? event.chatId}: message ${event.messageId}\n`;
|
|
121
|
+
case "delivery":
|
|
122
|
+
return `${event.delivery} in ${event.chatTitle ?? event.chatId}: message ${event.messageId}\n`;
|
|
115
123
|
case "chat_event": {
|
|
116
124
|
const { event: action, by, people } = event.change;
|
|
117
125
|
const who = people.map((one) => one.name ?? one.id).join(", ");
|
package/dist/domain/models.d.ts
CHANGED
|
@@ -33,9 +33,16 @@ export interface Chat {
|
|
|
33
33
|
/** ISO 8601, or `null` when the chat has never had a message. */
|
|
34
34
|
lastMessageAt: string | null;
|
|
35
35
|
participantsCount: number | null;
|
|
36
|
-
/** Absent where the messenger does not say. */
|
|
36
|
+
/** Absent where the messenger does not say. A mute that has ended reads as `false`. */
|
|
37
37
|
muted?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* ISO 8601 UTC: when the mute ends. `null` or absent with `muted` is for good. Saving a chat: absent keeps the stored
|
|
40
|
+
* end, and `muted: false` clears it.
|
|
41
|
+
*/
|
|
42
|
+
mutedUntil?: string | null;
|
|
38
43
|
archived?: boolean;
|
|
44
|
+
/** The owner marked the chat unread, whatever its count; absent where the messenger does not say. */
|
|
45
|
+
markedUnread?: boolean;
|
|
39
46
|
/** Unread messages that mention the owner or reply to them. */
|
|
40
47
|
unreadMentions?: number;
|
|
41
48
|
/** Absent where the messenger does not say. */
|
|
@@ -50,7 +57,8 @@ export interface Chat {
|
|
|
50
57
|
* A chat as an adapter saves it. A `title`, `unreadCount`, `lastMessageAt`, `participantsCount` or `membershipState`
|
|
51
58
|
* left out keeps the stored value; `null` stores none. So a push that knows only some of them, such as a notice that
|
|
52
59
|
* a group left its community, leaves the rest out. `membershipState: "member"` says the owner is in the chat again: it
|
|
53
|
-
* takes off a "left" mark and keeps any other state, such as "archived". It is never stored.
|
|
60
|
+
* takes off a "left" mark and keeps any other state, such as "archived". It is never stored. `muted`, `mutedUntil`,
|
|
61
|
+
* `archived` and `markedUnread` left out keep the stored value too.
|
|
54
62
|
*/
|
|
55
63
|
export type ChatUpdate = Omit<Chat, KeptFields | "membershipState"> & Partial<Pick<Chat, KeptFields>> & {
|
|
56
64
|
membershipState?: MembershipState | "member" | null;
|
|
@@ -263,6 +271,19 @@ export interface Reactions {
|
|
|
263
271
|
mine: string | null;
|
|
264
272
|
total: number;
|
|
265
273
|
}
|
|
274
|
+
/**
|
|
275
|
+
* One person's reaction to a message, for a messenger that sends a reaction change at a time (WhatsApp) instead of
|
|
276
|
+
* totals. `reaction` is `null` when they took it back. The store keeps each person's newest by `reactedAt` and derives
|
|
277
|
+
* the message's `Reactions` from them.
|
|
278
|
+
*/
|
|
279
|
+
export interface PersonReaction {
|
|
280
|
+
person: Member;
|
|
281
|
+
/** The owner's own reaction, which becomes `Reactions.mine`. */
|
|
282
|
+
own: boolean;
|
|
283
|
+
reaction: string | null;
|
|
284
|
+
/** ISO 8601 — when the person reacted, as the messenger says, not when it arrived. */
|
|
285
|
+
reactedAt: string;
|
|
286
|
+
}
|
|
266
287
|
/** The message a reply answers or a forward carries. */
|
|
267
288
|
export interface QuotedMessage {
|
|
268
289
|
id: Id;
|
|
@@ -319,7 +340,15 @@ export interface Message {
|
|
|
319
340
|
* keeps what the store holds: a fetch, an edit or another messenger's message says nothing about it.
|
|
320
341
|
*/
|
|
321
342
|
starred?: boolean;
|
|
343
|
+
/**
|
|
344
|
+
* How far the owner's own message got in a one-to-one chat, from the messenger's receipts: `read` once the other
|
|
345
|
+
* person opened it. Absent when no receipt came. On a save, absent keeps what the store holds, and a state never
|
|
346
|
+
* moves back: a late `delivered` after `read` changes nothing.
|
|
347
|
+
*/
|
|
348
|
+
delivery?: Delivery;
|
|
322
349
|
}
|
|
350
|
+
/** `delivered` reached the other person's phone; `read` they opened it (a voice note or view-once file played counts). */
|
|
351
|
+
export type Delivery = "delivered" | "read";
|
|
323
352
|
/**
|
|
324
353
|
* A message found by searching, carrying the chat's name as well as its id: a search spans every
|
|
325
354
|
* chat, so an answer that named only the id would make the reader look each one up.
|
|
@@ -384,6 +413,14 @@ export interface PollVoteEvent {
|
|
|
384
413
|
messageId: Id;
|
|
385
414
|
vote: PollVote;
|
|
386
415
|
}
|
|
416
|
+
/** One person reacted to `messageId`, changed their reaction, or took it back; saved, an older one never wins. */
|
|
417
|
+
export interface PersonReactionEvent {
|
|
418
|
+
event: "person_reaction";
|
|
419
|
+
chatId: Id;
|
|
420
|
+
chatTitle: string | null;
|
|
421
|
+
messageId: Id;
|
|
422
|
+
reaction: PersonReaction;
|
|
423
|
+
}
|
|
387
424
|
/** The owner starred a message or took the star off, here or on another device; saved, the same twice is one. */
|
|
388
425
|
export interface MessageStarEvent {
|
|
389
426
|
event: "star";
|
|
@@ -392,6 +429,16 @@ export interface MessageStarEvent {
|
|
|
392
429
|
messageId: Id;
|
|
393
430
|
starred: boolean;
|
|
394
431
|
}
|
|
432
|
+
/** A receipt for the owner's own message in a one-to-one chat; saved, it never moves the stored state back. */
|
|
433
|
+
export interface MessageDeliveryEvent {
|
|
434
|
+
event: "delivery";
|
|
435
|
+
chatId: Id;
|
|
436
|
+
chatTitle: string | null;
|
|
437
|
+
messageId: Id;
|
|
438
|
+
delivery: Delivery;
|
|
439
|
+
/** ISO 8601 — when the receipt says it happened. */
|
|
440
|
+
at: string;
|
|
441
|
+
}
|
|
395
442
|
/** Who joined, left, was added, removed, promoted or demoted, or a new title, as it happens; saved for `chats events`. */
|
|
396
443
|
export interface ChatEventNotice {
|
|
397
444
|
event: "chat_event";
|
|
@@ -399,13 +446,14 @@ export interface ChatEventNotice {
|
|
|
399
446
|
chatTitle: string | null;
|
|
400
447
|
change: ChatEvent;
|
|
401
448
|
}
|
|
402
|
-
/** What a listening connection reports: a
|
|
449
|
+
/** What a listening connection reports: a message, a change to one, a vote, a reaction, a star, a receipt, a chat change. */
|
|
403
450
|
export type MessageEvent = {
|
|
404
451
|
event: "message";
|
|
405
452
|
message: MessageHit;
|
|
406
|
-
} | MessageChange | PollVoteEvent | MessageStarEvent | ChatEventNotice;
|
|
453
|
+
} | MessageChange | PollVoteEvent | PersonReactionEvent | MessageStarEvent | MessageDeliveryEvent | ChatEventNotice;
|
|
407
454
|
/** One chat's share of `inbox`: other people's messages since the last check, oldest first. */
|
|
408
455
|
export interface InboxChat extends Pick<Chat, "id" | "title" | "kind" | "unreadCount"> {
|
|
456
|
+
/** A chat marked unread with nothing counted: its newest message from someone else. */
|
|
409
457
|
messages: Message[];
|
|
410
458
|
/** There are more than `--limit`; these are the newest of them. */
|
|
411
459
|
more: boolean;
|
package/dist/entities/chat.d.ts
CHANGED
|
@@ -11,7 +11,11 @@ export declare const chat: v.StrictObjectSchema<{
|
|
|
11
11
|
readonly last_message_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
|
|
12
12
|
readonly participants_count: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
|
|
13
13
|
readonly muted: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
14
|
+
/** When the mute ends; absent with `muted` true is for good. */
|
|
15
|
+
readonly muted_until: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
|
|
14
16
|
readonly archived: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
17
|
+
/** The owner marked it unread, whatever `unread_count` says. */
|
|
18
|
+
readonly marked_unread: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
15
19
|
readonly membership_state: v.OptionalSchema<v.PicklistSchema<["joined", "left", "public", "imported", "archived", "external"], undefined>, undefined>;
|
|
16
20
|
readonly parent_chat_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
|
|
17
21
|
readonly scope: v.OptionalSchema<v.PicklistSchema<["personal", "work"], undefined>, undefined>;
|
package/dist/entities/chat.js
CHANGED
|
@@ -14,7 +14,11 @@ export const chat = v.strictObject({
|
|
|
14
14
|
last_message_at: v.nullable(time),
|
|
15
15
|
participants_count: v.nullable(count),
|
|
16
16
|
muted: v.optional(v.boolean()),
|
|
17
|
+
/** When the mute ends; absent with `muted` true is for good. */
|
|
18
|
+
muted_until: v.optional(time),
|
|
17
19
|
archived: v.optional(v.boolean()),
|
|
20
|
+
/** The owner marked it unread, whatever `unread_count` says. */
|
|
21
|
+
marked_unread: v.optional(v.boolean()),
|
|
18
22
|
membership_state: v.optional(v.picklist(["joined", "left", "public", "imported", "archived", "external"])),
|
|
19
23
|
parent_chat_id: v.optional(id),
|
|
20
24
|
scope: v.optional(v.picklist(["personal", "work"])),
|
|
@@ -24,7 +24,9 @@ export declare const contact: v.StrictObjectSchema<{
|
|
|
24
24
|
readonly last_message_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
|
|
25
25
|
readonly participants_count: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
|
|
26
26
|
readonly muted: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
27
|
+
readonly muted_until: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
|
|
27
28
|
readonly archived: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
29
|
+
readonly marked_unread: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
28
30
|
readonly membership_state: v.OptionalSchema<v.PicklistSchema<["joined", "left", "public", "imported", "archived", "external"], undefined>, undefined>;
|
|
29
31
|
readonly parent_chat_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
|
|
30
32
|
readonly scope: v.OptionalSchema<v.PicklistSchema<["personal", "work"], undefined>, undefined>;
|
|
@@ -72,7 +74,9 @@ export declare const contact: v.StrictObjectSchema<{
|
|
|
72
74
|
readonly last_message_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
|
|
73
75
|
readonly participants_count: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>, undefined>;
|
|
74
76
|
readonly muted: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
77
|
+
readonly muted_until: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
|
|
75
78
|
readonly archived: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
79
|
+
readonly marked_unread: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
76
80
|
readonly membership_state: v.OptionalSchema<v.PicklistSchema<["joined", "left", "public", "imported", "archived", "external"], undefined>, undefined>;
|
|
77
81
|
readonly parent_chat_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>, undefined>;
|
|
78
82
|
readonly scope: v.OptionalSchema<v.PicklistSchema<["personal", "work"], undefined>, undefined>;
|
|
@@ -142,6 +142,7 @@ export declare const contribution: v.StrictObjectSchema<{
|
|
|
142
142
|
}, undefined>, undefined>, undefined>;
|
|
143
143
|
readonly scheduled_for: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
|
|
144
144
|
readonly starred: v.OptionalSchema<v.LiteralSchema<true, undefined>, undefined>;
|
|
145
|
+
readonly delivery: v.OptionalSchema<v.PicklistSchema<["delivered", "read"], undefined>, undefined>;
|
|
145
146
|
readonly email: v.OptionalSchema<v.StrictObjectSchema<{
|
|
146
147
|
readonly subject: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
147
148
|
readonly from: v.NullableSchema<v.StrictObjectSchema<{
|
|
@@ -322,6 +323,7 @@ export declare const contribution: v.StrictObjectSchema<{
|
|
|
322
323
|
}, undefined>, undefined>, undefined>;
|
|
323
324
|
readonly scheduled_for: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
|
|
324
325
|
readonly starred: v.OptionalSchema<v.LiteralSchema<true, undefined>, undefined>;
|
|
326
|
+
readonly delivery: v.OptionalSchema<v.PicklistSchema<["delivered", "read"], undefined>, undefined>;
|
|
325
327
|
readonly email: v.OptionalSchema<v.StrictObjectSchema<{
|
|
326
328
|
readonly subject: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
327
329
|
readonly from: v.NullableSchema<v.StrictObjectSchema<{
|
|
@@ -540,6 +542,7 @@ export declare const contribution: v.StrictObjectSchema<{
|
|
|
540
542
|
}, undefined>, undefined>, undefined>;
|
|
541
543
|
readonly scheduled_for: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
|
|
542
544
|
readonly starred: v.OptionalSchema<v.LiteralSchema<true, undefined>, undefined>;
|
|
545
|
+
readonly delivery: v.OptionalSchema<v.PicklistSchema<["delivered", "read"], undefined>, undefined>;
|
|
543
546
|
readonly email: v.OptionalSchema<v.StrictObjectSchema<{
|
|
544
547
|
readonly subject: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
545
548
|
readonly from: v.NullableSchema<v.StrictObjectSchema<{
|
|
@@ -720,6 +723,7 @@ export declare const contribution: v.StrictObjectSchema<{
|
|
|
720
723
|
}, undefined>, undefined>, undefined>;
|
|
721
724
|
readonly scheduled_for: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
|
|
722
725
|
readonly starred: v.OptionalSchema<v.LiteralSchema<true, undefined>, undefined>;
|
|
726
|
+
readonly delivery: v.OptionalSchema<v.PicklistSchema<["delivered", "read"], undefined>, undefined>;
|
|
723
727
|
readonly email: v.OptionalSchema<v.StrictObjectSchema<{
|
|
724
728
|
readonly subject: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
725
729
|
readonly from: v.NullableSchema<v.StrictObjectSchema<{
|
|
@@ -974,6 +978,7 @@ export declare const evidence: v.UnionSchema<[v.StrictObjectSchema<{
|
|
|
974
978
|
}, undefined>, undefined>, undefined>;
|
|
975
979
|
readonly scheduled_for: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
|
|
976
980
|
readonly starred: v.OptionalSchema<v.LiteralSchema<true, undefined>, undefined>;
|
|
981
|
+
readonly delivery: v.OptionalSchema<v.PicklistSchema<["delivered", "read"], undefined>, undefined>;
|
|
977
982
|
readonly email: v.OptionalSchema<v.StrictObjectSchema<{
|
|
978
983
|
readonly subject: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
979
984
|
readonly from: v.NullableSchema<v.StrictObjectSchema<{
|
|
@@ -1154,6 +1159,7 @@ export declare const evidence: v.UnionSchema<[v.StrictObjectSchema<{
|
|
|
1154
1159
|
}, undefined>, undefined>, undefined>;
|
|
1155
1160
|
readonly scheduled_for: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
|
|
1156
1161
|
readonly starred: v.OptionalSchema<v.LiteralSchema<true, undefined>, undefined>;
|
|
1162
|
+
readonly delivery: v.OptionalSchema<v.PicklistSchema<["delivered", "read"], undefined>, undefined>;
|
|
1157
1163
|
readonly email: v.OptionalSchema<v.StrictObjectSchema<{
|
|
1158
1164
|
readonly subject: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
1159
1165
|
readonly from: v.NullableSchema<v.StrictObjectSchema<{
|
|
@@ -1372,6 +1378,7 @@ export declare const evidence: v.UnionSchema<[v.StrictObjectSchema<{
|
|
|
1372
1378
|
}, undefined>, undefined>, undefined>;
|
|
1373
1379
|
readonly scheduled_for: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
|
|
1374
1380
|
readonly starred: v.OptionalSchema<v.LiteralSchema<true, undefined>, undefined>;
|
|
1381
|
+
readonly delivery: v.OptionalSchema<v.PicklistSchema<["delivered", "read"], undefined>, undefined>;
|
|
1375
1382
|
readonly email: v.OptionalSchema<v.StrictObjectSchema<{
|
|
1376
1383
|
readonly subject: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
1377
1384
|
readonly from: v.NullableSchema<v.StrictObjectSchema<{
|
|
@@ -1552,6 +1559,7 @@ export declare const evidence: v.UnionSchema<[v.StrictObjectSchema<{
|
|
|
1552
1559
|
}, undefined>, undefined>, undefined>;
|
|
1553
1560
|
readonly scheduled_for: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
|
|
1554
1561
|
readonly starred: v.OptionalSchema<v.LiteralSchema<true, undefined>, undefined>;
|
|
1562
|
+
readonly delivery: v.OptionalSchema<v.PicklistSchema<["delivered", "read"], undefined>, undefined>;
|
|
1555
1563
|
readonly email: v.OptionalSchema<v.StrictObjectSchema<{
|
|
1556
1564
|
readonly subject: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
1557
1565
|
readonly from: v.NullableSchema<v.StrictObjectSchema<{
|