@ticketpm/core 0.0.4

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 (48) hide show
  1. package/LICENSE +372 -0
  2. package/README.md +364 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/canonical.d.ts +26 -0
  5. package/dist/canonical.d.ts.map +1 -0
  6. package/dist/canonical.js +51 -0
  7. package/dist/canonical.js.map +1 -0
  8. package/dist/compact.d.ts +24 -0
  9. package/dist/compact.d.ts.map +1 -0
  10. package/dist/compact.js +164 -0
  11. package/dist/compact.js.map +1 -0
  12. package/dist/constants.d.ts +11 -0
  13. package/dist/constants.d.ts.map +1 -0
  14. package/dist/constants.js +11 -0
  15. package/dist/constants.js.map +1 -0
  16. package/dist/identity.d.ts +24 -0
  17. package/dist/identity.d.ts.map +1 -0
  18. package/dist/identity.js +35 -0
  19. package/dist/identity.js.map +1 -0
  20. package/dist/index.d.ts +10 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +10 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/media-proxy.d.ts +100 -0
  25. package/dist/media-proxy.d.ts.map +1 -0
  26. package/dist/media-proxy.js +318 -0
  27. package/dist/media-proxy.js.map +1 -0
  28. package/dist/runtime.d.ts +12 -0
  29. package/dist/runtime.d.ts.map +1 -0
  30. package/dist/runtime.js +48 -0
  31. package/dist/runtime.js.map +1 -0
  32. package/dist/types.d.ts +509 -0
  33. package/dist/types.d.ts.map +1 -0
  34. package/dist/types.js +94 -0
  35. package/dist/types.js.map +1 -0
  36. package/dist/upload-client.d.ts +99 -0
  37. package/dist/upload-client.d.ts.map +1 -0
  38. package/dist/upload-client.js +115 -0
  39. package/dist/upload-client.js.map +1 -0
  40. package/dist/utils.d.ts +7 -0
  41. package/dist/utils.d.ts.map +1 -0
  42. package/dist/utils.js +35 -0
  43. package/dist/utils.js.map +1 -0
  44. package/dist/validation.d.ts +34 -0
  45. package/dist/validation.d.ts.map +1 -0
  46. package/dist/validation.js +425 -0
  47. package/dist/validation.js.map +1 -0
  48. package/package.json +32 -0
