@seedcord/http 0.1.0-next.2 → 0.1.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.
@@ -1,7 +1,9 @@
1
1
  //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __exportAll = (all, no_symbols) => {
7
9
  let target = {};
@@ -31,6 +33,10 @@ var __copyProps = (to, from, except, desc) => {
31
33
  return to;
32
34
  };
33
35
  var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
36
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
37
+ value: mod,
38
+ enumerable: true
39
+ }) : target, mod));
34
40
 
35
41
  //#endregion
36
42
  let _seedcord_errors_internal = require("@seedcord/errors/internal");
@@ -54,11 +60,12 @@ function wireAllowedMentions(mentions) {
54
60
  };
55
61
  }
56
62
  function wireAttachments(files) {
57
- if (!files?.some((file) => file.description)) return null;
63
+ if (!files?.some((file) => file.description ?? file.title)) return null;
58
64
  return files.map((file, index) => ({
59
65
  id: index,
60
- ...file.name && { filename: file.name },
61
- ...file.description && { description: file.description }
66
+ filename: file.name,
67
+ ...file.description && { description: file.description },
68
+ ...file.title && { title: file.title }
62
69
  }));
63
70
  }
64
71
  function callbackData(reply, flags) {
@@ -143,9 +150,9 @@ var ReplySender = class extends _seedcord_core_internal.BaseReplySender {
143
150
  });
144
151
  }
