@omelhorsite/sdk 0.2.0 → 0.4.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/README.md +112 -130
- package/dist/index.js +4800 -610
- package/dist/types/client.d.ts +60 -3
- package/dist/types/http.d.ts +444 -19
- package/dist/types/index.d.ts +5 -1
- package/dist/types/internal/attachments.d.ts +17 -0
- package/dist/types/internal/helpers.d.ts +9 -0
- package/dist/types/listing.d.ts +90 -0
- package/dist/types/resources/account.d.ts +71 -5
- package/dist/types/resources/admin/authorizedApplications.d.ts +133 -0
- package/dist/types/resources/admin/chests.d.ts +51 -0
- package/dist/types/resources/admin/eventAlerts.d.ts +60 -0
- package/dist/types/resources/admin/identities.d.ts +99 -0
- package/dist/types/resources/admin/index.d.ts +77 -0
- package/dist/types/resources/admin/jobs.d.ts +97 -0
- package/dist/types/resources/admin/myOauthApplications.d.ts +282 -0
- package/dist/types/resources/admin/notepads.d.ts +49 -0
- package/dist/types/resources/admin/oauthApplications.d.ts +309 -0
- package/dist/types/resources/admin/quotas.d.ts +114 -0
- package/dist/types/resources/admin/shortLinks.d.ts +201 -0
- package/dist/types/resources/admin/types.d.ts +222 -0
- package/dist/types/resources/admin/vocalSeparations.d.ts +98 -0
- package/dist/types/resources/admin.d.ts +1841 -0
- package/dist/types/resources/auth/index.d.ts +39 -0
- package/dist/types/resources/auth/passkeys.d.ts +652 -0
- package/dist/types/resources/auth/sessions.d.ts +844 -0
- package/dist/types/resources/chests.d.ts +54 -3
- package/dist/types/resources/content/analysis.d.ts +62 -0
- package/dist/types/resources/content/blogs.d.ts +471 -0
- package/dist/types/resources/content/feedbacks.d.ts +263 -0
- package/dist/types/resources/content/index.d.ts +52 -0
- package/dist/types/resources/content/intel/articles.d.ts +230 -0
- package/dist/types/resources/content/intel/config.d.ts +135 -0
- package/dist/types/resources/content/intel/index.d.ts +53 -0
- package/dist/types/resources/content/intel/items.d.ts +91 -0
- package/dist/types/resources/content/intel/reports.d.ts +108 -0
- package/dist/types/resources/content/intel/scripts.d.ts +152 -0
- package/dist/types/resources/content/intel/sources.d.ts +236 -0
- package/dist/types/resources/content/intel/stats.d.ts +105 -0
- package/dist/types/resources/content/intel/types.d.ts +86 -0
- package/dist/types/resources/content/jokes.d.ts +93 -0
- package/dist/types/resources/content/notifications.d.ts +147 -0
- package/dist/types/resources/content/serviceUsages.d.ts +73 -0
- package/dist/types/resources/content/servicesStatus.d.ts +194 -0
- package/dist/types/resources/content/siteConfig.d.ts +43 -0
- package/dist/types/resources/content/spaceInvaders.d.ts +154 -0
- package/dist/types/resources/content.d.ts +2775 -0
- package/dist/types/resources/dynamicQrs.d.ts +39 -3
- package/dist/types/resources/forms.d.ts +176 -35
- package/dist/types/resources/index.d.ts +19 -8
- package/dist/types/resources/ipLookup.d.ts +20 -4
- package/dist/types/resources/jobs.d.ts +69 -25
- package/dist/types/resources/library/annotations.d.ts +162 -0
- package/dist/types/resources/library/books.d.ts +534 -0
- package/dist/types/resources/library/chat.d.ts +259 -0
- package/dist/types/resources/library/index.d.ts +39 -0
- package/dist/types/resources/library/shelves.d.ts +237 -0
- package/dist/types/resources/library/types.d.ts +120 -0
- package/dist/types/resources/library.d.ts +1433 -0
- package/dist/types/resources/linkTrees.d.ts +142 -30
- package/dist/types/resources/media.d.ts +351 -0
- package/dist/types/resources/movies/addons.d.ts +388 -0
- package/dist/types/resources/movies/collections.d.ts +352 -0
- package/dist/types/resources/movies/index.d.ts +29 -0
- package/dist/types/resources/movies/types.d.ts +50 -0
- package/dist/types/resources/movies/watchProgress.d.ts +277 -0
- package/dist/types/resources/movies.d.ts +1160 -0
- package/dist/types/resources/music/artists.d.ts +1068 -0
- package/dist/types/resources/music/imports.d.ts +941 -0
- package/dist/types/resources/music/index.d.ts +61 -0
- package/dist/types/resources/music/playlists.d.ts +1027 -0
- package/dist/types/resources/music/social.d.ts +1132 -0
- package/dist/types/resources/music/songs.d.ts +1167 -0
- package/dist/types/resources/notepads.d.ts +4 -1
- package/dist/types/resources/quotas.d.ts +7 -1
- package/dist/types/resources/realtime.d.ts +855 -0
- package/dist/types/resources/shortLinks.d.ts +49 -5
- package/dist/types/resources/social/groupChats.d.ts +458 -0
- package/dist/types/resources/social/index.d.ts +19 -0
- package/dist/types/resources/social/messages.d.ts +424 -0
- package/dist/types/resources/social/relationships.d.ts +322 -0
- package/dist/types/resources/social/types.d.ts +37 -0
- package/dist/types/resources/social.d.ts +1348 -0
- package/dist/types/resources/storage/upload.d.ts +158 -11
- package/dist/types/resources/storage.d.ts +111 -27
- package/dist/types/resources/tickets.d.ts +101 -13
- package/dist/types/resources/tools/backgroundRemoval.d.ts +18 -3
- package/dist/types/resources/tools/captions.d.ts +448 -21
- package/dist/types/resources/tools/downloader.d.ts +21 -0
- package/dist/types/resources/tools/index.d.ts +57 -15
- package/dist/types/resources/tools/jumpstyle.d.ts +50 -17
- package/dist/types/resources/tools/transcription.d.ts +35 -13
- package/dist/types/resources/tools/upscale.d.ts +23 -3
- package/dist/types/resources/tools/vocalSeparation.d.ts +30 -13
- package/dist/types/types.d.ts +249 -17
- package/package.json +2 -1
|
@@ -9,9 +9,17 @@
|
|
|
9
9
|
* Creating a link works anonymously; listing, editing and statistics need a
|
|
10
10
|
* credential. Creation is the most tightly throttled write in the whole API -
|
|
11
11
|
* see {@link ShortLinksNamespace.create} before you spend one.
|
|
12
|
+
*
|
|
13
|
+
* There is deliberately no `get(id)` here, and its absence is the API's, not
|
|
14
|
+
* an omission: the route file declares `resources :short_links, only: [:create,
|
|
15
|
+
* :index, :update, :destroy]`, so `GET /short_links/:id` is not routed at all
|
|
16
|
+
* and answers 404 for every id, including your own links. To read one link,
|
|
17
|
+
* find it in {@link ShortLinksNamespace.list} - or by endpoint with
|
|
18
|
+
* {@link ShortLinksNamespace.resolve}, which explains what that costs.
|
|
12
19
|
*/
|
|
13
20
|
import { Resource } from "../http";
|
|
14
|
-
import
|
|
21
|
+
import type { ListParams } from "../listing";
|
|
22
|
+
import { type BaseRecord, type Id, type Json, type Paginated, type RequestOptions, type Timestamp } from "../types";
|
|
15
23
|
/** Public host that fronts `short_links#follow`. See {@link ShortLinksNamespace.shortUrl}. */
|
|
16
24
|
export declare const SHORT_LINK_BASE_URL = "https://omelhor.site";
|
|
17
25
|
/**
|
|
@@ -33,11 +41,39 @@ export interface ShortLinkClick {
|
|
|
33
41
|
/** Browser or app name parsed from the user agent, or `null`. */
|
|
34
42
|
readonly device_name: string | null;
|
|
35
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* The owner of a link, rendered inline by `UserBlueprint`'s default view.
|
|
46
|
+
*
|
|
47
|
+
* Only the keys that view declares unconditionally are named. `UserBlueprint`
|
|
48
|
+
* also renders `group`, `email`, `gender`, `last_seen_at`, `sessions_count`,
|
|
49
|
+
* `deactivated_at`, `allowed_to_use_spotify` and `share_listening` behind `if:`
|
|
50
|
+
* predicates that test who is ASKING, so whether they appear depends on the
|
|
51
|
+
* caller's own privileges rather than on the record. That is why they are
|
|
52
|
+
* reached through the index signature instead of being declared here as
|
|
53
|
+
* optionals: an optional would suggest the server decides, and it does not.
|
|
54
|
+
*/
|
|
55
|
+
export interface ShortLinkOwner {
|
|
56
|
+
readonly id: Id;
|
|
57
|
+
readonly handle: string;
|
|
58
|
+
readonly name: string;
|
|
59
|
+
readonly bio: string | null;
|
|
60
|
+
readonly country_code: string;
|
|
61
|
+
readonly created_at: Timestamp;
|
|
62
|
+
readonly updated_at: Timestamp;
|
|
63
|
+
readonly [key: string]: Json | undefined;
|
|
64
|
+
}
|
|
36
65
|
/**
|
|
37
66
|
* A short link.
|
|
38
67
|
*
|
|
39
68
|
* `Omit<BaseRecord, "id">` rather than a plain `extends BaseRecord`: see
|
|
40
69
|
* {@link ShortLinkId} for why the identifier is a number on this one table.
|
|
70
|
+
*
|
|
71
|
+
* Every key below is present on every response this namespace can produce.
|
|
72
|
+
* `ShortLinkBlueprint` does declare a second, narrower `:admin` view - it drops
|
|
73
|
+
* `updated_at`, both associations, and adds `owner`, `click_count` and
|
|
74
|
+
* `last_click_at` - but that view is only ever rendered by the admin
|
|
75
|
+
* shortlinks tool under `/admin/short_links`, which is not this resource. A
|
|
76
|
+
* record that arrived here has the full default shape.
|
|
41
77
|
*/
|
|
42
78
|
export interface ShortLink extends Omit<BaseRecord, "id"> {
|
|
43
79
|
/** Integer primary key. See {@link ShortLinkId}. */
|
|
@@ -52,6 +88,9 @@ export interface ShortLink extends Omit<BaseRecord, "id"> {
|
|
|
52
88
|
* shares), `"qr"` (dynamic QR), `"f"` (forms) and `"t"` (link trees). That
|
|
53
89
|
* is why {@link ShortLink} and `DynamicQr` are separate resources even
|
|
54
90
|
* though both are rows in the same table.
|
|
91
|
+
*
|
|
92
|
+
* A link that reached you through {@link ShortLinksNamespace.list} always
|
|
93
|
+
* holds `null` or `""`, because the listing scope is `user_managed`.
|
|
55
94
|
*/
|
|
56
95
|
readonly namespace: string | null;
|
|
57
96
|
/** Owner, or `null` for a link created anonymously. */
|
|
@@ -61,10 +100,13 @@ export interface ShortLink extends Omit<BaseRecord, "id"> {
|
|
|
61
100
|
* page. A link with 50 000 visits sends 50 000 objects here. Use
|
|
62
101
|
* {@link ShortLinksNamespace.stats} for anything analytical and treat this
|
|
63
102
|
* field as a payload hazard, not as a feature.
|
|
103
|
+
*
|
|
104
|
+
* Always present, and `[]` rather than `null` for a link nobody has clicked:
|
|
105
|
+
* a Blueprinter association over an empty `has_many` renders an empty array.
|
|
64
106
|
*/
|
|
65
|
-
readonly short_link_clicks
|
|
66
|
-
/** The owner rendered inline
|
|
67
|
-
readonly user
|
|
107
|
+
readonly short_link_clicks: ShortLinkClick[];
|
|
108
|
+
/** The owner rendered inline, or `null` for a link created anonymously. */
|
|
109
|
+
readonly user: ShortLinkOwner | null;
|
|
68
110
|
}
|
|
69
111
|
/** One day of the click histogram. */
|
|
70
112
|
export interface ShortLinkDailyClicks {
|
|
@@ -128,8 +170,10 @@ export interface UpdateShortLinkInput {
|
|
|
128
170
|
readonly url?: string;
|
|
129
171
|
readonly endpoint?: string;
|
|
130
172
|
}
|
|
173
|
+
/** Filter columns of `GET /short_links`, on top of {@link BASE_FILTER_COLUMNS}. */
|
|
174
|
+
export declare const SHORT_LINK_FILTER_COLUMNS: readonly ["user_id"];
|
|
131
175
|
/** Filters for {@link ShortLinksNamespace.list}. */
|
|
132
|
-
export interface ListShortLinksParams extends
|
|
176
|
+
export interface ListShortLinksParams extends ListParams<(typeof SHORT_LINK_FILTER_COLUMNS)[number]> {
|
|
133
177
|
/**
|
|
134
178
|
* Narrow to one owner, sent as `exact_search[user_id]`.
|
|
135
179
|
*
|
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
/** Group chats: the chat, its roster and its messages, as `oms.social.groupChats`. */
|
|
2
|
+
import { Resource } from "../../http";
|
|
3
|
+
import type { BaseRecord, FileInput, Id, NativeFile, RequestOptions, Timestamp } from "../../types";
|
|
4
|
+
import type { AttachmentKind } from "./types";
|
|
5
|
+
/**
|
|
6
|
+
* Primary key of a group chat. A STRING - `group_chats` is an `id: :string`
|
|
7
|
+
* table, unlike `messages` and `relationships`.
|
|
8
|
+
*/
|
|
9
|
+
export type GroupChatId = string;
|
|
10
|
+
/** Primary key of a membership row. A string. */
|
|
11
|
+
export type GroupChatMemberId = string;
|
|
12
|
+
/** Primary key of a group chat message. A string. */
|
|
13
|
+
export type GroupChatMessageId = string;
|
|
14
|
+
/** `GroupChatMessage` allows four thousand, not one thousand. */
|
|
15
|
+
export declare const GROUP_CHAT_MESSAGE_CONTENT_MAX_LENGTH = 4000;
|
|
16
|
+
/** Length cap of a group chat's name. */
|
|
17
|
+
export declare const GROUP_CHAT_NAME_MAX_LENGTH = 120;
|
|
18
|
+
/**
|
|
19
|
+
* Rows `GET /group_chats/:id/messages` returns per call.
|
|
20
|
+
*
|
|
21
|
+
* A hard constant, not a modifier: this endpoint does not speak the list DSL
|
|
22
|
+
* and `modifiers[page]` on it is ignored.
|
|
23
|
+
*/
|
|
24
|
+
export declare const GROUP_CHAT_MESSAGE_PAGE_SIZE = 100;
|
|
25
|
+
/** Newest message in a chat, as the chat record summarises it. */
|
|
26
|
+
export interface GroupChatLastMessage {
|
|
27
|
+
readonly id: GroupChatMessageId;
|
|
28
|
+
readonly sender_id: Id | null;
|
|
29
|
+
readonly preview: string;
|
|
30
|
+
readonly attachment_kind: AttachmentKind | null;
|
|
31
|
+
readonly created_at: Timestamp;
|
|
32
|
+
}
|
|
33
|
+
/** One membership row, as the `:extended` chat view embeds it. */
|
|
34
|
+
export interface GroupChatMember {
|
|
35
|
+
readonly id: GroupChatMemberId;
|
|
36
|
+
readonly user_id: Id;
|
|
37
|
+
readonly user_handle: string | null;
|
|
38
|
+
readonly user_name: string | null;
|
|
39
|
+
readonly role: GroupChatRole;
|
|
40
|
+
readonly joined_at: Timestamp;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A group chat, as the index renders it.
|
|
44
|
+
*
|
|
45
|
+
* Extends {@link BaseRecord}, which the integer-keyed direct message and
|
|
46
|
+
* relationship records cannot: `group_chats` is an `id: :string` table, so its
|
|
47
|
+
* key is the same opaque string every other resource in the SDK uses.
|
|
48
|
+
*/
|
|
49
|
+
export interface GroupChat extends BaseRecord {
|
|
50
|
+
readonly id: GroupChatId;
|
|
51
|
+
readonly name: string | null;
|
|
52
|
+
readonly kind: "ad_hoc";
|
|
53
|
+
readonly system_managed: boolean;
|
|
54
|
+
readonly context_type: string | null;
|
|
55
|
+
readonly context_id: string | null;
|
|
56
|
+
readonly last_message: GroupChatLastMessage | null;
|
|
57
|
+
}
|
|
58
|
+
/** The `:extended` view: {@link GroupChat} plus the roster. */
|
|
59
|
+
export interface GroupChatDetail extends GroupChat {
|
|
60
|
+
readonly members: GroupChatMember[];
|
|
61
|
+
}
|
|
62
|
+
/** A message inside a group chat. */
|
|
63
|
+
export interface GroupChatMessage extends BaseRecord {
|
|
64
|
+
readonly id: GroupChatMessageId;
|
|
65
|
+
readonly group_chat_id: GroupChatId;
|
|
66
|
+
/** Null on a system message. */
|
|
67
|
+
readonly sender_id: Id | null;
|
|
68
|
+
readonly sender_handle: string | null;
|
|
69
|
+
readonly sender_name: string | null;
|
|
70
|
+
readonly content: string | null;
|
|
71
|
+
readonly attachment_kind: AttachmentKind | null;
|
|
72
|
+
readonly has_attachment: boolean;
|
|
73
|
+
readonly system_kind: string | null;
|
|
74
|
+
readonly system_payload: Record<string, unknown>;
|
|
75
|
+
readonly edited_at: Timestamp | null;
|
|
76
|
+
readonly attachment_filename?: string;
|
|
77
|
+
readonly attachment_byte_size?: number;
|
|
78
|
+
readonly attachment_content_type?: string;
|
|
79
|
+
}
|
|
80
|
+
/** Membership role. */
|
|
81
|
+
export type GroupChatRole = "member" | "admin";
|
|
82
|
+
/** Body of {@link GroupChatsNamespace.create}. */
|
|
83
|
+
export interface CreateGroupChatInput {
|
|
84
|
+
/**
|
|
85
|
+
* Required, up to {@link GROUP_CHAT_NAME_MAX_LENGTH}. Blank, whitespace-only
|
|
86
|
+
* and the null sentinel are all rejected with `400 "Name is required"`.
|
|
87
|
+
*/
|
|
88
|
+
readonly name: string;
|
|
89
|
+
/**
|
|
90
|
+
* Everyone else to put in the chat, by user id.
|
|
91
|
+
*
|
|
92
|
+
* De-duplicated, stripped of blanks, and the caller's own id is removed - the
|
|
93
|
+
* creator is added separately, as the chat's `admin`. Ids that do not name a
|
|
94
|
+
* real user are DROPPED IN SILENCE: the call still answers `201`, and the
|
|
95
|
+
* only way to know a member is missing is to count `members` on the answer.
|
|
96
|
+
*
|
|
97
|
+
* There is no friendship check and no invitation step. Anyone can be put into
|
|
98
|
+
* a chat by anyone, and finds out by seeing it in their listing.
|
|
99
|
+
*/
|
|
100
|
+
readonly memberIds?: readonly Id[];
|
|
101
|
+
}
|
|
102
|
+
/** Body of {@link GroupChatMessagesNamespace.send}. */
|
|
103
|
+
export interface SendGroupChatMessageInput {
|
|
104
|
+
/**
|
|
105
|
+
* Up to {@link GROUP_CHAT_MESSAGE_CONTENT_MAX_LENGTH} - four thousand
|
|
106
|
+
* characters here, against one thousand for a direct message.
|
|
107
|
+
*
|
|
108
|
+
* Optional when `attachment` is present, and genuinely optional: unlike
|
|
109
|
+
* {@link SendMessageInput.content}, nothing substitutes a placeholder, so an
|
|
110
|
+
* attachment-only message comes back with `content: null`.
|
|
111
|
+
*/
|
|
112
|
+
readonly content?: string;
|
|
113
|
+
/**
|
|
114
|
+
* One file, up to {@link MESSAGE_ATTACHMENT_MAX_BYTES}.
|
|
115
|
+
*
|
|
116
|
+
* Stored byte for byte. There is no webp recompression here and no
|
|
117
|
+
* pixel-bomb check either, which is the opposite of what
|
|
118
|
+
* {@link DirectMessagesNamespace.send} does with an image, so the 20 MiB
|
|
119
|
+
* image ceiling does NOT apply and `attachment_content_type` on the answer is
|
|
120
|
+
* whatever you uploaded.
|
|
121
|
+
*/
|
|
122
|
+
readonly attachment?: FileInput | NativeFile;
|
|
123
|
+
}
|
|
124
|
+
/** Cursor for {@link GroupChatMessagesNamespace.list}. */
|
|
125
|
+
export interface ListGroupChatMessagesParams {
|
|
126
|
+
/**
|
|
127
|
+
* Return messages created strictly AFTER this one. Sent as `after_id`.
|
|
128
|
+
*
|
|
129
|
+
* Read {@link GroupChatMessagesNamespace.list} before using it: this cursor
|
|
130
|
+
* fails open, and the failure looks like a working request.
|
|
131
|
+
*/
|
|
132
|
+
readonly afterId?: GroupChatMessageId;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Many-to-many chats, reachable as `oms.social.groupChats`.
|
|
136
|
+
*
|
|
137
|
+
* ## THERE IS NO REALTIME HERE AT ALL
|
|
138
|
+
*
|
|
139
|
+
* Direct messages at least push a `message_received` notification over the
|
|
140
|
+
* cable. Group chats push NOTHING: no channel streams them, no `Notification`
|
|
141
|
+
* row is written when a message lands, and the only thing a new group message
|
|
142
|
+
* triggers server-side is a Discord alert for the operators. A group chat UI
|
|
143
|
+
* has to poll {@link GroupChatMessagesNamespace.list} with an `after_id`
|
|
144
|
+
* cursor, and there is no endpoint that will tell it which chats changed
|
|
145
|
+
* without listing them.
|
|
146
|
+
*
|
|
147
|
+
* The cheapest honest loop is {@link GroupChatsNamespace.list} on a slow timer
|
|
148
|
+
* for the chat list (it carries `last_message` per chat, so one request covers
|
|
149
|
+
* every conversation) and
|
|
150
|
+
* {@link GroupChatMessagesNamespace.list} with `afterId` on a fast timer for
|
|
151
|
+
* the chat that is open. Both are on the general 600/min ceiling shared with
|
|
152
|
+
* the rest of the app.
|
|
153
|
+
*
|
|
154
|
+
* ## Every id in this family is a STRING
|
|
155
|
+
*
|
|
156
|
+
* Unlike {@link DirectMessage} and {@link Relationship}.
|
|
157
|
+
*
|
|
158
|
+
* ## Only one `kind` exists
|
|
159
|
+
*
|
|
160
|
+
* `kind` is always `"ad_hoc"`. `system_managed`, `context_type` and
|
|
161
|
+
* `context_id` are there for a future subsystem; nothing writes them today.
|
|
162
|
+
*
|
|
163
|
+
* ## Errors here have a different SHAPE from the rest of the API
|
|
164
|
+
*
|
|
165
|
+
* A `404` or a `401` from these routes carries the JSON body `null` rather
|
|
166
|
+
* than the bare error string the rest of the API sends. Branch on the status,
|
|
167
|
+
* not on the body.
|
|
168
|
+
*/
|
|
169
|
+
export declare class GroupChatsNamespace extends Resource {
|
|
170
|
+
/** Messages inside a chat. */
|
|
171
|
+
readonly messages: GroupChatMessagesNamespace;
|
|
172
|
+
constructor(http: ConstructorParameters<typeof Resource>[0]);
|
|
173
|
+
/**
|
|
174
|
+
* `GET /group_chats` - every chat the caller is a member of, most recently
|
|
175
|
+
* touched first.
|
|
176
|
+
*
|
|
177
|
+
* Returns a bare array and not a {@link Paginated}, because the endpoint
|
|
178
|
+
* genuinely has no paging: `modifiers[page]`, `search[...]` and the `ETag`
|
|
179
|
+
* are all absent and the whole list comes back on every call. That is fine
|
|
180
|
+
* while a user has tens of chats and is a cliff if one ever has thousands.
|
|
181
|
+
*
|
|
182
|
+
* `updated_at` is the sort key and it is touched by a new message, by a
|
|
183
|
+
* rename, and by nothing else - a deleted message does not move a chat back
|
|
184
|
+
* down the list.
|
|
185
|
+
*
|
|
186
|
+
* Each chat carries a `last_message` summary, computed for the whole page in
|
|
187
|
+
* one window-function query. That summary is what makes this endpoint usable
|
|
188
|
+
* as a poll for "did anything change anywhere": compare `last_message.id`
|
|
189
|
+
* per chat instead of listing every conversation.
|
|
190
|
+
*
|
|
191
|
+
* Members are NOT included. Use {@link get} for the roster.
|
|
192
|
+
*
|
|
193
|
+
* A site administrator sees every chat on the instance here, not just their
|
|
194
|
+
* own.
|
|
195
|
+
*/
|
|
196
|
+
list(options?: RequestOptions): Promise<GroupChat[]>;
|
|
197
|
+
/**
|
|
198
|
+
* `GET /group_chats/:id` - one chat with its member roster.
|
|
199
|
+
*
|
|
200
|
+
* The `:extended` view, which is everything {@link list} returns PLUS
|
|
201
|
+
* `members`. Each member row carries `user_handle` and `user_name`
|
|
202
|
+
* denormalised, so rendering a roster needs no further requests.
|
|
203
|
+
*
|
|
204
|
+
* Not a member? `404 "Resource not found"` - the id is not distinguishable
|
|
205
|
+
* from one that does not exist, which is the right answer.
|
|
206
|
+
*
|
|
207
|
+
* Note that this is one of the few places in this namespace whose 404 body
|
|
208
|
+
* is the usual string rather than `null`.
|
|
209
|
+
*/
|
|
210
|
+
get(id: GroupChatId, options?: RequestOptions): Promise<GroupChatDetail>;
|
|
211
|
+
/**
|
|
212
|
+
* `POST /group_chats` - creates a chat and its roster in one transaction.
|
|
213
|
+
* `201` with the `:extended` view.
|
|
214
|
+
*
|
|
215
|
+
* The caller becomes the chat's `admin`; everyone in
|
|
216
|
+
* {@link CreateGroupChatInput.memberIds} becomes a `member`. There is no way
|
|
217
|
+
* to create a chat you are not in, and no way to hand out a second admin
|
|
218
|
+
* afterwards - `role` is not writable through any route in this namespace, so
|
|
219
|
+
* the creator is the only administrator the chat will ever have. If they
|
|
220
|
+
* leave, the chat keeps working for everybody but can never be renamed and
|
|
221
|
+
* can never take another member.
|
|
222
|
+
*
|
|
223
|
+
* Not retried: a replay after a lost response creates a second chat.
|
|
224
|
+
*
|
|
225
|
+
* @throws {OmsError} `invalid_request` when the name is blank here.
|
|
226
|
+
* @throws {OmsApiError} `400 "Name is required"` when the server judges it
|
|
227
|
+
* blank.
|
|
228
|
+
*/
|
|
229
|
+
create(input: CreateGroupChatInput, options?: RequestOptions): Promise<GroupChatDetail>;
|
|
230
|
+
/**
|
|
231
|
+
* `PATCH /group_chats/:id` - renames the chat. `200` with the `:extended`
|
|
232
|
+
* view.
|
|
233
|
+
*
|
|
234
|
+
* The name is the ONLY writable field: `kind`, `system_managed` and the
|
|
235
|
+
* context pair are ignored if sent.
|
|
236
|
+
*
|
|
237
|
+
* Passing `null` clears the name, and so does passing `""` or any
|
|
238
|
+
* whitespace-only string - all three collapse to `null`, so there is no way
|
|
239
|
+
* to set a blank name and no error telling you it was dropped. A nameless
|
|
240
|
+
* chat is legal and every client has to fall back to listing the members.
|
|
241
|
+
*
|
|
242
|
+
* Restricted to the chat's admin (its creator) or a site administrator.
|
|
243
|
+
* Anyone else gets `401` with a `null` body.
|
|
244
|
+
*/
|
|
245
|
+
rename(id: GroupChatId, name: string | null, options?: RequestOptions): Promise<GroupChatDetail>;
|
|
246
|
+
/**
|
|
247
|
+
* `POST /group_chats/:id/members` - adds one user. `200` (NOT `201`) with the
|
|
248
|
+
* `:extended` view.
|
|
249
|
+
*
|
|
250
|
+
* Idempotent by design: a user who is already a member is not re-added and
|
|
251
|
+
* the current chat comes back unchanged, so this is safe to retry and safe to
|
|
252
|
+
* call from a UI that is not sure of its own state.
|
|
253
|
+
*
|
|
254
|
+
* Admin-only, and the new member joins as a plain `member` - there is no way
|
|
255
|
+
* to promote anyone.
|
|
256
|
+
*
|
|
257
|
+
* A `user_id` that names nobody is `400 "user_id is required"`, which is the
|
|
258
|
+
* same message an absent `user_id` gets and is therefore not a useful
|
|
259
|
+
* diagnostic.
|
|
260
|
+
*/
|
|
261
|
+
addMember(id: GroupChatId, userId: Id, options?: RequestOptions): Promise<GroupChatDetail>;
|
|
262
|
+
/**
|
|
263
|
+
* `DELETE /group_chats/:id/members/:user_id` - `204`, empty body.
|
|
264
|
+
*
|
|
265
|
+
* Two callers are allowed and they mean different things: the chat's admin
|
|
266
|
+
* removing somebody, and any member removing THEMSELVES, which is how you
|
|
267
|
+
* leave. {@link leave} is the same call under a name that says so.
|
|
268
|
+
*
|
|
269
|
+
* ## Removing the last member DESTROYS THE CHAT
|
|
270
|
+
*
|
|
271
|
+
* A chat whose roster is empty after the removal is destroyed on the spot,
|
|
272
|
+
* messages included. So the last person to leave takes the entire history
|
|
273
|
+
* with them, for everyone, with no confirmation and no way back. There is no
|
|
274
|
+
* `DELETE /group_chats/:id` - emptying the roster is the only way a chat is
|
|
275
|
+
* ever deleted, and it is easy to trigger by accident on a two-person chat.
|
|
276
|
+
*
|
|
277
|
+
* ## An admin can strand a chat
|
|
278
|
+
*
|
|
279
|
+
* The admin leaving is permitted and promotes nobody. The chat survives with
|
|
280
|
+
* members and no administrator: nobody can rename it and nobody can add
|
|
281
|
+
* anyone ever again. Warn before letting the creator leave a chat that still
|
|
282
|
+
* has people in it.
|
|
283
|
+
*
|
|
284
|
+
* Removing someone who is not a member is a `204` with no effect, not a 404.
|
|
285
|
+
*/
|
|
286
|
+
removeMember(id: GroupChatId, userId: Id, options?: RequestOptions): Promise<void>;
|
|
287
|
+
/**
|
|
288
|
+
* Leaves a chat: {@link removeMember} with the caller's own id.
|
|
289
|
+
*
|
|
290
|
+
* `selfId` is passed rather than looked up, for the same reason
|
|
291
|
+
* {@link RelationshipsNamespace.friends} takes one - the SDK will not spend a
|
|
292
|
+
* session round trip on every call to learn who it is.
|
|
293
|
+
*
|
|
294
|
+
* If you are the last member this DESTROYS the chat and every message in it.
|
|
295
|
+
* If you are the admin it leaves the chat permanently unadministered. Both
|
|
296
|
+
* are described on {@link removeMember} and both are worth a confirmation
|
|
297
|
+
* dialog.
|
|
298
|
+
*/
|
|
299
|
+
leave(id: GroupChatId, selfId: Id, options?: RequestOptions): Promise<void>;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Messages inside a group chat, reachable as
|
|
303
|
+
* `oms.social.groupChats.messages`.
|
|
304
|
+
*
|
|
305
|
+
* Every route is nested under the chat, and every one of them resolves the
|
|
306
|
+
* chat first: a caller who is not a member gets `404` on the CHAT before the
|
|
307
|
+
* message id is even looked at, so there is no way to probe for message ids.
|
|
308
|
+
*/
|
|
309
|
+
export declare class GroupChatMessagesNamespace extends Resource {
|
|
310
|
+
/**
|
|
311
|
+
* `GET /group_chats/:id/messages` - up to
|
|
312
|
+
* {@link GROUP_CHAT_MESSAGE_PAGE_SIZE} messages, OLDEST FIRST.
|
|
313
|
+
*
|
|
314
|
+
* This endpoint does not speak the list DSL. No `search`, no `exact_search`,
|
|
315
|
+
* no `modifiers`, no `ETag`; the page size is a constant and
|
|
316
|
+
* `modifiers[page]` is ignored rather than rejected. The only knob is
|
|
317
|
+
* `after_id`, and it has two sharp edges.
|
|
318
|
+
*
|
|
319
|
+
* ## `afterId` FAILS OPEN
|
|
320
|
+
*
|
|
321
|
+
* The server looks the anchor up in the chat and applies the filter only
|
|
322
|
+
* when it finds one. An id it cannot find - a message that was deleted, an
|
|
323
|
+
* id from a different chat, a typo - does not produce an error. The cursor
|
|
324
|
+
* is silently DROPPED and you get the first 100 messages of the chat from
|
|
325
|
+
* the very beginning.
|
|
326
|
+
*
|
|
327
|
+
* A client that pages by remembering the last id it saw, and whose last id
|
|
328
|
+
* gets deleted, therefore restarts at the top and appends the same 100
|
|
329
|
+
* messages forever. Guard it: if the first row you get back is one you have
|
|
330
|
+
* already seen, your cursor is gone, not your data.
|
|
331
|
+
*
|
|
332
|
+
* ## `afterId` SKIPS TIES
|
|
333
|
+
*
|
|
334
|
+
* The filter is `created_at > anchor.created_at`, on the timestamp alone
|
|
335
|
+
* rather than on `(created_at, id)`. Two messages written in the same
|
|
336
|
+
* microsecond - which is how a burst of system messages arrives - and
|
|
337
|
+
* anchoring on the first one drops the second permanently from a forward
|
|
338
|
+
* walk.
|
|
339
|
+
*
|
|
340
|
+
* ## THERE IS NO BACKWARD CURSOR
|
|
341
|
+
*
|
|
342
|
+
* `before_id` does not exist. The only entry point into a chat's history is
|
|
343
|
+
* its beginning, and the only direction is forward. Opening a 5000-message
|
|
344
|
+
* chat at the newest message costs 50 sequential requests, and there is no
|
|
345
|
+
* way to fetch the tail directly. For the common "what is new" case, keep the
|
|
346
|
+
* newest id you have seen and poll with it; for a first open, either walk
|
|
347
|
+
* with {@link all} or accept that you are showing the top of the chat.
|
|
348
|
+
*
|
|
349
|
+
* System messages (`system_kind` set, `sender_id` null) are in the same
|
|
350
|
+
* stream and are meant to render as centred pills rather than as messages.
|
|
351
|
+
* {@link isSystemMessage} tests for them.
|
|
352
|
+
*/
|
|
353
|
+
list(chatId: GroupChatId, params?: ListGroupChatMessagesParams, options?: RequestOptions): Promise<GroupChatMessage[]>;
|
|
354
|
+
/**
|
|
355
|
+
* Walks a chat's history forward from the beginning and returns it in one
|
|
356
|
+
* array, oldest first.
|
|
357
|
+
*
|
|
358
|
+
* One request per {@link GROUP_CHAT_MESSAGE_PAGE_SIZE} messages, which is the
|
|
359
|
+
* only shape the endpoint allows. `limit` caps the walk at 1000 messages (ten
|
|
360
|
+
* requests) by default so a long chat cannot quietly spend a large share of
|
|
361
|
+
* the 600/min ceiling; raise it deliberately.
|
|
362
|
+
*
|
|
363
|
+
* Stops early on a short page, and also stops if the server hands back a page
|
|
364
|
+
* whose first row it has already seen - that is the fail-open cursor
|
|
365
|
+
* described on {@link list}, and continuing would loop forever.
|
|
366
|
+
*/
|
|
367
|
+
all(chatId: GroupChatId, limit?: number, options?: RequestOptions): Promise<GroupChatMessage[]>;
|
|
368
|
+
/**
|
|
369
|
+
* `POST /group_chats/:id/messages` - sends one message. `201` with the
|
|
370
|
+
* record.
|
|
371
|
+
*
|
|
372
|
+
* Content, an attachment, or both; a message with neither is `400 "Message
|
|
373
|
+
* must have content or an attachment"`. The sender is always the
|
|
374
|
+
* authenticated user, and non-members never get this far - the chat lookup
|
|
375
|
+
* answers `404` first.
|
|
376
|
+
*
|
|
377
|
+
* Sending TOUCHES the chat, which is what moves it to the top of
|
|
378
|
+
* {@link GroupChatsNamespace.list}. Nothing else in this namespace does, so a
|
|
379
|
+
* chat whose only recent activity was a rename or a deletion sorts by its own
|
|
380
|
+
* `updated_at` rather than by its newest message.
|
|
381
|
+
*
|
|
382
|
+
* Sent as JSON with no attachment and as `multipart/form-data` with one.
|
|
383
|
+
*
|
|
384
|
+
* Nobody is notified. See the {@link GroupChatsNamespace} docs: there is no
|
|
385
|
+
* cable channel, no notification row, and no push for group chat messages, so
|
|
386
|
+
* the only way anyone learns about this is by polling.
|
|
387
|
+
*
|
|
388
|
+
* Not retried: a replay after a lost response posts the message twice.
|
|
389
|
+
*
|
|
390
|
+
* @throws {OmsError} `invalid_request` when neither content nor attachment is
|
|
391
|
+
* given, or content is over the cap.
|
|
392
|
+
*/
|
|
393
|
+
send(chatId: GroupChatId, input: SendGroupChatMessageInput, options?: RequestOptions): Promise<GroupChatMessage>;
|
|
394
|
+
/**
|
|
395
|
+
* `PATCH /group_chats/:id/messages/:id` - rewrites the content. `200`.
|
|
396
|
+
*
|
|
397
|
+
* Content only, and it must be non-blank: an empty edit is `400 "Content
|
|
398
|
+
* required"` rather than a way to clear the text. An attachment cannot be
|
|
399
|
+
* changed or removed.
|
|
400
|
+
*
|
|
401
|
+
* Allowed for the sender within {@link MESSAGE_EDIT_WINDOW_MS} of
|
|
402
|
+
* `created_at`, and for a site administrator with no window at all. A system
|
|
403
|
+
* message is never editable by anybody. Past the window: `401`.
|
|
404
|
+
*
|
|
405
|
+
* `edited_at` is stamped only when the content actually differs, so
|
|
406
|
+
* re-sending the same string is a genuine no-op rather than a way to mark a
|
|
407
|
+
* message edited.
|
|
408
|
+
*
|
|
409
|
+
* Does NOT touch the chat, so an edit does not reorder
|
|
410
|
+
* {@link GroupChatsNamespace.list}.
|
|
411
|
+
*/
|
|
412
|
+
edit(chatId: GroupChatId, messageId: GroupChatMessageId, content: string, options?: RequestOptions): Promise<GroupChatMessage>;
|
|
413
|
+
/**
|
|
414
|
+
* `DELETE /group_chats/:id/messages/:id` - `204`, empty body.
|
|
415
|
+
*
|
|
416
|
+
* The sender may delete at ANY time - unlike editing, destroying has no
|
|
417
|
+
* fifteen-minute window - and so may a site administrator. A system message
|
|
418
|
+
* cannot be deleted by anyone. The row and its blob go for everybody.
|
|
419
|
+
*
|
|
420
|
+
* Deleting does not touch the chat, so {@link GroupChatsNamespace.list} keeps
|
|
421
|
+
* its old ordering, and it invalidates any `afterId` cursor pointing at the
|
|
422
|
+
* deleted message: the next {@link list} call with that cursor silently
|
|
423
|
+
* restarts at the top of the chat. See {@link list}.
|
|
424
|
+
*/
|
|
425
|
+
delete(chatId: GroupChatId, messageId: GroupChatMessageId, options?: RequestOptions): Promise<void>;
|
|
426
|
+
/**
|
|
427
|
+
* `GET /group_chats/:id/messages/:id/attachment` - the bytes of the attached
|
|
428
|
+
* file.
|
|
429
|
+
*
|
|
430
|
+
* A `302` to a presigned object-store URL, which `fetch` follows on its own
|
|
431
|
+
* everywhere except a browser in cookie mode; see
|
|
432
|
+
* {@link DirectMessagesNamespace.attachment} for why, and use
|
|
433
|
+
* {@link attachmentUrl} there.
|
|
434
|
+
*
|
|
435
|
+
* Filename, byte size and content type are on the {@link GroupChatMessage}
|
|
436
|
+
* itself - but only when it HAS an attachment: those three fields are ABSENT
|
|
437
|
+
* rather than `null` on a message without one. Test `has_attachment`, not
|
|
438
|
+
* `attachment_filename !== null`.
|
|
439
|
+
*
|
|
440
|
+
* @throws {OmsError} `unsupported` when the redirect was blocked by CORS.
|
|
441
|
+
* @throws {OmsApiError} `404` with a `null` body when the chat is not the
|
|
442
|
+
* caller's or the message is not in it; `404 "No attachment"` when it
|
|
443
|
+
* carries none.
|
|
444
|
+
*/
|
|
445
|
+
attachment(chatId: GroupChatId, messageId: GroupChatMessageId, options?: RequestOptions): Promise<Blob>;
|
|
446
|
+
/**
|
|
447
|
+
* Absolute URL for a group chat attachment, for an `<img>`, an
|
|
448
|
+
* `<a download>` or a new tab.
|
|
449
|
+
*
|
|
450
|
+
* Same rules as {@link DirectMessagesNamespace.attachmentUrl}: no credential
|
|
451
|
+
* in cookie mode, `?token=` in token mode, and THE TOKEN-MODE URL IS A LIVE
|
|
452
|
+
* CREDENTIAL - build it at the moment of use and never store, log or share
|
|
453
|
+
* it.
|
|
454
|
+
*/
|
|
455
|
+
attachmentUrl(chatId: GroupChatId, messageId: GroupChatMessageId): Promise<string>;
|
|
456
|
+
}
|
|
457
|
+
/** A system message: rendered as a centred pill, never editable or deletable. */
|
|
458
|
+
export declare function isSystemMessage(message: GroupChatMessage): boolean;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** The `social` namespace: direct messages, relationships and group chats, reachable as `oms.social`. */
|
|
2
|
+
import { Resource } from "../../http";
|
|
3
|
+
import { GroupChatsNamespace } from "./groupChats";
|
|
4
|
+
import { DirectMessagesNamespace } from "./messages";
|
|
5
|
+
import { RelationshipsNamespace } from "./relationships";
|
|
6
|
+
export * from "./groupChats";
|
|
7
|
+
export * from "./messages";
|
|
8
|
+
export * from "./relationships";
|
|
9
|
+
export * from "./types";
|
|
10
|
+
/** The `social` namespace, reachable as `oms.social`. */
|
|
11
|
+
export declare class SocialNamespace extends Resource {
|
|
12
|
+
/** One-to-one messages. */
|
|
13
|
+
readonly messages: DirectMessagesNamespace;
|
|
14
|
+
/** Friendships and blocks. */
|
|
15
|
+
readonly relationships: RelationshipsNamespace;
|
|
16
|
+
/** Many-to-many chats, their roster and their messages. */
|
|
17
|
+
readonly groupChats: GroupChatsNamespace;
|
|
18
|
+
constructor(http: ConstructorParameters<typeof Resource>[0]);
|
|
19
|
+
}
|