sweety-html-transcripts 0.2.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/LICENSE +201 -0
- package/README.md +127 -0
- package/dist/adapters/core.d.ts +41 -0
- package/dist/adapters/core.js +30 -0
- package/dist/adapters/core.js.map +1 -0
- package/dist/adapters/discordjs.d.ts +26 -0
- package/dist/adapters/discordjs.js +102 -0
- package/dist/adapters/discordjs.js.map +1 -0
- package/dist/adapters/seyfert.d.ts +26 -0
- package/dist/adapters/seyfert.js +67 -0
- package/dist/adapters/seyfert.js.map +1 -0
- package/dist/downloader/images.d.ts +37 -0
- package/dist/downloader/images.js +119 -0
- package/dist/downloader/images.js.map +1 -0
- package/dist/generator/index.d.ts +34 -0
- package/dist/generator/index.js +81 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/generator/renderers/attachment.d.ts +24 -0
- package/dist/generator/renderers/attachment.js +133 -0
- package/dist/generator/renderers/attachment.js.map +1 -0
- package/dist/generator/renderers/components.d.ts +8 -0
- package/dist/generator/renderers/components.js +179 -0
- package/dist/generator/renderers/components.js.map +1 -0
- package/dist/generator/renderers/content.d.ts +32 -0
- package/dist/generator/renderers/content.js +168 -0
- package/dist/generator/renderers/content.js.map +1 -0
- package/dist/generator/renderers/embed.d.ts +15 -0
- package/dist/generator/renderers/embed.js +77 -0
- package/dist/generator/renderers/embed.js.map +1 -0
- package/dist/generator/renderers/message.d.ts +15 -0
- package/dist/generator/renderers/message.js +95 -0
- package/dist/generator/renderers/message.js.map +1 -0
- package/dist/generator/renderers/reply.d.ts +7 -0
- package/dist/generator/renderers/reply.js +76 -0
- package/dist/generator/renderers/reply.js.map +1 -0
- package/dist/generator/renderers/systemMessage.d.ts +19 -0
- package/dist/generator/renderers/systemMessage.js +109 -0
- package/dist/generator/renderers/systemMessage.js.map +1 -0
- package/dist/generator/transcript.d.ts +12 -0
- package/dist/generator/transcript.js +85 -0
- package/dist/generator/transcript.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +143 -0
- package/dist/index.js.map +1 -0
- package/dist/static/client.d.ts +2 -0
- package/dist/static/client.js +30 -0
- package/dist/static/client.js.map +1 -0
- package/dist/types.d.ts +69 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/api.d.ts +19 -0
- package/dist/utils/api.js +364 -0
- package/dist/utils/api.js.map +1 -0
- package/dist/utils/cdn.d.ts +28 -0
- package/dist/utils/cdn.js +61 -0
- package/dist/utils/cdn.js.map +1 -0
- package/dist/utils/channel.d.ts +34 -0
- package/dist/utils/channel.js +51 -0
- package/dist/utils/channel.js.map +1 -0
- package/dist/utils/embeds.d.ts +2 -0
- package/dist/utils/embeds.js +17 -0
- package/dist/utils/embeds.js.map +1 -0
- package/dist/utils/guild.d.ts +9 -0
- package/dist/utils/guild.js +19 -0
- package/dist/utils/guild.js.map +1 -0
- package/dist/utils/message.d.ts +6 -0
- package/dist/utils/message.js +11 -0
- package/dist/utils/message.js.map +1 -0
- package/dist/utils/profiles.d.ts +18 -0
- package/dist/utils/profiles.js +67 -0
- package/dist/utils/profiles.js.map +1 -0
- package/dist/utils/replacer.d.ts +28 -0
- package/dist/utils/replacer.js +67 -0
- package/dist/utils/replacer.js.map +1 -0
- package/dist/utils/user.d.ts +18 -0
- package/dist/utils/user.js +38 -0
- package/dist/utils/user.js.map +1 -0
- package/dist/utils/utils.d.ts +32 -0
- package/dist/utils/utils.js +61 -0
- package/dist/utils/utils.js.map +1 -0
- package/package.json +90 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { WebpOptions } from 'sharp';
|
|
2
|
+
import type { APIAttachment, APIMessage, APIMessageSnapshot } from 'discord-api-types/v10';
|
|
3
|
+
import type { Awaitable } from '../adapters/core';
|
|
4
|
+
/**
|
|
5
|
+
* Callback used to save an image attachment.
|
|
6
|
+
* The returned string is the URL that will be used in the transcript.
|
|
7
|
+
*
|
|
8
|
+
* `undefined` indicates to use the original attachment URL.
|
|
9
|
+
* `null` indicates to not include the attachment in the transcript.
|
|
10
|
+
* `string` indicates to use the returned URL as the attachment URL (base64 or remote image).
|
|
11
|
+
*/
|
|
12
|
+
export type ResolveImageCallback = (attachment: APIAttachment, message: APIMessage | APIMessageSnapshot['message']) => Awaitable<string | null | undefined>;
|
|
13
|
+
/**
|
|
14
|
+
* Builder to build a image saving callback.
|
|
15
|
+
*/
|
|
16
|
+
export declare class TranscriptImageDownloader {
|
|
17
|
+
private static log;
|
|
18
|
+
private log;
|
|
19
|
+
private maxFileSize?;
|
|
20
|
+
private compression?;
|
|
21
|
+
/**
|
|
22
|
+
* Sets the maximum file size for *each* individual image.
|
|
23
|
+
* @param size The maximum file size in kilobytes
|
|
24
|
+
*/
|
|
25
|
+
withMaxSize(size: number): this;
|
|
26
|
+
/**
|
|
27
|
+
* Sets the compression quality for each image. This requires `sharp` to be installed.
|
|
28
|
+
* Optionally, images can be converted to WebP format which is smaller in size.
|
|
29
|
+
* @param quality The quality of the image (1 lowest - 100 highest). Lower quality means smaller file size.
|
|
30
|
+
* @param convertToWebP Whether to convert the image to WebP format
|
|
31
|
+
*/
|
|
32
|
+
withCompression(quality?: number, convertToWebP?: boolean, options?: Omit<WebpOptions, 'quality' | 'force'>): this;
|
|
33
|
+
/**
|
|
34
|
+
* Builds the image saving callback.
|
|
35
|
+
*/
|
|
36
|
+
build(): ResolveImageCallback;
|
|
37
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.TranscriptImageDownloader = void 0;
|
|
40
|
+
const undici_1 = require("undici");
|
|
41
|
+
const debug_1 = __importDefault(require("debug"));
|
|
42
|
+
/**
|
|
43
|
+
* Builder to build a image saving callback.
|
|
44
|
+
*/
|
|
45
|
+
class TranscriptImageDownloader {
|
|
46
|
+
constructor() {
|
|
47
|
+
this.log = TranscriptImageDownloader.log;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Sets the maximum file size for *each* individual image.
|
|
51
|
+
* @param size The maximum file size in kilobytes
|
|
52
|
+
*/
|
|
53
|
+
withMaxSize(size) {
|
|
54
|
+
this.maxFileSize = size;
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Sets the compression quality for each image. This requires `sharp` to be installed.
|
|
59
|
+
* Optionally, images can be converted to WebP format which is smaller in size.
|
|
60
|
+
* @param quality The quality of the image (1 lowest - 100 highest). Lower quality means smaller file size.
|
|
61
|
+
* @param convertToWebP Whether to convert the image to WebP format
|
|
62
|
+
*/
|
|
63
|
+
withCompression(quality = 80, convertToWebP = false, options = {}) {
|
|
64
|
+
if (quality < 1 || quality > 100)
|
|
65
|
+
throw new Error('Quality must be between 1 and 100');
|
|
66
|
+
// try and import sharp
|
|
67
|
+
Promise.resolve().then(() => __importStar(require('sharp'))).catch((err) => {
|
|
68
|
+
console.error(err);
|
|
69
|
+
console.error(`[sweety-html-transcripts] Failed to import 'sharp'. Image compression requires the 'sharp' package to be installed. Either install sharp or remove the compression options.`);
|
|
70
|
+
});
|
|
71
|
+
this.compression = { quality, convertToWebP, options };
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Builds the image saving callback.
|
|
76
|
+
*/
|
|
77
|
+
build() {
|
|
78
|
+
return async (attachment) => {
|
|
79
|
+
// if the attachment is not an image, return null
|
|
80
|
+
if (!attachment.width || !attachment.height)
|
|
81
|
+
return undefined;
|
|
82
|
+
// if the max file size is set, check if the file size is within the limit
|
|
83
|
+
if (this.maxFileSize && attachment.size > this.maxFileSize * 1024)
|
|
84
|
+
return undefined;
|
|
85
|
+
// fetch the image
|
|
86
|
+
this.log(`Fetching attachment ${attachment.id}: ${attachment.url}`);
|
|
87
|
+
const response = await (0, undici_1.request)(attachment.url).catch((err) => {
|
|
88
|
+
console.error(`[sweety-html-transcripts] Failed to download image for transcript: `, err);
|
|
89
|
+
return null;
|
|
90
|
+
});
|
|
91
|
+
if (!response)
|
|
92
|
+
return undefined;
|
|
93
|
+
const mimetype = response.headers['content-type'];
|
|
94
|
+
const buffer = await response.body.arrayBuffer().then((res) => Buffer.from(res));
|
|
95
|
+
this.log(`Finished fetching ${attachment.id} (${buffer.length} bytes)`);
|
|
96
|
+
// if the compression options are set, compress the image
|
|
97
|
+
if (this.compression) {
|
|
98
|
+
const sharp = await Promise.resolve().then(() => __importStar(require('sharp')));
|
|
99
|
+
this.log(`Compressing ${attachment.id} with 'sharp'`);
|
|
100
|
+
const sharpbuf = await sharp
|
|
101
|
+
.default(buffer)
|
|
102
|
+
.webp({
|
|
103
|
+
quality: this.compression.quality,
|
|
104
|
+
force: this.compression.convertToWebP,
|
|
105
|
+
effort: 2,
|
|
106
|
+
...this.compression.options,
|
|
107
|
+
})
|
|
108
|
+
.toBuffer({ resolveWithObject: true });
|
|
109
|
+
this.log(`Finished compressing ${attachment.id} (${sharpbuf.info.size} bytes)`);
|
|
110
|
+
return `data:image/${sharpbuf.info.format};base64,${sharpbuf.data.toString('base64')}`;
|
|
111
|
+
}
|
|
112
|
+
// return the base64 string
|
|
113
|
+
return `data:${mimetype};base64,${buffer.toString('base64')}`;
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.TranscriptImageDownloader = TranscriptImageDownloader;
|
|
118
|
+
TranscriptImageDownloader.log = (0, debug_1.default)('sweety-html-transcripts:TranscriptImageDownloader');
|
|
119
|
+
//# sourceMappingURL=images.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"images.js","sourceRoot":"","sources":["../../src/downloader/images.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { APIGuild, APIRole, APIUser } from 'discord-api-types/v10';
|
|
2
|
+
import type { Awaitable, TranscriptAdapter } from '../adapters/core';
|
|
3
|
+
import type { ResolveImageCallback } from '../downloader/images';
|
|
4
|
+
import type { AllAPIChannel, APIMessageData } from '../utils/channel';
|
|
5
|
+
export type RenderMessageContext = {
|
|
6
|
+
adapter: TranscriptAdapter<unknown>;
|
|
7
|
+
messages: APIMessageData[];
|
|
8
|
+
channel: AllAPIChannel;
|
|
9
|
+
guild?: APIGuild | null;
|
|
10
|
+
callbacks: {
|
|
11
|
+
resolveImageSrc: ResolveImageCallback;
|
|
12
|
+
resolveChannel: (channelId: string) => Awaitable<AllAPIChannel | null>;
|
|
13
|
+
resolveUser: (userId: string) => Awaitable<APIUser | null>;
|
|
14
|
+
resolveRole: (roleId: string) => Awaitable<APIRole | null>;
|
|
15
|
+
};
|
|
16
|
+
poweredBy?: boolean;
|
|
17
|
+
footerText?: string;
|
|
18
|
+
saveImages: boolean;
|
|
19
|
+
favicon: 'guild' | string;
|
|
20
|
+
hydrate: boolean;
|
|
21
|
+
/** @default false */
|
|
22
|
+
lightTheme?: boolean;
|
|
23
|
+
selectMenus?: {
|
|
24
|
+
/** @default true */
|
|
25
|
+
includeUsers?: boolean;
|
|
26
|
+
/** @default true */
|
|
27
|
+
includeRoles?: boolean;
|
|
28
|
+
/** @default true */
|
|
29
|
+
includeChannels?: boolean;
|
|
30
|
+
/** @default 25 */
|
|
31
|
+
channelLimits?: number;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
export default function render(context: RenderMessageContext): Promise<string>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = render;
|
|
7
|
+
const hydrate_1 = require("@derockdev/discord-components-core/hydrate");
|
|
8
|
+
const react_1 = __importDefault(require("react"));
|
|
9
|
+
const static_1 = require("react-dom/static");
|
|
10
|
+
const package_json_1 = require("../../package.json");
|
|
11
|
+
const client_1 = require("../static/client");
|
|
12
|
+
const profiles_1 = require("../utils/profiles");
|
|
13
|
+
const channel_1 = require("../utils/channel");
|
|
14
|
+
const guild_1 = require("../utils/guild");
|
|
15
|
+
const utils_1 = require("../utils/utils");
|
|
16
|
+
const transcript_1 = __importDefault(require("./transcript"));
|
|
17
|
+
const resolveVersion = (version) => version.replace('^', '').replace('~', '');
|
|
18
|
+
const discordComponentsVersion = resolveVersion(package_json_1.devDependencies['@penwin/discord-components-core']);
|
|
19
|
+
async function render(context) {
|
|
20
|
+
var _a, _b, _c, _d;
|
|
21
|
+
context.lightTheme ?? (context.lightTheme = false);
|
|
22
|
+
context.selectMenus ?? (context.selectMenus = {});
|
|
23
|
+
(_a = context.selectMenus).includeUsers ?? (_a.includeUsers = true);
|
|
24
|
+
(_b = context.selectMenus).includeRoles ?? (_b.includeRoles = true);
|
|
25
|
+
(_c = context.selectMenus).includeChannels ?? (_c.includeChannels = true);
|
|
26
|
+
(_d = context.selectMenus).channelLimits ?? (_d.channelLimits = 25);
|
|
27
|
+
const { adapter, channel, ...options } = context;
|
|
28
|
+
const profiles = await (0, profiles_1.buildProfiles)(context);
|
|
29
|
+
adapter.renderContext.profiles = profiles;
|
|
30
|
+
// tysom sagiriikeda to fix this <3
|
|
31
|
+
const stream = await (0, static_1.prerenderToNodeStream)(react_1.default.createElement("html", null,
|
|
32
|
+
react_1.default.createElement("head", null,
|
|
33
|
+
react_1.default.createElement("meta", { charSet: "utf-8" }),
|
|
34
|
+
react_1.default.createElement("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }),
|
|
35
|
+
react_1.default.createElement("link", { rel: "icon", type: "image/png", href: options.favicon === 'guild'
|
|
36
|
+
? channel_1.channelUtils.isDM(channel) || channel_1.channelUtils.isDirectory(channel)
|
|
37
|
+
? undefined
|
|
38
|
+
: ((context.guild ? guild_1.guildUtils.iconURL(context.guild, { size: 16, extension: 'png' }) : undefined) ??
|
|
39
|
+
undefined)
|
|
40
|
+
: options.favicon }),
|
|
41
|
+
react_1.default.createElement("title", null, channel_1.channelUtils.isDM(channel) || channel_1.channelUtils.isDirectory(channel) ? 'Direct Messages' : channel.name),
|
|
42
|
+
react_1.default.createElement("script", { dangerouslySetInnerHTML: {
|
|
43
|
+
__html: client_1.scrollToMessage,
|
|
44
|
+
} }),
|
|
45
|
+
!options.hydrate && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
46
|
+
react_1.default.createElement("script", { dangerouslySetInnerHTML: {
|
|
47
|
+
__html: `window.$discordMessage={profiles:${JSON.stringify(profiles)}}`,
|
|
48
|
+
} }),
|
|
49
|
+
react_1.default.createElement("script", { type: "module", src: `https://cdn.jsdelivr.net/npm/@penwin/discord-components-core@${discordComponentsVersion}/dist/bundle/index.mjs` }))),
|
|
50
|
+
react_1.default.createElement("link", { rel: "stylesheet", href: `https://cdn.jsdelivr.net/npm/@penwin/discord-components-core@${discordComponentsVersion}/dist/bundle/styles/base.css` })),
|
|
51
|
+
react_1.default.createElement("body", { style: {
|
|
52
|
+
margin: 0,
|
|
53
|
+
minHeight: '100vh',
|
|
54
|
+
} },
|
|
55
|
+
react_1.default.createElement(transcript_1.default, { context: context })),
|
|
56
|
+
options.hydrate && react_1.default.createElement("script", { dangerouslySetInnerHTML: { __html: client_1.revealSpoiler } })));
|
|
57
|
+
const markup = await (0, utils_1.streamToString)(stream.prelude);
|
|
58
|
+
if (options.hydrate) {
|
|
59
|
+
const result = await (0, hydrate_1.renderToString)(markup, {
|
|
60
|
+
beforeHydrate: async (document) => {
|
|
61
|
+
document.defaultView.$discordMessage = {
|
|
62
|
+
profiles,
|
|
63
|
+
};
|
|
64
|
+
document.defaultView.$discordSelectMenu = {
|
|
65
|
+
users: !adapter.renderContext.selectMenu.users?.injectedScript
|
|
66
|
+
? (adapter.renderContext.selectMenu.users?.data ?? [])
|
|
67
|
+
: [],
|
|
68
|
+
roles: !adapter.renderContext.selectMenu.roles?.injectedScript
|
|
69
|
+
? (adapter.renderContext.selectMenu.roles?.data ?? [])
|
|
70
|
+
: [],
|
|
71
|
+
channels: !adapter.renderContext.selectMenu.channels?.injectedScript
|
|
72
|
+
? (adapter.renderContext.selectMenu.channels?.data ?? [])
|
|
73
|
+
: [],
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
return result.html;
|
|
78
|
+
}
|
|
79
|
+
return markup;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generator/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { APIAttachment, APIMessageSnapshot } from 'discord-api-types/v10';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import type { RenderMessageContext } from '..';
|
|
4
|
+
import type { APIMessageData } from '../../utils/channel';
|
|
5
|
+
/**
|
|
6
|
+
* Renders all attachments for a message
|
|
7
|
+
* @param message
|
|
8
|
+
* @param context
|
|
9
|
+
* @returns
|
|
10
|
+
*/
|
|
11
|
+
export declare function Attachments(props: {
|
|
12
|
+
message: APIMessageData | APIMessageSnapshot['message'];
|
|
13
|
+
context: RenderMessageContext;
|
|
14
|
+
}): Promise<React.JSX.Element>;
|
|
15
|
+
/**
|
|
16
|
+
* Renders one Discord Attachment
|
|
17
|
+
* @param props - the attachment and rendering context
|
|
18
|
+
*/
|
|
19
|
+
export declare function Attachment({ attachment, context, message, isVoiceMessage, }: {
|
|
20
|
+
attachment: APIAttachment;
|
|
21
|
+
context: RenderMessageContext;
|
|
22
|
+
message: APIMessageData | APIMessageSnapshot['message'];
|
|
23
|
+
isVoiceMessage?: boolean;
|
|
24
|
+
}): Promise<React.JSX.Element>;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Attachments = Attachments;
|
|
7
|
+
exports.Attachment = Attachment;
|
|
8
|
+
const discord_components_react_render_1 = require("@penwin/discord-components-react-render");
|
|
9
|
+
const v10_1 = require("discord-api-types/v10");
|
|
10
|
+
const react_1 = __importDefault(require("react"));
|
|
11
|
+
const utils_1 = require("../../utils/utils");
|
|
12
|
+
function getAttachmentType(attachment) {
|
|
13
|
+
const type = attachment.content_type?.split('/')?.[0] ?? 'unknown';
|
|
14
|
+
if (['audio', 'video', 'image'].includes(type))
|
|
15
|
+
return type;
|
|
16
|
+
return 'file';
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Renders all attachments for a message
|
|
20
|
+
* @param message
|
|
21
|
+
* @param context
|
|
22
|
+
* @returns
|
|
23
|
+
*/
|
|
24
|
+
async function Attachments(props) {
|
|
25
|
+
if (props.message.attachments.length === 0)
|
|
26
|
+
return react_1.default.createElement(react_1.default.Fragment, null);
|
|
27
|
+
const grouped = {
|
|
28
|
+
mediaGallery: [],
|
|
29
|
+
other: [],
|
|
30
|
+
};
|
|
31
|
+
for (const attachment of props.message.attachments) {
|
|
32
|
+
const type = getAttachmentType(attachment);
|
|
33
|
+
if (type === 'image' || type === 'video') {
|
|
34
|
+
grouped.mediaGallery.push(attachment);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
grouped.other.push(attachment);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const isVoiceMessage = props.message.flags
|
|
41
|
+
? (props.message.flags & v10_1.MessageFlags.IsVoiceMessage) === v10_1.MessageFlags.IsVoiceMessage
|
|
42
|
+
: false;
|
|
43
|
+
return (react_1.default.createElement(discord_components_react_render_1.DiscordAttachments, { slot: "attachments" },
|
|
44
|
+
grouped.mediaGallery.length > 0 && (react_1.default.createElement(discord_components_react_render_1.DiscordMediaGallery, null, grouped.mediaGallery.map((attachment, id) => (react_1.default.createElement(Attachment, { attachment: attachment, message: props.message, context: props.context, key: id }))))),
|
|
45
|
+
grouped.other.map((attachment, id) => (react_1.default.createElement(Attachment, { attachment: attachment, message: props.message, context: props.context, key: id, isVoiceMessage: isVoiceMessage })))));
|
|
46
|
+
}
|
|
47
|
+
const programmingLanguageMimeMap = new Map([
|
|
48
|
+
['text/html', 'html'],
|
|
49
|
+
['text/css', 'css'],
|
|
50
|
+
['text/javascript', 'javascript'],
|
|
51
|
+
['application/javascript', 'javascript'],
|
|
52
|
+
['application/json', 'json'],
|
|
53
|
+
['application/xml', 'xml'],
|
|
54
|
+
['image/svg+xml', 'svg'],
|
|
55
|
+
['application/xhtml+xml', 'xhtml'],
|
|
56
|
+
['application/wasm', 'wasm'],
|
|
57
|
+
['text/markdown', 'markdown'],
|
|
58
|
+
['text/x-sass', 'sass'],
|
|
59
|
+
['text/x-scss', 'scss'],
|
|
60
|
+
['text/x-python', 'python'],
|
|
61
|
+
['application/x-python-code', 'python'],
|
|
62
|
+
['text/x-java-source', 'java'],
|
|
63
|
+
['text/x-csharp', 'csharp'],
|
|
64
|
+
['text/x-php', 'php'],
|
|
65
|
+
['application/x-php', 'php'],
|
|
66
|
+
['text/x-ruby', 'ruby'],
|
|
67
|
+
['text/x-go', 'go'],
|
|
68
|
+
['text/x-rustsrc', 'rust'],
|
|
69
|
+
['text/x-kotlin', 'kotlin'],
|
|
70
|
+
['text/x-swift', 'swift'],
|
|
71
|
+
['text/x-dart', 'dart'],
|
|
72
|
+
['text/x-lua', 'lua'],
|
|
73
|
+
['text/x-scala', 'scala'],
|
|
74
|
+
['application/sql', 'sql'],
|
|
75
|
+
['text/x-sh', 'bash'],
|
|
76
|
+
['application/x-sh', 'bash'],
|
|
77
|
+
['text/x-objectivec', 'objectivec'],
|
|
78
|
+
['text/x-perl', 'perl'],
|
|
79
|
+
['text/x-pascal', 'pascal'],
|
|
80
|
+
['text/x-dsrc', 'd'],
|
|
81
|
+
['text/x-groovy', 'groovy'],
|
|
82
|
+
['text/x-rsrc', 'r'],
|
|
83
|
+
['text/x-vb', 'vbnet'],
|
|
84
|
+
['text/x-solidity', 'solidity'],
|
|
85
|
+
['text/x-julia', 'julia'],
|
|
86
|
+
['text/x-clojure', 'clojure'],
|
|
87
|
+
['application/graphql', 'graphql'],
|
|
88
|
+
['application/x-yaml', 'yaml'],
|
|
89
|
+
['text/x-ini', 'ini'],
|
|
90
|
+
['text/plain', 'plaintext'],
|
|
91
|
+
['text/uri-list', 'uri'],
|
|
92
|
+
['application/diff', 'diff'],
|
|
93
|
+
['text/x-dockerfile', 'dockerfile'],
|
|
94
|
+
]);
|
|
95
|
+
/**
|
|
96
|
+
* Renders one Discord Attachment
|
|
97
|
+
* @param props - the attachment and rendering context
|
|
98
|
+
*/
|
|
99
|
+
async function Attachment({ attachment, context, message, isVoiceMessage, }) {
|
|
100
|
+
let url = attachment.url;
|
|
101
|
+
const type = getAttachmentType(attachment);
|
|
102
|
+
const attach = ('data' in attachment ? attachment.data : attachment);
|
|
103
|
+
if (isVoiceMessage) {
|
|
104
|
+
return react_1.default.createElement(discord_components_react_render_1.DiscordVoiceMessage, { key: attachment.id, href: attachment.url, waveform: attachment.waveform });
|
|
105
|
+
}
|
|
106
|
+
if (type === 'image' || type === 'video') {
|
|
107
|
+
// download it to a data url
|
|
108
|
+
const downloaded = await context.callbacks.resolveImageSrc(attach, message);
|
|
109
|
+
if (downloaded !== null) {
|
|
110
|
+
url = downloaded ?? url;
|
|
111
|
+
}
|
|
112
|
+
return (react_1.default.createElement(discord_components_react_render_1.DiscordMediaGalleryItem, { spoiler: (0, utils_1.hasFlag)({ bitfield: attach.flags, flag: 8 }), media: url, key: attachment.id, description: attachment.description, "mime-type": attachment.content_type, width: attachment.width ?? void 0, height: attachment.height ?? void 0 }));
|
|
113
|
+
}
|
|
114
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
|
|
115
|
+
const mime = attachment.content_type?.split(';')[0];
|
|
116
|
+
const format = programmingLanguageMimeMap.get(mime);
|
|
117
|
+
const { size, unit } = (0, utils_1.formatBytes)(attachment.size);
|
|
118
|
+
if (type === 'audio') {
|
|
119
|
+
return (react_1.default.createElement(discord_components_react_render_1.DiscordAudioAttachment, { key: attachment.id, href: url, bytes: size, "bytes-unit": unit, name: attachment.filename }));
|
|
120
|
+
}
|
|
121
|
+
if (type === 'file') {
|
|
122
|
+
if (format && size <= 1024 * 1024) {
|
|
123
|
+
const content = await fetch(attach.url)
|
|
124
|
+
.then((res) => res.text())
|
|
125
|
+
.catch(() => null);
|
|
126
|
+
if (content) {
|
|
127
|
+
return (react_1.default.createElement(discord_components_react_render_1.DiscordTextFileAttachmentPreviewer, { href: url, name: attachment.filename, language: format, bytes: size, "bytes-unit": unit, key: attachment.id, content: content }));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return (react_1.default.createElement(discord_components_react_render_1.DiscordFileAttachment, { type: type, bytes: size, "bytes-unit": unit, name: attachment.filename, key: attachment.id, href: url }));
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=attachment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachment.js","sourceRoot":"","sources":["../../../src/generator/renderers/attachment.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { APIMessageComponent } from 'discord-api-types/v10';
|
|
3
|
+
import type { RenderMessageContext } from '..';
|
|
4
|
+
export declare function Component({ component, id, context, }: {
|
|
5
|
+
component: APIMessageComponent;
|
|
6
|
+
id: number;
|
|
7
|
+
context: RenderMessageContext;
|
|
8
|
+
}): Promise<React.JSX.Element>;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.Component = Component;
|
|
40
|
+
const discord_components_react_render_1 = require("@penwin/discord-components-react-render");
|
|
41
|
+
const react_1 = __importDefault(require("react"));
|
|
42
|
+
const v10_1 = require("discord-api-types/v10");
|
|
43
|
+
const utils_1 = require("../../utils/utils");
|
|
44
|
+
const content_1 = __importStar(require("./content"));
|
|
45
|
+
const guild_1 = require("../../utils/guild");
|
|
46
|
+
const selectMenuScriptHeader = `(window.$discordSelectMenu ??= {})`;
|
|
47
|
+
const ButtonStyleMapping = {
|
|
48
|
+
[v10_1.ButtonStyle.Primary]: 'primary',
|
|
49
|
+
[v10_1.ButtonStyle.Secondary]: 'secondary',
|
|
50
|
+
[v10_1.ButtonStyle.Success]: 'success',
|
|
51
|
+
[v10_1.ButtonStyle.Danger]: 'destructive',
|
|
52
|
+
[v10_1.ButtonStyle.Link]: 'secondary',
|
|
53
|
+
[v10_1.ButtonStyle.Premium]: 'premium',
|
|
54
|
+
};
|
|
55
|
+
async function Component({ component, id, context, }) {
|
|
56
|
+
switch (component.type) {
|
|
57
|
+
case v10_1.ComponentType.Button:
|
|
58
|
+
return (react_1.default.createElement(discord_components_react_render_1.DiscordButton, { key: id, type: 'style' in component ? ButtonStyleMapping[component.style] : 'secondary', url: 'url' in component ? component.url : undefined, emoji: 'emoji' in component ? (0, utils_1.parseDiscordEmoji)(component.emoji) : undefined, disabled: component.disabled }, 'label' in component ? component.label : undefined));
|
|
59
|
+
case v10_1.ComponentType.ActionRow: {
|
|
60
|
+
return (react_1.default.createElement(discord_components_react_render_1.DiscordActionRow, { key: id }, component.components.map((component, id) => (react_1.default.createElement(Component, { component: component, id: id, key: id, context: context })))));
|
|
61
|
+
}
|
|
62
|
+
case v10_1.ComponentType.Container: {
|
|
63
|
+
return (react_1.default.createElement(discord_components_react_render_1.DiscordContainer, { key: id, spoiler: component.spoiler },
|
|
64
|
+
react_1.default.createElement(discord_components_react_render_1.DiscordComponentsColumn, null, component.components.map((component, id) => (react_1.default.createElement(Component, { component: component, id: id, key: id, context: context }))))));
|
|
65
|
+
}
|
|
66
|
+
case v10_1.ComponentType.Thumbnail: {
|
|
67
|
+
return (react_1.default.createElement(discord_components_react_render_1.DiscordThumbnail, { key: id, media: component.media.proxy_url ?? component.media.url, spoiler: component.spoiler }));
|
|
68
|
+
}
|
|
69
|
+
case v10_1.ComponentType.Section: {
|
|
70
|
+
return (react_1.default.createElement(discord_components_react_render_1.DiscordSection, { key: id },
|
|
71
|
+
react_1.default.createElement(discord_components_react_render_1.DiscordSectionComponents, null, component.components.map((component, id) => (react_1.default.createElement(Component, { component: component, id: id, key: id, context: context })))),
|
|
72
|
+
react_1.default.createElement(Component, { component: component.accessory, id: id, key: id, context: context })));
|
|
73
|
+
}
|
|
74
|
+
case v10_1.ComponentType.TextDisplay: {
|
|
75
|
+
return (react_1.default.createElement(discord_components_react_render_1.DiscordTextDisplay, { key: id },
|
|
76
|
+
react_1.default.createElement(content_1.default, { content: component.content, context: { ...context, type: content_1.RenderType.EMBED } })));
|
|
77
|
+
}
|
|
78
|
+
case v10_1.ComponentType.Separator: {
|
|
79
|
+
return react_1.default.createElement(discord_components_react_render_1.DiscordSeparator, { key: id, spacing: component.spacing, divider: component.divider });
|
|
80
|
+
}
|
|
81
|
+
case v10_1.ComponentType.File: {
|
|
82
|
+
const resolvedFileComponent = component;
|
|
83
|
+
const { size, unit } = (0, utils_1.formatBytes)(resolvedFileComponent.size);
|
|
84
|
+
return (react_1.default.createElement(discord_components_react_render_1.DiscordFileAttachment, { key: id, name: resolvedFileComponent.name, bytes: size, "bytes-unit": unit, href: component.file.proxy_url ?? component.file.url, spoiler: component.spoiler }));
|
|
85
|
+
}
|
|
86
|
+
case v10_1.ComponentType.MediaGallery: {
|
|
87
|
+
return (react_1.default.createElement(discord_components_react_render_1.DiscordMediaGallery, { key: id }, component.items.map((item, id) => (react_1.default.createElement(discord_components_react_render_1.DiscordMediaGalleryItem, { key: `${id}-${component.id}`, media: item.media.proxy_url ?? item.media.url, "mime-type": item.media.content_type, spoiler: item.spoiler, description: item.description ?? void 0, width: item.media.width ?? void 0, height: item.media.height ?? void 0 })))));
|
|
88
|
+
}
|
|
89
|
+
case v10_1.ComponentType.StringSelect:
|
|
90
|
+
case v10_1.ComponentType.SelectMenu: {
|
|
91
|
+
return (react_1.default.createElement(discord_components_react_render_1.DiscordStringSelectMenu, { disabled: component.disabled, placeholder: component.placeholder }, component.options.map((option, id) => (react_1.default.createElement(discord_components_react_render_1.DiscordStringSelectMenuOption, { key: id, label: option.label, description: option.description, emojiName: option.emoji?.name, emoji: option.emoji && (0, utils_1.parseDiscordEmoji)(option.emoji), selected: option.default })))));
|
|
92
|
+
}
|
|
93
|
+
case v10_1.ComponentType.ChannelSelect:
|
|
94
|
+
case v10_1.ComponentType.RoleSelect:
|
|
95
|
+
case v10_1.ComponentType.MentionableSelect:
|
|
96
|
+
case v10_1.ComponentType.UserSelect: {
|
|
97
|
+
const isMentionable = component.type === v10_1.ComponentType.MentionableSelect;
|
|
98
|
+
const isUser = component.type === v10_1.ComponentType.UserSelect;
|
|
99
|
+
const isRole = component.type === v10_1.ComponentType.RoleSelect;
|
|
100
|
+
const isChannel = component.type === v10_1.ComponentType.ChannelSelect;
|
|
101
|
+
const containsUsers = (isMentionable || isUser) && context.selectMenus?.includeUsers;
|
|
102
|
+
const containsRoles = isRole && context.selectMenus?.includeRoles;
|
|
103
|
+
const containsChannels = isChannel && context.selectMenus?.includeChannels;
|
|
104
|
+
const scripts = [];
|
|
105
|
+
if (containsUsers && !context.adapter.renderContext.selectMenu.users) {
|
|
106
|
+
context.adapter.renderContext.selectMenu.users = {
|
|
107
|
+
data: Object.entries(context.adapter.renderContext.profiles).map(([id, profile]) => ({
|
|
108
|
+
identifier: id,
|
|
109
|
+
discriminator: profile.discriminator,
|
|
110
|
+
avatarUrl: profile.avatar,
|
|
111
|
+
username: profile.author,
|
|
112
|
+
globalName: profile.displayName ?? profile.globalName,
|
|
113
|
+
bot: profile.bot,
|
|
114
|
+
verified: profile.verified,
|
|
115
|
+
})),
|
|
116
|
+
injectedScript: !context.hydrate,
|
|
117
|
+
};
|
|
118
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
119
|
+
!context.hydrate &&
|
|
120
|
+
scripts.push(react_1.default.createElement("script", { key: 'users-script', dangerouslySetInnerHTML: {
|
|
121
|
+
__html: `${selectMenuScriptHeader}.users = ${JSON.stringify(context.adapter.renderContext.selectMenu.users.data)}`,
|
|
122
|
+
} }));
|
|
123
|
+
}
|
|
124
|
+
if (containsRoles && !context.adapter.renderContext.selectMenu.roles && context.guild?.id) {
|
|
125
|
+
const data = [];
|
|
126
|
+
const roles = await context.adapter.resolveGuildRoles(context.guild?.id);
|
|
127
|
+
for (const role of roles) {
|
|
128
|
+
if (role.id === context.guild?.id)
|
|
129
|
+
continue;
|
|
130
|
+
data.push({
|
|
131
|
+
identifier: role.id,
|
|
132
|
+
name: role.name,
|
|
133
|
+
color: (0, utils_1.convertToHEX)(role.color),
|
|
134
|
+
iconUrl: (role.icon && guild_1.guildUtils.roleIcon(role.id, role.icon)) ?? void 0,
|
|
135
|
+
memberCount: 0,
|
|
136
|
+
showMemberCount: false,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
context.adapter.renderContext.selectMenu.roles = {
|
|
140
|
+
data,
|
|
141
|
+
injectedScript: !context.hydrate,
|
|
142
|
+
};
|
|
143
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
144
|
+
!context.hydrate &&
|
|
145
|
+
scripts.push(react_1.default.createElement("script", { key: 'roles-script', dangerouslySetInnerHTML: {
|
|
146
|
+
__html: `${selectMenuScriptHeader}.roles = ${JSON.stringify(context.adapter.renderContext.selectMenu.roles.data)}`,
|
|
147
|
+
} }));
|
|
148
|
+
}
|
|
149
|
+
if (containsChannels && !context.adapter.renderContext.selectMenu.channels && context.guild?.id) {
|
|
150
|
+
const data = [];
|
|
151
|
+
const channels = await context.adapter.resolveGuildChannels(context.guild?.id);
|
|
152
|
+
for (const channel of channels) {
|
|
153
|
+
if (data.length >= (context.selectMenus?.channelLimits ?? 25))
|
|
154
|
+
break;
|
|
155
|
+
if ('name' in channel && channel.name) {
|
|
156
|
+
data.push({
|
|
157
|
+
identifier: channel.id,
|
|
158
|
+
name: channel.name,
|
|
159
|
+
type: channel.type,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
context.adapter.renderContext.selectMenu.channels = {
|
|
164
|
+
data,
|
|
165
|
+
injectedScript: !context.hydrate,
|
|
166
|
+
};
|
|
167
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
168
|
+
!context.hydrate &&
|
|
169
|
+
scripts.push(react_1.default.createElement("script", { key: 'channels-script', dangerouslySetInnerHTML: {
|
|
170
|
+
__html: `${selectMenuScriptHeader}.channels = ${JSON.stringify(context.adapter.renderContext.selectMenu.channels.data)}`,
|
|
171
|
+
} }));
|
|
172
|
+
}
|
|
173
|
+
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
174
|
+
scripts,
|
|
175
|
+
react_1.default.createElement(discord_components_react_render_1.DiscordSelectMenuPortal, { key: id, disabled: component.disabled, placeholder: component.placeholder, type: isMentionable ? 'mentionable' : isUser ? 'user' : isRole ? 'role' : 'channel', "default-identifier": component.default_values?.[0].id, "default-type": component.default_values?.[0].type })));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=components.js.map
|