145
152
  rawFiles(files) {
146
- return files.map((file, index) => ({
147
- name: file.name ?? `file-${index}`,
148
- data: file.attachment
153
+ return files.map((file) => ({
154
+ name: file.name,
155
+ data: file.data
149
156
  }));
150
157
  }
151
158
  createdMessage(result) {
@@ -177,6 +184,10 @@ function apiFor(rest) {
177
184
  * @typeParam Event - The repliable interaction type this handler processes
178
185
  */
179
186
  var RepliableHandler = class extends _seedcord_core.RepliableHandler {
187
+ /** @internal */
188
+ getEvent() {
189
+ return this.event;
190
+ }
180
191
  buildSender(event, core, routeId) {
181
192
  return new ReplySender({
182
193
  application_id: event.application_id,
@@ -401,7 +412,7 @@ async function handleRawFault(error, uuid, scope) {
401
412
  }
402
413
  async function handleFault(caught, scope) {
403
414
  if (caught instanceof _seedcord_core.Silence) {
404
- if (caught.reason !== void 0) logger().debug(`Silence: ${caught.reason}`);
415
+ if (caught.reason !== void 0 && (scope.core.config.errors?.logSilences ?? true)) logger().debug(`Silence: ${caught.reason}`);
405
416
  return;
406
417
  }
407
418
  const uuid = crypto.randomUUID();
@@ -475,8 +486,8 @@ async function loadHandlerCtor(match, payload, core, report) {
475
486
  }
476
487
  /**
477
488
  * Runs the pre-ack phase for a matched interaction. Loads the route's handler class, constructs it, and
478
- * runs its gates, and the sender posts any refusal. Returns the post-ack execute continuation, or null
479
- * when a gate refuses or nothing can run.
489
+ * runs its gates. The sender posts any refusal. Returns the post-ack execute continuation, or null when a
490
+ * gate refuses or nothing can run.
480
491
  */
481
492
  async function dispatchInteraction(args) {
482
493
  const { match, payload, core } = args;
@@ -1056,6 +1067,114 @@ function createSeedcord(config, manifest) {
1056
1067
  return buildEngine(core, buildRouteMaps(manifest)).handle;
1057
1068
  }
1058
1069
 
1070
+ //#endregion
1071
+ //#region src/applicationId.ts
1072
+ /**
1073
+ * Reads the bot's own application id over REST. A gateway host takes it off the logged-in client, and
1074
+ * an http host has no session to read it from.
1075
+ *
1076
+ * @internal
1077
+ */
1078
+ async function fetchApplicationId(rest) {
1079
+ try {
1080
+ return (await rest.get(discord_api_types_v10.Routes.currentApplication())).id;
1081
+ } catch (error) {
1082
+ throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.CoreApplicationUnavailable, { cause: error });
1083
+ }
1084
+ }
1085
+
1086
+ //#endregion
1087
+ //#region src/emojis/EmojiInjector.ts
1088
+ var Emoji = class {
1089
+ name;
1090
+ id;
1091
+ animated;
1092
+ constructor(name, id, animated = false) {
1093
+ this.name = name;
1094
+ this.id = id;
1095
+ this.animated = animated;
1096
+ }
1097
+ toString() {
1098
+ return `<${this.animated ? "a" : ""}:${this.name}:${this.id}>`;
1099
+ }
1100
+ };
1101
+ const emojiStorage = (0, _seedcord_core_internal.accessorStore)();
1102
+ function reasonOf(error) {
1103
+ return Error.isError(error) ? error.message : String(error);
1104
+ }
1105
+ function byName(list) {
1106
+ const map = /* @__PURE__ */ new Map();
1107
+ for (const entry of list) if (entry.name) map.set(entry.name, entry);
1108
+ return map;
1109
+ }
1110
+ /**
1111
+ * The bot's resolved emojis, keyed by {@link EmojiMap}. Filled by {@link EmojiInjector} during startup.
1112
+ * A read before that throws.
1113
+ */
1114
+ const Emojis = (0, _seedcord_core_internal.guardedAccessor)("Emojis", emojiStorage);
1115
+ /**
1116
+ * Resolves the configured emojis over REST at startup.
1117
+ *
1118
+ * @internal
1119
+ */
1120
+ var EmojiInjector = class {
1121
+ core;
1122
+ applicationId;
1123
+ logger = new _seedcord_logger.Logger("Emojis", { channel: "bot" });
1124
+ constructor(core, applicationId = () => fetchApplicationId(core.rest)) {
1125
+ this.core = core;
1126
+ this.applicationId = applicationId;
1127
+ }
1128
+ async init() {
1129
+ (0, _seedcord_core_internal.clearStore)(emojiStorage);
1130
+ const configured = this.core.config.bot.emojis;
1131
+ if (!configured || Object.keys(configured).length === 0) {
1132
+ this.logger.debug("No emojis configured, skipping emoji injection.");
1133
+ return;
1134
+ }
1135
+ const failures = [];
1136
+ const guilds = /* @__PURE__ */ new Map();
1137
+ let application;
1138
+ for (const [key, value] of Object.entries(configured)) if ((0, _seedcord_core_internal.isEmojiTuple)(value)) await this.resolveTuple(key, value, guilds, failures);
1139
+ else if (typeof value === "string") {
1140
+ application ??= await this.applicationEmojis(failures);
1141
+ this.resolve(key, value, application, failures, "the application");
1142
+ } else failures.push(` - "${key}" has an invalid value (expected a name or [name, guildId])`);
1143
+ if (failures.length > 0) throw new _seedcord_errors_internal.SeedcordError(_seedcord_errors.SeedcordErrorCode.ConfigEmojiUnresolved, [failures.length, failures.join("\n")]);
1144
+ this.logger.utils.summary("Loaded emojis", { emojis: Object.keys(emojiStorage).length });
1145
+ }
1146
+ async applicationEmojis(failures) {
1147
+ try {
1148
+ const appId = await this.applicationId();
1149
+ return byName((await this.core.rest.get(discord_api_types_v10.Routes.applicationEmojis(appId))).items);
1150
+ } catch (error) {
1151
+ failures.push(` - the application emojis could not be read (${reasonOf(error)})`);
1152
+ return /* @__PURE__ */ new Map();
1153
+ }
1154
+ }
1155
+ async resolveTuple(key, [name, guildId], guilds, failures) {
1156
+ let guild = guilds.get(guildId);
1157
+ if (!guild) {
1158
+ try {
1159
+ guild = byName(await this.core.rest.get(discord_api_types_v10.Routes.guildEmojis(guildId)));
1160
+ } catch (error) {
1161
+ failures.push(` - "${name}" for "${key}" targets guild ${guildId}, which could not be read (${reasonOf(error)})`);
1162
+ return;
1163
+ }
1164
+ guilds.set(guildId, guild);
1165
+ }
1166
+ this.resolve(key, name, guild, failures, `guild ${guildId}`);
1167
+ }
1168
+ resolve(key, name, source, failures, where) {
1169
+ const found = source.get(name);
1170
+ if (!found?.id) {
1171
+ failures.push(` - "${name}" for "${key}" was not found in ${where}`);
1172
+ return;
1173
+ }
1174
+ emojiStorage[key] = new Emoji(name, found.id, found.animated ?? false);
1175
+ }
1176
+ };
1177
+
1059
1178
  //#endregion
1060
1179
  //#region src/handlers/interaction/SlashHandler.ts
1061
1180
  /**
@@ -1236,12 +1355,12 @@ var SelectMenuHandler = class extends ComponentHandler {};
1236
1355
  * @typeParam Defs - The customId definitions this handler decodes, e.g. `[typeof ConfigId]`.
1237
1356
  */
1238
1357
  var ModalHandler = class extends ComponentHandler {
1239
- /** Rewrite the message this modal was opened from (only when a component opened it). */
1358
+ /** Rewrite the message this modal was opened from. Throws when a command opened the modal. */
1240
1359
  update(response) {
1241
1360
  this.ensureSourceMessage("update");
1242
1361
  return super.update(response);
1243
1362
  }
1244
- /** Silently acknowledge, leaving the source message untouched. */
1363
+ /** Acknowledge the submit without changing the source message. Throws when a command opened the modal. */
1245
1364
  deferUpdate() {
1246
1365
  this.ensureSourceMessage("deferUpdate");
1247
1366
  return super.deferUpdate();
@@ -1268,6 +1387,82 @@ var Subscriber = class extends _seedcord_core.Subscriber {};
1268
1387
  */
1269
1388
  var WebhookLog = class extends _seedcord_core.WebhookLog {};
1270
1389
 
1390
+ //#endregion
1391
+ //#region src/pagination/Paginator.ts
1392
+ function contextOf(interaction, core) {
1393
+ return {
1394
+ interaction,
1395
+ user: interaction.member?.user ?? interaction.user,
1396
+ guildId: interaction.guild_id ?? null,
1397
+ core
1398
+ };
1399
+ }
1400
+ /**
1401
+ * A restart-proof paginator. Each nav button's customId encodes its full target page, so clicks are
1402
+ * idempotent and survive a restart. A persistent `@ButtonRoute` on `Handler` dispatches the clicks.
1403
+ *
1404
+ * @typeParam Item - The item type, inferred from the source.
1405
+ * @typeParam Prefix - The route prefix, inferred from `config.prefix`.
1406
+ *
1407
+ * @example
1408
+ * ```ts
1409
+ * export const Bans = new Paginator({
1410
+ * prefix: 'bans',
1411
+ * source: new ArraySource((ctx) => loadBans(ctx.guildId), { perPage: 10 }),
1412
+ * renderItem: (ban) => ban.user.username
1413
+ * });
1414
+ *
1415
+ * \@ButtonRoute(Bans.cursor)
1416
+ * export class BansNav extends Bans.Handler {}
1417
+ * ```
1418
+ */
1419
+ var Paginator = class extends _seedcord_core.PaginatorBase {
1420
+ /** The nav handler base. Extend it with an empty body and decorate it, `@ButtonRoute(p.cursor)`. */
1421
+ Handler;
1422
+ constructor(config) {
1423
+ super(config);
1424
+ const loadPage = (ctx, n) => this.page(ctx, n);
1425
+ this.Handler = class Nav extends ButtonHandler {
1426
+ async execute() {
1427
+ await this.deferUpdate();
1428
+ const response = await loadPage(contextOf(this.event, this.core), this.params.page);
1429
+ await this.update(response);
1430
+ }
1431
+ };
1432
+ }
1433
+ /**
1434
+ * Render page 0 and send it through the handler's sender, which picks reply, edit, or followUp from its
1435
+ * ack state.
1436
+ *
1437
+ * @param handler - The handler starting the paginator, normally `this`.
1438
+ */
1439
+ async start(handler) {
1440
+ const interaction = handler.getEvent();
1441
+ const response = await this.page(contextOf(interaction, handler.core), 0);
1442
+ return handler.getSender().send(response, { ephemeral: this.config.ephemeral ?? false });
1443
+ }
1444
+ };
1445
+
1446
+ //#endregion
1447
+ //#region src/pagination/sources.ts
1448
+ /**
1449
+ * A source for a bounded list you can load whole. It loads the full list on every click, then slices the
1450
+ * page, so the real total is known (a real last button, "Page X of Y"). Cache inside your loader if the
1451
+ * load is expensive.
1452
+ *
1453
+ * @typeParam Item - The item type, inferred from the loader's return.
1454
+ */
1455
+ var ArraySource = class extends _seedcord_core.ArraySource {};
1456
+ /**
1457
+ * A source for a large or unknown-length set you fetch one page at a time (SQL LIMIT/OFFSET, a paged API).
1458
+ * The fetcher receives the page index and the page size and reports whether a next page exists. A cursor
1459
+ * source has no cheap total, so `totalPages` is undefined, the last button is omitted, and the indicator
1460
+ * reads "Page X".
1461
+ *
1462
+ * @typeParam Item - The item type, inferred from the fetcher's slice.
1463
+ */
1464
+ var CursorSource = class extends _seedcord_core.CursorSource {};
1465
+
1271
1466
  //#endregion
1272
1467
  //#region src/gates/Gated.ts
1273
1468
  /**
@@ -1312,9 +1507,15 @@ function Gated(...gates) {
1312
1507
  //#endregion
1313
1508
  //#region src/version.ts
1314
1509
  /** Package version */
1315
- const version = "0.1.0-next.2";
1510
+ const version = "0.1.0";
1316
1511
 
1317
1512
  //#endregion
1513
+ Object.defineProperty(exports, 'ArraySource', {
1514
+ enumerable: true,
1515
+ get: function () {
1516
+ return ArraySource;
1517
+ }
1518
+ });
1318
1519
  Object.defineProperty(exports, 'AutocompleteHandler', {
1319
1520
  enumerable: true,
1320
1521
  get: function () {
@@ -1339,6 +1540,24 @@ Object.defineProperty(exports, 'ContextMenuHandler', {
1339
1540
  return ContextMenuHandler;
1340
1541
  }
1341
1542
  });
1543
+ Object.defineProperty(exports, 'CursorSource', {
1544
+ enumerable: true,
1545
+ get: function () {
1546
+ return CursorSource;
1547
+ }
1548
+ });
1549
+ Object.defineProperty(exports, 'EmojiInjector', {
1550
+ enumerable: true,
1551
+ get: function () {
1552
+ return EmojiInjector;
1553
+ }
1554
+ });
1555
+ Object.defineProperty(exports, 'Emojis', {
1556
+ enumerable: true,
1557
+ get: function () {
1558
+ return Emojis;
1559
+ }
1560
+ });
1342
1561
  Object.defineProperty(exports, 'Gated', {
1343
1562
  enumerable: true,
1344
1563
  get: function () {
@@ -1357,6 +1576,12 @@ Object.defineProperty(exports, 'ModalHandler', {
1357
1576
  return ModalHandler;
1358
1577
  }
1359
1578
  });
1579
+ Object.defineProperty(exports, 'Paginator', {
1580
+ enumerable: true,
1581
+ get: function () {
1582
+ return Paginator;
1583
+ }
1584
+ });
1360
1585
  Object.defineProperty(exports, 'RepliableHandler', {
1361
1586
  enumerable: true,
1362
1587
  get: function () {
@@ -1399,6 +1624,12 @@ Object.defineProperty(exports, '__reExport', {
1399
1624
  return __reExport;
1400
1625
  }
1401
1626
  });
1627
+ Object.defineProperty(exports, '__toESM', {
1628
+ enumerable: true,
1629
+ get: function () {
1630
+ return __toESM;
1631
+ }
1632
+ });
1402
1633
  Object.defineProperty(exports, 'buildEngine', {
1403
1634
  enumerable: true,
1404
1635
  get: function () {
@@ -1417,10 +1648,16 @@ Object.defineProperty(exports, 'createSeedcord', {
1417
1648
  return createSeedcord;
1418
1649
  }
1419
1650
  });
1651
+ Object.defineProperty(exports, 'fetchApplicationId', {
1652
+ enumerable: true,
1653
+ get: function () {
1654
+ return fetchApplicationId;
1655
+ }
1656
+ });
1420
1657
  Object.defineProperty(exports, 'version', {
1421
1658
  enumerable: true,
1422
1659
  get: function () {
1423
1660
  return version;
1424
1661
  }
1425
1662
  });
1426
- //# sourceMappingURL=edge.index-joDL39cK.cjs.map
1663
+ //# sourceMappingURL=edge.index-CweiaQ5R.cjs.map