@@ -0,0 +1,164 @@
1
+ import { sortRecordByKey } from "./utils.js";
2
+ function compactInteractionMetadata(metadata) {
3
+ if (!metadata) {
4
+ return undefined;
5
+ }
6
+ return {
7
+ id: metadata.id,
8
+ type: metadata.type,
9
+ user_id: metadata.user.id,
10
+ name: metadata.name,
11
+ original_response_message_id: metadata.original_response_message_id,
12
+ triggering_interaction_metadata: compactInteractionMetadata(metadata.triggering_interaction_metadata)
13
+ };
14
+ }
15
+ function compactInteraction(interaction) {
16
+ if (!interaction) {
17
+ return undefined;
18
+ }
19
+ return {
20
+ id: interaction.id,
21
+ type: interaction.type,
22
+ name: interaction.name,
23
+ user_id: interaction.user.id
24
+ };
25
+ }
26
+ function compactPoll(poll) {
27
+ if (!poll) {
28
+ return undefined;
29
+ }
30
+ const { answer_voters, ...compactPollData } = poll;
31
+ if (!answer_voters || Object.keys(answer_voters).length === 0) {
32
+ return compactPollData;
33
+ }
34
+ return {
35
+ ...compactPollData,
36
+ answer_voter_ids: Object.fromEntries(Object.entries(answer_voters).map(([answerId, voters]) => [Number(answerId), voters.map((voter) => voter.id)]))
37
+ };
38
+ }
39
+ function compactReferencedMessage(message) {
40
+ return {
41
+ id: message.id,
42
+ type: message.type,
43
+ author_id: message.author?.id,
44
+ content: message.content,
45
+ mention_everyone: message.mention_everyone || undefined,
46
+ interaction: message.interaction ? { type: message.interaction.type } : undefined,
47
+ interaction_metadata: message.interaction_metadata ? { type: message.interaction_metadata.type } : undefined,
48
+ embeds: message.embeds,
49
+ attachments: message.attachments,
50
+ sticker_items: message.sticker_items
51
+ };
52
+ }
53
+ function compactMessageSnapshot(snapshot) {
54
+ return {
55
+ message: {
56
+ ...snapshot.message,
57
+ mention_everyone: snapshot.message.mention_everyone || undefined
58
+ }
59
+ };
60
+ }
61
+ function compactMessage(message) {
62
+ return {
63
+ id: message.id,
64
+ type: message.type,
65
+ timestamp: message.timestamp,
66
+ author_id: message.author?.id,
67
+ content: message.content,
68
+ mention_everyone: message.mention_everyone || undefined,
69
+ edited_timestamp: message.edited_timestamp,
70
+ attachments: message.attachments,
71
+ embeds: message.embeds,
72
+ reactions: message.reactions,
73
+ components: message.components,
74
+ sticker_items: message.sticker_items,
75
+ poll: compactPoll(message.poll),
76
+ interaction_metadata: compactInteractionMetadata(message.interaction_metadata),
77
+ interaction: compactInteraction(message.interaction),
78
+ message_reference: message.message_reference,
79
+ message_snapshots: message.message_snapshots?.map(compactMessageSnapshot),
80
+ referenced_message: message.referenced_message
81
+ ? compactReferencedMessage(message.referenced_message)
82
+ : message.referenced_message,
83
+ mention_ids: message.mentions?.map((user) => user.id),
84
+ mention_roles: message.mention_roles
85
+ };
86
+ }
87
+ /**
88
+ * Prune `null`, `undefined`, and structurally empty values while preserving the
89
+ * two context containers that are intentionally meaningful when non-empty.
90
+ */
91
+ export function pruneForExport(value) {
92
+ if (value === null || value === undefined) {
93
+ return undefined;
94
+ }
95
+ if (Array.isArray(value)) {
96
+ const prunedArray = value
97
+ .map((item) => pruneForExport(item))
98
+ .filter((item) => item !== undefined);
99
+ return prunedArray.length > 0 ? prunedArray : undefined;
100
+ }
101
+ if (typeof value === "object") {
102
+ const objectValue = value;
103
+ const prunedObject = {};
104
+ for (const key of Object.keys(objectValue).sort()) {
105
+ if (key === "members" || key === "roles") {
106
+ const nestedRecord = objectValue[key];
107
+ if (nestedRecord && Object.keys(nestedRecord).length > 0) {
108
+ prunedObject[key] = nestedRecord;
109
+ }
110
+ continue;
111
+ }
112
+ const prunedValue = pruneForExport(objectValue[key]);
113
+ if (prunedValue !== undefined) {
114
+ prunedObject[key] = prunedValue;
115
+ }
116
+ }
117
+ return Object.keys(prunedObject).length > 0 ? prunedObject : undefined;
118
+ }
119
+ return value;
120
+ }
121
+ /**
122
+ * Context ordering participates in canonical byte generation, so each map is
123
+ * normalized explicitly before serialization.
124
+ */
125
+ export function sortTranscriptContext(context) {
126
+ const transcriptChannelId = context.channel_id;
127
+ const channels = { ...(context.channels ?? {}) };
128
+ if (transcriptChannelId && !channels[transcriptChannelId]) {
129
+ channels[transcriptChannelId] = { name: transcriptChannelId };
130
+ }
131
+ return {
132
+ channel_id: transcriptChannelId,
133
+ users: sortRecordByKey(context.users),
134
+ channels: sortRecordByKey(channels),
135
+ roles: sortRecordByKey(context.roles),
136
+ members: sortRecordByKey(context.members),
137
+ guild: context.guild
138
+ };
139
+ }
140
+ /**
141
+ * Produce the compact stored transcript format that the upload API hashes and
142
+ * the viewer hydrates.
143
+ */
144
+ export function buildStoredTranscript(input) {
145
+ const compactTranscript = {
146
+ messages: input.messages.map(compactMessage),
147
+ context: sortTranscriptContext(input.context)
148
+ };
149
+ return (pruneForExport(compactTranscript) ?? {
150
+ messages: []
151
+ });
152
+ }
153
+ /**
154
+ * Preserve the first-party chronological ordering convention for adapters that
155
+ * receive newest-first collections from Discord APIs.
156
+ */
157
+ export function sortMessagesChronologically(messages) {
158
+ return [...messages].sort((left, right) => {
159
+ const leftTimestamp = new Date(left.timestamp ?? 0).getTime();
160
+ const rightTimestamp = new Date(right.timestamp ?? 0).getTime();
161
+ return leftTimestamp - rightTimestamp;
162
+ });
163
+ }
164
+ //# sourceMappingURL=compact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compact.js","sourceRoot":"","sources":["../src/compact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Shared constants copied from the current ticket.pm API contract so that
3
+ * package consumers can validate payloads before hitting the network.
4
+ */
5
+ export declare const MAX_TRANSCRIPT_COMPRESSED_BYTES: number;
6
+ export declare const MAX_TRANSCRIPT_DECOMPRESSED_BYTES: number;
7
+ export declare const MAX_TRANSCRIPT_CHANNEL_NAME_CHARACTERS = 100;
8
+ export declare const MAX_TRANSCRIPT_NESTING_DEPTH = 20;
9
+ export declare const DEFAULT_TRANSCRIPT_COMPRESSION_LEVEL = 15;
10
+ export declare const DEFAULT_TICKETPM_MEDIA_PROXY_BASE_URL = "https://m.ticket.pm/v2";
11
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,+BAA+B,QAAmB,CAAC;AAChE,eAAO,MAAM,iCAAiC,QAAoB,CAAC;AACnE,eAAO,MAAM,sCAAsC,MAAM,CAAC;AAC1D,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAC/C,eAAO,MAAM,oCAAoC,KAAK,CAAC;AACvD,eAAO,MAAM,qCAAqC,2BAA2B,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Shared constants copied from the current ticket.pm API contract so that
3
+ * package consumers can validate payloads before hitting the network.
4
+ */
5
+ export const MAX_TRANSCRIPT_COMPRESSED_BYTES = 32 * 1024 * 1024;
6
+ export const MAX_TRANSCRIPT_DECOMPRESSED_BYTES = 128 * 1024 * 1024;
7
+ export const MAX_TRANSCRIPT_CHANNEL_NAME_CHARACTERS = 100;
8
+ export const MAX_TRANSCRIPT_NESTING_DEPTH = 20;
9
+ export const DEFAULT_TRANSCRIPT_COMPRESSION_LEVEL = 15;
10
+ export const DEFAULT_TICKETPM_MEDIA_PROXY_BASE_URL = "https://m.ticket.pm/v2";
11
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAChE,MAAM,CAAC,MAAM,iCAAiC,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AACnE,MAAM,CAAC,MAAM,sCAAsC,GAAG,GAAG,CAAC;AAC1D,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAC/C,MAAM,CAAC,MAAM,oCAAoC,GAAG,EAAE,CAAC;AACvD,MAAM,CAAC,MAAM,qCAAqC,GAAG,wBAAwB,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { UserInfo } from "./types.js";
2
+ export type IdentityUser = Pick<UserInfo, "bot" | "public_flags" | "username"> & {
3
+ discriminator?: string | null;
4
+ };
5
+ /**
6
+ * Discord marks verified bots with the public flag bit `1 << 16`.
7
+ */
8
+ export declare function isVerifiedBot(user: Pick<UserInfo, "bot" | "public_flags">): boolean;
9
+ /**
10
+ * The first-party exporter distinguishes ordinary bot users from webhook
11
+ * authors because webhooks do not have a stable application identity.
12
+ */
13
+ export declare function isWebhookAuthor(user: Pick<UserInfo, "bot" | "public_flags">, options?: {
14
+ isWebhook?: boolean;
15
+ applicationId?: string | null;
16
+ }): boolean;
17
+ /**
18
+ * The viewer wants canonical usernames for real users, but bot-like identities
19
+ * keep a `name#discriminator` shape so they stay visually distinguishable.
20
+ */
21
+ export declare function formatExportUsername(user: IdentityUser, options?: {
22
+ webhook?: boolean;
23
+ }): string;
24
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,GAAG,cAAc,GAAG,UAAU,CAAC,GAAG;IAChF,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,CAAC;AAEF;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,GAAG,cAAc,CAAC,GAAG,OAAO,CAOnF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC9B,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,GAAG,cAAc,CAAC,EAC5C,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC9D,OAAO,CAMT;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAWhG"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Discord marks verified bots with the public flag bit `1 << 16`.
3
+ */
4
+ export function isVerifiedBot(user) {
5
+ if (!user.bot) {
6
+ return false;
7
+ }
8
+ const flags = user.public_flags ?? 0;
9
+ return (flags & (1 << 16)) === 1 << 16;
10
+ }
11
+ /**
12
+ * The first-party exporter distinguishes ordinary bot users from webhook
13
+ * authors because webhooks do not have a stable application identity.
14
+ */
15
+ export function isWebhookAuthor(user, options) {
16
+ if (!user.bot || !options?.isWebhook) {
17
+ return false;
18
+ }
19
+ return !options.applicationId;
20
+ }
21
+ /**
22
+ * The viewer wants canonical usernames for real users, but bot-like identities
23
+ * keep a `name#discriminator` shape so they stay visually distinguishable.
24
+ */
25
+ export function formatExportUsername(user, options) {
26
+ if (!user.bot && !options?.webhook) {
27
+ return user.username;
28
+ }
29
+ if (user.username.includes("#")) {
30
+ return user.username;
31
+ }
32
+ const discriminator = user.discriminator && user.discriminator.length > 0 ? user.discriminator : "0000";
33
+ return `${user.username}#${discriminator}`;
34
+ }
35
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,IAA4C;IACzE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACf,OAAO,KAAK,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC9B,IAA4C,EAC5C,OAAgE;IAEhE,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAkB,EAAE,OAA+B;IACvF,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC;IACxG,OAAO,GAAG,IAAI,CAAC,QAAQ,IAAI,aAAa,EAAE,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,10 @@
1
+ export * from "./canonical.js";
2
+ export * from "./compact.js";
3
+ export * from "./constants.js";
4
+ export * from "./identity.js";
5
+ export * from "./media-proxy.js";
6
+ export * from "./runtime.js";
7
+ export * from "./types.js";
8
+ export * from "./upload-client.js";
9
+ export * from "./validation.js";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ export * from "./canonical.js";
2
+ export * from "./compact.js";
3
+ export * from "./constants.js";
4
+ export * from "./identity.js";
5
+ export * from "./media-proxy.js";
6
+ export * from "./runtime.js";
7
+ export * from "./types.js";
8
+ export * from "./upload-client.js";
9
+ export * from "./validation.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,100 @@
1
+ import type { DiscordContext, DraftMessage, GuildInfo, UserInfo } from "./types.js";
2
+ export interface TicketPmMediaProxyClientOptions {
3
+ /**
4
+ * Base media API URL, for example `https://m.ticket.pm/v2`.
5
+ *
6
+ * This value controls both where upload requests are sent and which proxy
7
+ * URLs are generated on successful uploads.
8
+ */
9
+ baseUrl: string;
10
+ /**
11
+ * Optional bearer token or raw token string. Raw values are normalized into
12
+ * the `Authorization: Bearer ...` header automatically.
13
+ */
14
+ token?: string;
15
+ /**
16
+ * Optional custom fetch implementation for environments that need their own
17
+ * HTTP transport, instrumentation, retries, or authentication pipeline.
18
+ */
19
+ fetch?: typeof fetch;
20
+ }
21
+ export type UploadProgressCallback = (completed: number, total: number) => void;
22
+ /**
23
+ * Stateful client with in-memory dedupe so repeated avatar/icon/media uploads
24
+ * inside a single export run do not fan out into redundant requests.
25
+ */
26
+ export declare class TicketPmMediaProxyClient {
27
+ private readonly options;
28
+ private readonly fetchImpl;
29
+ private readonly avatarUploadCache;
30
+ private readonly iconUploadCache;
31
+ private readonly attachmentUploadCache;
32
+ constructor(options: TicketPmMediaProxyClientOptions);
33
+ get baseUrl(): string;
34
+ /**
35
+ * Upload a Discord avatar hash to the configured media proxy.
36
+ *
37
+ * On success, the returned value is the proxy avatar URL. On failure, this
38
+ * returns `undefined` and the caller is expected to keep the original avatar
39
+ * hash untouched in transcript data.
40
+ */
41
+ uploadAvatarHash(hash: string, userId: string): Promise<string | undefined>;
42
+ uploadGuildIconHash(hash: string, guildId: string): Promise<string | undefined>;
43
+ /**
44
+ * Upload a media URL to the configured proxy.
45
+ *
46
+ * If the proxy is unavailable, returns a non-2xx response, or produces an
47
+ * invalid payload, this returns `undefined`. Callers should treat that as a
48
+ * no-rewrite outcome and keep the original media URL fields.
49
+ */
50
+ uploadAttachmentUrl(url: string): Promise<string | undefined>;
51
+ }
52
+ /**
53
+ * Walk a transcript recursively and collect the media URLs that would be sent
54
+ * to the proxy service.
55
+ */
56
+ export declare function collectTranscriptMediaUrls(messages: readonly DraftMessage[]): Set<string>;
57
+ /**
58
+ * Upload all avatar hashes already present in `context.users` so the media API
59
+ * can cache them, but keep `user.avatar` as the original Discord hash.
60
+ *
61
+ * The viewer still expects `user.avatar` to be a raw Discord avatar hash and
62
+ * derives the final CDN URL from `user.id + user.avatar`. Replacing the field
63
+ * with a proxy URL would make the serialized transcript incompatible with the
64
+ * existing viewer contract.
65
+ */
66
+ export declare function proxyTranscriptAvatarsInPlace(users: Record<string, UserInfo>, client: TicketPmMediaProxyClient, options?: {
67
+ onProgress?: UploadProgressCallback;
68
+ }): Promise<void>;
69
+ /**
70
+ * Proxy the guild icon if one exists and mutate the guild object in place.
71
+ */
72
+ export declare function proxyGuildIconInPlace(guild: GuildInfo, client: TicketPmMediaProxyClient): Promise<string | undefined>;
73
+ /**
74
+ * Rewrite nested media-bearing fields to prefer the ticket.pm proxy service.
75
+ *
76
+ * Failure behavior:
77
+ *
78
+ * - successful proxy uploads write `proxy_url` or `proxy_icon_url`
79
+ * - failed proxy uploads leave existing fields unchanged
80
+ * - original Discord-hosted media URLs remain available as fallback
81
+ */
82
+ export declare function rewriteTranscriptMediaUrlsInPlace(messages: DraftMessage[], client: TicketPmMediaProxyClient, options?: {
83
+ onProgress?: UploadProgressCallback;
84
+ expectedUrls?: Set<string>;
85
+ }): Promise<void>;
86
+ /**
87
+ * Convenience wrapper for callers that keep the whole transcript structure
88
+ * together while proxying assets.
89
+ *
90
+ * This helper is best-effort. Media proxy failures do not throw away the
91
+ * original transcript media fields; they simply leave them as they were.
92
+ */
93
+ export declare function proxyTranscriptAssetsInPlace(transcript: {
94
+ messages: DraftMessage[];
95
+ context: DiscordContext;
96
+ }, client: TicketPmMediaProxyClient, options?: {
97
+ avatarProgress?: UploadProgressCallback;
98
+ mediaProgress?: UploadProgressCallback;
99
+ }): Promise<void>;
100
+ //# sourceMappingURL=media-proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-proxy.d.ts","sourceRoot":"","sources":["../src/media-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAQpF,MAAM,WAAW,+BAA+B;IAC/C;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACrB;AAED,MAAM,MAAM,sBAAsB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;AAsChF;;;GAGG;AACH,qBAAa,wBAAwB;IAMjB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAL3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAkD;IACpF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkD;IAClF,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAkD;gBAEpD,OAAO,EAAE,+BAA+B;IAI5E,IAAW,OAAO,IAAI,MAAM,CAE3B;IAED;;;;;;OAMG;IACU,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAyC3E,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAyC5F;;;;;;OAMG;IACU,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAiC1E;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAmDzF;AAED;;;;;;;;GAQG;AACH,wBAAsB,6BAA6B,CAClD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC/B,MAAM,EAAE,wBAAwB,EAChC,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,sBAAsB,CAAA;CAAE,GAC/C,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,wBAAwB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAW3H;AAwBD;;;;;;;;GAQG;AACH,wBAAsB,iCAAiC,CACtD,QAAQ,EAAE,YAAY,EAAE,EACxB,MAAM,EAAE,wBAAwB,EAChC,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,sBAAsB,CAAC;IAAC,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAAE,GAC3E,OAAO,CAAC,IAAI,CAAC,CAqCf;AAED;;;;;;GAMG;AACH,wBAAsB,4BAA4B,CACjD,UAAU,EAAE;IAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,EACjE,MAAM,EAAE,wBAAwB,EAChC,OAAO,CAAC,EAAE;IACT,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,aAAa,CAAC,EAAE,sBAAsB,CAAC;CACvC,GACC,OAAO,CAAC,IAAI,CAAC,CAcf"}