@fedify/relay 2.4.0-pr.934.40 → 2.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 +74 -41
- package/dist/factory.test.d.ts +2 -0
- package/dist/factory.test.js +21 -0
- package/dist/litepub.test.js +238 -29
- package/dist/mastodon.test.js +94 -25
- package/dist/mod.cjs +249 -228
- package/dist/mod.d.cts +38 -2
- package/dist/mod.d.ts +38 -2
- package/dist/mod.js +141 -126
- package/dist/{types-CZd4ApYv.js → types-Bs0cVLk6.js} +22294 -22068
- package/package.json +4 -4
package/dist/mod.cjs
CHANGED
|
@@ -18,6 +18,28 @@ function isRelayFollowerData(value) {
|
|
|
18
18
|
const obj = value;
|
|
19
19
|
return "actor" in obj && "state" in obj && typeof obj.state === "string" && (obj.state === "pending" || obj.state === "accepted");
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Parses and semantically validates follower data from storage.
|
|
23
|
+
*
|
|
24
|
+
* @param actorId The actor ID used as the follower's storage key.
|
|
25
|
+
* @param value The stored follower data.
|
|
26
|
+
* @returns The parsed follower, or `null` if the row is invalid.
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
async function parseRelayFollowerData(actorId, value) {
|
|
30
|
+
if (!isRelayFollowerData(value)) return null;
|
|
31
|
+
try {
|
|
32
|
+
const actor = await _fedify_vocab.Object.fromJsonLd(value.actor);
|
|
33
|
+
if (!(0, _fedify_vocab.isActor)(actor) || actor.id?.href !== actorId) return null;
|
|
34
|
+
return {
|
|
35
|
+
actorId,
|
|
36
|
+
actor,
|
|
37
|
+
state: value.state
|
|
38
|
+
};
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
21
43
|
//#endregion
|
|
22
44
|
//#region src/builder.ts
|
|
23
45
|
const relayBuilder = (0, _fedify_fedify.createFederationBuilder)();
|
|
@@ -78,12 +100,12 @@ relayBuilder.setActorDispatcher("/users/{identifier}", async (ctx, identifier) =
|
|
|
78
100
|
});
|
|
79
101
|
async function getFollowerActors(ctx) {
|
|
80
102
|
const actors = [];
|
|
81
|
-
for await (const { value } of ctx.data.kv.list(["follower"])) {
|
|
82
|
-
|
|
83
|
-
if (
|
|
84
|
-
const
|
|
85
|
-
if (
|
|
86
|
-
actors.push(actor);
|
|
103
|
+
for await (const { key, value } of ctx.data.kv.list(["follower"])) {
|
|
104
|
+
const actorId = key[1];
|
|
105
|
+
if (typeof actorId !== "string") continue;
|
|
106
|
+
const follower = await parseRelayFollowerData(actorId, value);
|
|
107
|
+
if (follower?.state !== "accepted") continue;
|
|
108
|
+
actors.push(follower.actor);
|
|
87
109
|
}
|
|
88
110
|
return actors;
|
|
89
111
|
}
|
|
@@ -245,7 +267,7 @@ function parseInt0(s) {
|
|
|
245
267
|
function padNumber(digits, num) {
|
|
246
268
|
return String(num).padStart(digits, "0");
|
|
247
269
|
}
|
|
248
|
-
const padNumber2 =
|
|
270
|
+
const padNumber2 = /*@__PURE__*/ bindArgs(padNumber, 2);
|
|
249
271
|
function compareNumbers(a, b) {
|
|
250
272
|
return Math.sign(a - b);
|
|
251
273
|
}
|
|
@@ -313,7 +335,7 @@ const unitNameMap = {
|
|
|
313
335
|
month: 8,
|
|
314
336
|
year: 9
|
|
315
337
|
};
|
|
316
|
-
const unitNamesAsc =
|
|
338
|
+
const unitNamesAsc = /*@__PURE__*/ Object.keys(unitNameMap);
|
|
317
339
|
const nanoInMicro = nanoInMicro$1;
|
|
318
340
|
const nanoInMilli = nanoInMilli$1;
|
|
319
341
|
const nanoInSec = nanoInSec$1;
|
|
@@ -329,19 +351,19 @@ const unitNanoMap = [
|
|
|
329
351
|
nanoInHour,
|
|
330
352
|
nanoInUtcDay
|
|
331
353
|
];
|
|
332
|
-
const bigNanoInMicro =
|
|
333
|
-
const bigNanoInMilli =
|
|
334
|
-
const bigNanoInSec =
|
|
335
|
-
const bigNanoInMinute =
|
|
336
|
-
const bigNanoInHour =
|
|
337
|
-
const bigNanoInUtcDay =
|
|
354
|
+
const bigNanoInMicro = /*@__PURE__*/ BigInt(nanoInMicro);
|
|
355
|
+
const bigNanoInMilli = /*@__PURE__*/ BigInt(nanoInMilli);
|
|
356
|
+
const bigNanoInSec = /*@__PURE__*/ BigInt(nanoInSec);
|
|
357
|
+
const bigNanoInMinute = /*@__PURE__*/ BigInt(nanoInMinute);
|
|
358
|
+
const bigNanoInHour = /*@__PURE__*/ BigInt(nanoInHour);
|
|
359
|
+
const bigNanoInUtcDay = /*@__PURE__*/ BigInt(nanoInUtcDay);
|
|
338
360
|
function divideBigNanoToExactNumber(bigNano, divisorNano) {
|
|
339
361
|
const days = Number(bigNano / bigNanoInUtcDay);
|
|
340
362
|
const timeNano = Number(bigNano % bigNanoInUtcDay);
|
|
341
363
|
return days * (nanoInUtcDay / divisorNano) + (Math.trunc(timeNano / divisorNano) + timeNano % divisorNano / divisorNano);
|
|
342
364
|
}
|
|
343
|
-
const timeFieldNamesAsc =
|
|
344
|
-
const timeGetters =
|
|
365
|
+
const timeFieldNamesAsc = /*@__PURE__*/ unitNamesAsc.slice(0, 6);
|
|
366
|
+
const timeGetters = /*@__PURE__*/ createPropGetters(timeFieldNamesAsc);
|
|
345
367
|
const yearFieldNamesAsc = ["year"];
|
|
346
368
|
const dayFieldNamesAsc = ["day"];
|
|
347
369
|
const calendarDateFieldNamesAsc = [
|
|
@@ -363,24 +385,24 @@ const monthDayFieldNames = [
|
|
|
363
385
|
"month",
|
|
364
386
|
"monthCode"
|
|
365
387
|
];
|
|
366
|
-
const timeFieldNamesAlpha =
|
|
367
|
-
const yearFieldNamesWithEraAlpha =
|
|
368
|
-
const yearMonthFieldNamesAlpha =
|
|
369
|
-
const yearMonthFieldNamesWithEraAlpha =
|
|
370
|
-
const yearMonthCodeFieldNamesAlpha =
|
|
371
|
-
const yearMonthCodeFieldNamesWithEraAlpha =
|
|
372
|
-
const monthCodeDayFieldNamesAlpha =
|
|
373
|
-
const dateFieldNamesAlpha =
|
|
374
|
-
const dateFieldNamesWithEraAlpha =
|
|
375
|
-
const dateTimeFieldNamesAlpha =
|
|
376
|
-
const dateTimeFieldNamesWithEraAlpha =
|
|
377
|
-
const dateTimeAndOffsetFieldNamesAlpha =
|
|
378
|
-
const dateTimeAndOffsetFieldNamesWithEraAlpha =
|
|
379
|
-
const dateTimeAndZoneFieldNamesAlpha =
|
|
380
|
-
const dateTimeAndZoneFieldNamesWithEraAlpha =
|
|
381
|
-
const yearMonthCodeDayFieldNamesAlpha =
|
|
382
|
-
const yearMonthCodeDayFieldNamesWithEraAlpha =
|
|
383
|
-
const timeFieldDefaults =
|
|
388
|
+
const timeFieldNamesAlpha = /*@__PURE__*/ sortStrings(timeFieldNamesAsc);
|
|
389
|
+
const yearFieldNamesWithEraAlpha = /*@__PURE__*/ sortStrings(eraYearFieldNames, yearFieldNamesAsc);
|
|
390
|
+
const yearMonthFieldNamesAlpha = /*@__PURE__*/ sortStrings(monthFieldNames, yearFieldNamesAsc);
|
|
391
|
+
const yearMonthFieldNamesWithEraAlpha = /*@__PURE__*/ sortStrings(eraYearFieldNames, yearMonthFieldNamesAlpha);
|
|
392
|
+
const yearMonthCodeFieldNamesAlpha = /*@__PURE__*/ sortStrings(["monthCode"], yearFieldNamesAsc);
|
|
393
|
+
const yearMonthCodeFieldNamesWithEraAlpha = /*@__PURE__*/ sortStrings(eraYearFieldNames, yearMonthCodeFieldNamesAlpha);
|
|
394
|
+
const monthCodeDayFieldNamesAlpha = /*@__PURE__*/ sortStrings(dayFieldNamesAsc, ["monthCode"]);
|
|
395
|
+
const dateFieldNamesAlpha = /*@__PURE__*/ sortStrings(dayFieldNamesAsc, yearMonthFieldNamesAlpha);
|
|
396
|
+
const dateFieldNamesWithEraAlpha = /*@__PURE__*/ sortStrings(dayFieldNamesAsc, eraYearFieldNames, yearMonthFieldNamesAlpha);
|
|
397
|
+
const dateTimeFieldNamesAlpha = /*@__PURE__*/ sortStrings(dateFieldNamesAlpha, timeFieldNamesAsc);
|
|
398
|
+
const dateTimeFieldNamesWithEraAlpha = /*@__PURE__*/ sortStrings(dateFieldNamesWithEraAlpha, timeFieldNamesAsc);
|
|
399
|
+
const dateTimeAndOffsetFieldNamesAlpha = /*@__PURE__*/ sortStrings(dateFieldNamesAlpha, timeFieldNamesAsc, offsetFieldNames);
|
|
400
|
+
const dateTimeAndOffsetFieldNamesWithEraAlpha = /*@__PURE__*/ sortStrings(dateFieldNamesWithEraAlpha, timeFieldNamesAsc, offsetFieldNames);
|
|
401
|
+
const dateTimeAndZoneFieldNamesAlpha = /*@__PURE__*/ sortStrings(dateFieldNamesAlpha, timeFieldNamesAsc, offsetFieldNames, timeZoneFieldNames);
|
|
402
|
+
const dateTimeAndZoneFieldNamesWithEraAlpha = /*@__PURE__*/ sortStrings(dateFieldNamesWithEraAlpha, timeFieldNamesAsc, offsetFieldNames, timeZoneFieldNames);
|
|
403
|
+
const yearMonthCodeDayFieldNamesAlpha = /*@__PURE__*/ sortStrings(dayFieldNamesAsc, yearMonthCodeFieldNamesAlpha);
|
|
404
|
+
const yearMonthCodeDayFieldNamesWithEraAlpha = /*@__PURE__*/ sortStrings(dayFieldNamesAsc, eraYearFieldNames, yearMonthCodeFieldNamesAlpha);
|
|
405
|
+
const timeFieldDefaults = /*@__PURE__*/ zipPropsConst(timeFieldNamesAsc, 0);
|
|
384
406
|
function validateTimeFields(timeFields) {
|
|
385
407
|
return constrainTimeFields(timeFields, 1), timeFields;
|
|
386
408
|
}
|
|
@@ -609,20 +631,20 @@ function computeCalendarWeekOfYear(calendar, isoDate) {
|
|
|
609
631
|
function computeCalendarYearOfWeek(calendar, isoDate) {
|
|
610
632
|
return calendar === void 0 ? computeIsoWeekFields(isoDate).yearOfWeek : void 0;
|
|
611
633
|
}
|
|
612
|
-
const durationFieldNamesAsc =
|
|
613
|
-
const durationGetters =
|
|
614
|
-
const durationFieldNamesAlpha =
|
|
615
|
-
const durationTimeFieldNamesAsc =
|
|
616
|
-
const durationDateFieldNamesAsc =
|
|
617
|
-
const durationCalendarFieldNamesAsc =
|
|
618
|
-
const durationFieldIndexes =
|
|
619
|
-
const durationFieldDefaults =
|
|
620
|
-
const durationTimeFieldDefaults =
|
|
621
|
-
const clearDurationFields =
|
|
634
|
+
const durationFieldNamesAsc = /*@__PURE__*/ unitNamesAsc.map((unitName) => unitName + "s");
|
|
635
|
+
const durationGetters = /*@__PURE__*/ createPropGetters(durationFieldNamesAsc);
|
|
636
|
+
const durationFieldNamesAlpha = /*@__PURE__*/ sortStrings(durationFieldNamesAsc);
|
|
637
|
+
const durationTimeFieldNamesAsc = /*@__PURE__*/ durationFieldNamesAsc.slice(0, 6);
|
|
638
|
+
const durationDateFieldNamesAsc = /*@__PURE__*/ durationFieldNamesAsc.slice(6);
|
|
639
|
+
const durationCalendarFieldNamesAsc = /*@__PURE__*/ durationDateFieldNamesAsc.slice(1);
|
|
640
|
+
const durationFieldIndexes = /*@__PURE__*/ durationFieldNamesAsc.reduce((indexes, fieldName, i) => (indexes[fieldName] = i, indexes), {});
|
|
641
|
+
const durationFieldDefaults = /*@__PURE__*/ zipPropsConst(durationFieldNamesAsc, 0);
|
|
642
|
+
const durationTimeFieldDefaults = /*@__PURE__*/ zipPropsConst(durationTimeFieldNamesAsc, 0);
|
|
643
|
+
const clearDurationFields = /*@__PURE__*/ bindArgs(zeroOutProps, durationFieldNamesAsc);
|
|
622
644
|
function requirePropDefined(optionName, optionVal) {
|
|
623
645
|
return optionVal ?? throwRangeError(missingField(optionName)), optionVal;
|
|
624
646
|
}
|
|
625
|
-
const requireString =
|
|
647
|
+
const requireString = /*@__PURE__*/ bindArgs(requireType, "string");
|
|
626
648
|
function requireType(typeName, arg, entityName = typeName) {
|
|
627
649
|
return typeof arg !== typeName && throwTypeError(invalidEntity(entityName, arg)), arg;
|
|
628
650
|
}
|
|
@@ -734,17 +756,17 @@ function coerceChoiceOption(optionName, enumNameMap, options, defaultChoice = 0)
|
|
|
734
756
|
const enumNum = enumNameMap[enumStr];
|
|
735
757
|
return void 0 === enumNum && throwRangeError(invalidChoice(optionName, enumStr, enumNameMap)), enumNum;
|
|
736
758
|
}
|
|
737
|
-
const coerceSmallestUnit =
|
|
738
|
-
const coerceLargestUnit =
|
|
739
|
-
const coerceTotalUnit =
|
|
740
|
-
const coerceOverflow =
|
|
741
|
-
const coerceEpochDisambig =
|
|
742
|
-
const coerceOffsetDisambig =
|
|
743
|
-
const coerceCalendarDisplay =
|
|
744
|
-
const coerceTimeZoneDisplay =
|
|
745
|
-
const coerceOffsetDisplay =
|
|
746
|
-
const coerceRoundingMode =
|
|
747
|
-
const coerceDirection =
|
|
759
|
+
const coerceSmallestUnit = /*@__PURE__*/ bindArgs(coerceUnitOption, smallestUnitStr);
|
|
760
|
+
const coerceLargestUnit = /*@__PURE__*/ bindArgs(coerceUnitOption, "largestUnit");
|
|
761
|
+
const coerceTotalUnit = /*@__PURE__*/ bindArgs(coerceUnitOption, "unit");
|
|
762
|
+
const coerceOverflow = /*@__PURE__*/ bindArgs(coerceChoiceOption, "overflow", overflowMap);
|
|
763
|
+
const coerceEpochDisambig = /*@__PURE__*/ bindArgs(coerceChoiceOption, "disambiguation", epochDisambigMap);
|
|
764
|
+
const coerceOffsetDisambig = /*@__PURE__*/ bindArgs(coerceChoiceOption, "offset", offsetDisambigMap);
|
|
765
|
+
const coerceCalendarDisplay = /*@__PURE__*/ bindArgs(coerceChoiceOption, "calendarName", calendarDisplayMap);
|
|
766
|
+
const coerceTimeZoneDisplay = /*@__PURE__*/ bindArgs(coerceChoiceOption, "timeZoneName", timeZoneDisplayMap);
|
|
767
|
+
const coerceOffsetDisplay = /*@__PURE__*/ bindArgs(coerceChoiceOption, "offset", offsetDisplayMap);
|
|
768
|
+
const coerceRoundingMode = /*@__PURE__*/ bindArgs(coerceChoiceOption, "roundingMode", roundingModeMap);
|
|
769
|
+
const coerceDirection = /*@__PURE__*/ bindArgs(coerceChoiceOption, "direction", directionMap);
|
|
748
770
|
function validateRoundingInc(roundingInc, smallestUnit, allowManyLargeUnits, solarMode) {
|
|
749
771
|
const upUnitNano = solarMode ? nanoInUtcDay : unitNanoMap[smallestUnit + 1];
|
|
750
772
|
if (upUnitNano) {
|
|
@@ -798,8 +820,8 @@ function refineZonedFieldOptions(options, defaultOffsetDisambig = 0) {
|
|
|
798
820
|
epochDisambig
|
|
799
821
|
];
|
|
800
822
|
}
|
|
801
|
-
const epochNanoMax =
|
|
802
|
-
const epochNanoMin =
|
|
823
|
+
const epochNanoMax = /*@__PURE__*/ BigInt(1e8) * bigNanoInUtcDay;
|
|
824
|
+
const epochNanoMin = /*@__PURE__*/ BigInt(-1e8) * bigNanoInUtcDay;
|
|
803
825
|
const plainDateEpochNanoMin = epochNanoMin - bigNanoInUtcDay;
|
|
804
826
|
const isoYearMonthIndexMin = -3261848;
|
|
805
827
|
function checkIsoYearMonthInBounds(isoDate) {
|
|
@@ -1070,11 +1092,12 @@ function nudgeRelativeDuration(sign, durationFields, endEpochNano, _largestUnit,
|
|
|
1070
1092
|
}
|
|
1071
1093
|
function getTimeZoneTransitionEpochNanoseconds(slots, options) {
|
|
1072
1094
|
return slots.timeZone.U(slots.epochNanoseconds, ((options) => {
|
|
1073
|
-
const
|
|
1095
|
+
const normalizedOptions = normalizeOptionsOrString(options, "direction");
|
|
1096
|
+
const res = coerceDirection(normalizedOptions, 0);
|
|
1074
1097
|
return res || throwRangeError(invalidEntity("direction", res)), res;
|
|
1075
1098
|
})(options));
|
|
1076
1099
|
}
|
|
1077
|
-
const zonedEpochSlotsToIso =
|
|
1100
|
+
const zonedEpochSlotsToIso = /*@__PURE__*/ memoize(_zonedEpochSlotsToIso, WeakMap);
|
|
1078
1101
|
function _zonedEpochSlotsToIso(slots) {
|
|
1079
1102
|
const { epochNanoseconds, timeZone } = slots;
|
|
1080
1103
|
const offsetNanoseconds = timeZone.C(epochNanoseconds);
|
|
@@ -1640,7 +1663,7 @@ function resolveTimeFields(fields, overflow) {
|
|
|
1640
1663
|
...fields
|
|
1641
1664
|
}), overflow);
|
|
1642
1665
|
}
|
|
1643
|
-
const offsetRegExp =
|
|
1666
|
+
const offsetRegExp = /*@__PURE__*/ createRegExp("([+-])(\\d{2})(?::?(\\d{2})(?::?(\\d{2})(?:[.,](\\d{1,9}))?)?)?");
|
|
1644
1667
|
function parseOffsetNano(s) {
|
|
1645
1668
|
const offsetNano = parseOffsetNanoMaybe(s);
|
|
1646
1669
|
return void 0 === offsetNano && throwRangeError(failedParse(s)), offsetNano;
|
|
@@ -1675,13 +1698,13 @@ const dateFieldRefiners = {
|
|
|
1675
1698
|
},
|
|
1676
1699
|
day: toPositiveIntegerWithTruncation
|
|
1677
1700
|
};
|
|
1678
|
-
const timeFieldRefiners =
|
|
1679
|
-
const durationFieldRefiners =
|
|
1701
|
+
const timeFieldRefiners = /*@__PURE__*/ zipPropsConst(timeFieldNamesAsc, toIntegerWithTrunc);
|
|
1702
|
+
const durationFieldRefiners = /*@__PURE__*/ zipPropsConst(durationFieldNamesAsc, toStrictInteger);
|
|
1680
1703
|
const offsetFieldRefiners = { offset(offsetString) {
|
|
1681
1704
|
return parseOffsetNano(toStringViaPrimitive(offsetString));
|
|
1682
1705
|
} };
|
|
1683
|
-
const dateTimeFieldRefiners =
|
|
1684
|
-
const zonedDateTimeFieldRefiners =
|
|
1706
|
+
const dateTimeFieldRefiners = /*@__PURE__*/ Object.assign({}, dateFieldRefiners, timeFieldRefiners);
|
|
1707
|
+
const zonedDateTimeFieldRefiners = /*@__PURE__*/ Object.assign({}, dateTimeFieldRefiners, offsetFieldRefiners);
|
|
1685
1708
|
function readAndRefineBagFields(bag, validFieldNames, fieldRefiners, requiredFieldNames, disallowEmpty = !requiredFieldNames) {
|
|
1686
1709
|
const res = {};
|
|
1687
1710
|
let anyMatching = 0;
|
|
@@ -1784,7 +1807,9 @@ const timeZonePeriodDaysByName = {
|
|
|
1784
1807
|
const minPossibleTransitionSec = -388152e4;
|
|
1785
1808
|
function refineTimeDisplayTuple(options, maxSmallestUnit = 4) {
|
|
1786
1809
|
const subsecDigits = coerceFractionalSecondDigits(options);
|
|
1787
|
-
|
|
1810
|
+
const roundingMode = coerceRoundingMode(options, 4);
|
|
1811
|
+
const smallestUnit = coerceSmallestUnit(options);
|
|
1812
|
+
return [roundingMode, ...resolveSmallestUnitAndSubsecDigits(validateUnitRange(smallestUnitStr, smallestUnit, 0, maxSmallestUnit), subsecDigits)];
|
|
1788
1813
|
}
|
|
1789
1814
|
function refineDateDisplayOptions(options) {
|
|
1790
1815
|
return coerceCalendarDisplay(normalizeOptions(options));
|
|
@@ -1959,15 +1984,17 @@ function resolveTimeZoneRecord(rawId) {
|
|
|
1959
1984
|
kind: "fixed",
|
|
1960
1985
|
...offsetRecord
|
|
1961
1986
|
};
|
|
1962
|
-
|
|
1987
|
+
const normId = "UTC" === upperRawId ? "UTC" : ((rawId) => (badCharactersRegExp.test(rawId) && throwRangeError(invalidTimeZone(rawId)), icuRegExp.test(rawId) && throwRangeError("Forbidden ICU TimeZone"), rawId.toLowerCase().split("/").map((part, partI) => (part.length <= 3 || /\d/.test(part)) && !/etc|yap/.test(part) ? part.toUpperCase() : part.replace(/baja|dumont|[a-z]+/g, (a, i) => a.length <= 2 && !partI || "in" === a || "chat" === a ? a.toUpperCase() : a.length > 2 || !i ? capitalize(a).replace(/island|noronha|murdo|rivadavia|urville/, capitalize) : a)).join("/")))(rawId);
|
|
1988
|
+
return queryNamedTimeZoneRecord(normId);
|
|
1963
1989
|
}
|
|
1964
|
-
const queryNamedTimeZoneRecord =
|
|
1990
|
+
const queryNamedTimeZoneRecord = /*@__PURE__*/ memoize((normId) => {
|
|
1965
1991
|
if ("UTC" === normId) return {
|
|
1966
1992
|
kind: "utc",
|
|
1967
1993
|
id: normId,
|
|
1968
1994
|
o: normId
|
|
1969
1995
|
};
|
|
1970
|
-
const
|
|
1996
|
+
const upperNormId = normId.toUpperCase();
|
|
1997
|
+
const format = queryTimeZoneIntlFormat(upperNormId);
|
|
1971
1998
|
return {
|
|
1972
1999
|
kind: "named",
|
|
1973
2000
|
id: normId,
|
|
@@ -1975,7 +2002,7 @@ const queryNamedTimeZoneRecord = /* @__PURE__ */ memoize((normId) => {
|
|
|
1975
2002
|
o: format.resolvedOptions().timeZone
|
|
1976
2003
|
};
|
|
1977
2004
|
});
|
|
1978
|
-
const queryTimeZoneIntlFormat =
|
|
2005
|
+
const queryTimeZoneIntlFormat = /*@__PURE__*/ memoize((upperNormId) => new RawDateTimeFormat("en-u-hc-h23", {
|
|
1979
2006
|
calendar: "iso8601",
|
|
1980
2007
|
timeZone: upperNormId,
|
|
1981
2008
|
era: "short",
|
|
@@ -1990,7 +2017,7 @@ function queryTimeZone(rawTimeZoneId) {
|
|
|
1990
2017
|
const record = resolveTimeZoneRecord(rawTimeZoneId);
|
|
1991
2018
|
return queryTimeZoneRecord(record.id, record);
|
|
1992
2019
|
}
|
|
1993
|
-
const queryTimeZoneRecord =
|
|
2020
|
+
const queryTimeZoneRecord = /*@__PURE__*/ memoize((normTimeZoneId, record) => "named" === record.kind ? new IntlTimeZone(normTimeZoneId, record.o, record.format) : new FixedTimeZone(normTimeZoneId, record.o, "fixed" === record.kind ? record._ : 0));
|
|
1994
2021
|
var FixedTimeZone = class {
|
|
1995
2022
|
constructor(id, compareKey, offsetNano) {
|
|
1996
2023
|
this.id = id, this.o = compareKey, this._ = offsetNano;
|
|
@@ -2072,7 +2099,8 @@ var IntlTimeZone = class {
|
|
|
2072
2099
|
return void 0 !== intlParts.era && "bce" === normalizeEraName(intlParts.era) ? 1 - year : year;
|
|
2073
2100
|
})(intlParts), parseInt(intlParts.month), parseInt(intlParts.day)) + 3600 * parseInt(intlParts.hour) + 60 * parseInt(intlParts.minute) + parseInt(intlParts.second) - epochSec;
|
|
2074
2101
|
})(format), ((timeZoneId) => {
|
|
2075
|
-
|
|
2102
|
+
const timeZoneName = timeZoneId.split("/").pop();
|
|
2103
|
+
return timeZonePeriodDaysByName[timeZoneName] || 60;
|
|
2076
2104
|
})(id));
|
|
2077
2105
|
}
|
|
2078
2106
|
C(epochNano) {
|
|
@@ -2296,12 +2324,12 @@ function offsetRegExpStr(separatorIndex) {
|
|
|
2296
2324
|
return "([+-])" + timeRegExpStr(separatorIndex);
|
|
2297
2325
|
}
|
|
2298
2326
|
const dateTimeRegExpStr = "(?:(?:([+-])(\\d{6}))|(\\d{4}))(-?)(\\d{2})\\4(\\d{2})(?:[T ]" + timeRegExpStr(8) + "(Z|" + offsetRegExpStr(15) + ")?)?";
|
|
2299
|
-
const yearMonthRegExp =
|
|
2300
|
-
const monthDayRegExp =
|
|
2301
|
-
const dateTimeRegExp =
|
|
2302
|
-
const timeRegExp =
|
|
2303
|
-
const annotationRegExp =
|
|
2304
|
-
const durationRegExp =
|
|
2327
|
+
const yearMonthRegExp = /*@__PURE__*/ createRegExp("(?:(?:([+-])(\\d{6}))|(\\d{4}))-?(\\d{2})((?:\\[(!?)([^\\]]*)\\]){0,9})");
|
|
2328
|
+
const monthDayRegExp = /*@__PURE__*/ createRegExp("(?:--)?(\\d{2})-?(\\d{2})((?:\\[(!?)([^\\]]*)\\]){0,9})");
|
|
2329
|
+
const dateTimeRegExp = /*@__PURE__*/ createRegExp(dateTimeRegExpStr + "((?:\\[(!?)([^\\]]*)\\]){0,9})");
|
|
2330
|
+
const timeRegExp = /*@__PURE__*/ createRegExp("T?" + timeRegExpStr(2) + `(${offsetRegExpStr(9)})?((?:\\[(!?)([^\\]]*)\\]){0,9})`);
|
|
2331
|
+
const annotationRegExp = /*@__PURE__*/ new RegExp("\\[(!?)([^\\]]*)\\]", "g");
|
|
2332
|
+
const durationRegExp = /*@__PURE__*/ createRegExp("([+-])?P(\\d+Y)?(\\d+M)?(\\d+W)?(\\d+D)?(?:T(?:(\\d+)(?:[.,](\\d{1,9}))?H)?(?:(\\d+)(?:[.,](\\d{1,9}))?M)?(?:(\\d+)(?:[.,](\\d{1,9}))?S)?)?");
|
|
2305
2333
|
function parseDateTimeLike(s) {
|
|
2306
2334
|
const parts = dateTimeRegExp.exec(s);
|
|
2307
2335
|
return parts ? ((parts) => {
|
|
@@ -2579,8 +2607,8 @@ const timeDefaultShapeFields = {
|
|
|
2579
2607
|
minute: "numeric",
|
|
2580
2608
|
second: "numeric"
|
|
2581
2609
|
};
|
|
2582
|
-
const dateTimeDefaultShapeFields =
|
|
2583
|
-
const zonedDateTimeDefaultShapeFields =
|
|
2610
|
+
const dateTimeDefaultShapeFields = /*@__PURE__*/ Object.assign({}, dateDefaultShapeFields, timeDefaultShapeFields);
|
|
2611
|
+
const zonedDateTimeDefaultShapeFields = /*@__PURE__*/ Object.assign({}, dateTimeDefaultShapeFields, { timeZoneName: "short" });
|
|
2584
2612
|
const yearMonthDefaultShapeFields = {
|
|
2585
2613
|
year: "numeric",
|
|
2586
2614
|
month: "numeric"
|
|
@@ -2604,15 +2632,15 @@ const timeShapeFieldNames = [
|
|
|
2604
2632
|
"fractionalSecondDigits",
|
|
2605
2633
|
"timeStyle"
|
|
2606
2634
|
];
|
|
2607
|
-
const dateTimeShapeFieldNames =
|
|
2608
|
-
const yearMonthIgnoredFieldNames =
|
|
2609
|
-
const monthDayIgnoredFieldNames =
|
|
2610
|
-
const transformInstantOptions =
|
|
2611
|
-
const transformZonedOptions =
|
|
2612
|
-
const transformDateTimeOptions =
|
|
2613
|
-
const transformDateOptions =
|
|
2614
|
-
const transformTimeOptions =
|
|
2615
|
-
const transformYearMonthOptions =
|
|
2635
|
+
const dateTimeShapeFieldNames = /*@__PURE__*/ dateShapeFieldNames.concat(timeShapeFieldNames);
|
|
2636
|
+
const yearMonthIgnoredFieldNames = /*@__PURE__*/ ["weekday", "day"].concat(timeShapeFieldNames);
|
|
2637
|
+
const monthDayIgnoredFieldNames = /*@__PURE__*/ ["weekday", "year"].concat(timeShapeFieldNames);
|
|
2638
|
+
const transformInstantOptions = /*@__PURE__*/ createOptionsTransformer(dateTimeShapeFieldNames, [], [], dateTimeDefaultShapeFields);
|
|
2639
|
+
const transformZonedOptions = /*@__PURE__*/ createOptionsTransformer(dateTimeShapeFieldNames, [], [], zonedDateTimeDefaultShapeFields);
|
|
2640
|
+
const transformDateTimeOptions = /*@__PURE__*/ createOptionsTransformer(dateTimeShapeFieldNames, [], ["timeZoneName"], dateTimeDefaultShapeFields);
|
|
2641
|
+
const transformDateOptions = /*@__PURE__*/ createOptionsTransformer(dateShapeFieldNames, timeShapeFieldNames, ["timeZoneName"], dateDefaultShapeFields);
|
|
2642
|
+
const transformTimeOptions = /*@__PURE__*/ createOptionsTransformer(timeShapeFieldNames, dateShapeFieldNames, ["timeZoneName", "era"], timeDefaultShapeFields);
|
|
2643
|
+
const transformYearMonthOptions = /*@__PURE__*/ createOptionsTransformer([
|
|
2616
2644
|
"year",
|
|
2617
2645
|
"month",
|
|
2618
2646
|
"dateStyle"
|
|
@@ -2634,7 +2662,7 @@ const transformYearMonthOptions = /* @__PURE__ */ createOptionsTransformer([
|
|
|
2634
2662
|
month: "numeric"
|
|
2635
2663
|
}
|
|
2636
2664
|
});
|
|
2637
|
-
const transformMonthDayOptions =
|
|
2665
|
+
const transformMonthDayOptions = /*@__PURE__*/ createOptionsTransformer([
|
|
2638
2666
|
"month",
|
|
2639
2667
|
"day",
|
|
2640
2668
|
"dateStyle"
|
|
@@ -2808,8 +2836,8 @@ function resolveBasicCalendarId(rawCalendarId) {
|
|
|
2808
2836
|
function resolveBasicCalendarArg(rawCalendarId = isoCalendarId) {
|
|
2809
2837
|
return resolveBasicCalendarId(rawCalendarId);
|
|
2810
2838
|
}
|
|
2811
|
-
const zonedDateTimeSlotsMap =
|
|
2812
|
-
const ZonedDateTime =
|
|
2839
|
+
const zonedDateTimeSlotsMap = /*@__PURE__*/ new WeakMap();
|
|
2840
|
+
const ZonedDateTime = /*@__PURE__*/ defineTemporalClass(ZonedDateTimeBranding, class {
|
|
2813
2841
|
constructor(epochNanoseconds, timeZoneId, calendar = void 0) {
|
|
2814
2842
|
const epochNano = checkEpochNanoInBounds(toBigInt(epochNanoseconds));
|
|
2815
2843
|
const timeZone = queryTimeZone(refineTimeZoneId(timeZoneId));
|
|
@@ -2957,8 +2985,8 @@ function refineTimeZoneArg(arg) {
|
|
|
2957
2985
|
}
|
|
2958
2986
|
return ((arg) => resolveTimeZoneId(parseTimeZoneId(requireString(arg))))(arg);
|
|
2959
2987
|
}
|
|
2960
|
-
const instantSlotsMap =
|
|
2961
|
-
const Instant =
|
|
2988
|
+
const instantSlotsMap = /*@__PURE__*/ new WeakMap();
|
|
2989
|
+
const Instant = /*@__PURE__*/ defineTemporalClass(InstantBranding, class {
|
|
2962
2990
|
constructor(epochNanoseconds) {
|
|
2963
2991
|
const epochNano = checkEpochNanoInBounds(toBigInt(epochNanoseconds));
|
|
2964
2992
|
initInstant(this, createEpochNanoSlots(epochNano));
|
|
@@ -3043,8 +3071,8 @@ const { toTemporalInstant: toTemporalInstant$1 } = { toTemporalInstant() {
|
|
|
3043
3071
|
function initInstant(instance, slots) {
|
|
3044
3072
|
return instantSlotsMap.set(instance, slots), attachDebugString(instance), instance;
|
|
3045
3073
|
}
|
|
3046
|
-
const plainMonthDaySlotsMap =
|
|
3047
|
-
const PlainMonthDay =
|
|
3074
|
+
const plainMonthDaySlotsMap = /*@__PURE__*/ new WeakMap();
|
|
3075
|
+
const PlainMonthDay = /*@__PURE__*/ defineTemporalClass(PlainMonthDayBranding, class {
|
|
3048
3076
|
constructor(isoMonth, isoDay, calendar = void 0, referenceIsoYear) {
|
|
3049
3077
|
const isoMonthInt = toIntegerWithTrunc(isoMonth);
|
|
3050
3078
|
const isoDayInt = toIntegerWithTrunc(isoDay);
|
|
@@ -3108,8 +3136,8 @@ function toPlainMonthDaySlots(arg, options) {
|
|
|
3108
3136
|
function initPlainMonthDay(instance, slots) {
|
|
3109
3137
|
return plainMonthDaySlotsMap.set(instance, slots), attachDebugString(instance), instance;
|
|
3110
3138
|
}
|
|
3111
|
-
const plainYearMonthSlotsMap =
|
|
3112
|
-
const PlainYearMonth =
|
|
3139
|
+
const plainYearMonthSlotsMap = /*@__PURE__*/ new WeakMap();
|
|
3140
|
+
const PlainYearMonth = /*@__PURE__*/ defineTemporalClass(PlainYearMonthBranding, class {
|
|
3113
3141
|
constructor(isoYear, isoMonth, calendar = void 0, referenceIsoDay) {
|
|
3114
3142
|
const isoYearInt = toIntegerWithTrunc(isoYear);
|
|
3115
3143
|
const isoMonthInt = toIntegerWithTrunc(isoMonth);
|
|
@@ -3201,8 +3229,8 @@ function getTemporalBrandingAndSlots(obj) {
|
|
|
3201
3229
|
function validateBag(bag) {
|
|
3202
3230
|
return (getTemporalBrandingAndSlots(bag) || void 0 !== bag.calendar || void 0 !== bag.timeZone) && throwTypeError("Invalid bag"), bag;
|
|
3203
3231
|
}
|
|
3204
|
-
const plainTimeSlotsMap =
|
|
3205
|
-
const PlainTime =
|
|
3232
|
+
const plainTimeSlotsMap = /*@__PURE__*/ new WeakMap();
|
|
3233
|
+
const PlainTime = /*@__PURE__*/ defineTemporalClass(PlainTimeBranding, class {
|
|
3206
3234
|
constructor(hour = 0, minute = 0, second = 0, millisecond = 0, microsecond = 0, nanosecond = 0) {
|
|
3207
3235
|
const fields = validateTimeFields(mapProps(toIntegerWithTrunc, {
|
|
3208
3236
|
hour,
|
|
@@ -3284,8 +3312,8 @@ function optionalToPlainTimeFields(timeArg) {
|
|
|
3284
3312
|
function initPlainTime(instance, slots) {
|
|
3285
3313
|
return plainTimeSlotsMap.set(instance, slots), attachDebugString(instance), instance;
|
|
3286
3314
|
}
|
|
3287
|
-
const plainDateTimeSlotsMap =
|
|
3288
|
-
const PlainDateTime =
|
|
3315
|
+
const plainDateTimeSlotsMap = /*@__PURE__*/ new WeakMap();
|
|
3316
|
+
const PlainDateTime = /*@__PURE__*/ defineTemporalClass(PlainDateTimeBranding, class {
|
|
3289
3317
|
constructor(isoYear, isoMonth, isoDay, hour = 0, minute = 0, second = 0, millisecond = 0, microsecond = 0, nanosecond = 0, calendar = void 0) {
|
|
3290
3318
|
const fields = checkIsoDateTimeInBounds(validateIsoDateTimeFields(mapProps(toIntegerWithTrunc, {
|
|
3291
3319
|
year: isoYear,
|
|
@@ -3396,8 +3424,8 @@ function toPlainDateTimeSlots(arg, options) {
|
|
|
3396
3424
|
function initPlainDateTime(instance, slots) {
|
|
3397
3425
|
return plainDateTimeSlotsMap.set(instance, slots), attachDebugString(instance), instance;
|
|
3398
3426
|
}
|
|
3399
|
-
const plainDateSlotsMap =
|
|
3400
|
-
const PlainDate =
|
|
3427
|
+
const plainDateSlotsMap = /*@__PURE__*/ new WeakMap();
|
|
3428
|
+
const PlainDate = /*@__PURE__*/ defineTemporalClass(PlainDateBranding, class {
|
|
3401
3429
|
constructor(isoYear, isoMonth, isoDay, calendar = void 0) {
|
|
3402
3430
|
const fields = checkIsoDateInBounds(validateIsoDateFields(mapProps(toIntegerWithTrunc, {
|
|
3403
3431
|
year: isoYear,
|
|
@@ -3515,8 +3543,8 @@ function refineCalendarArg(arg) {
|
|
|
3515
3543
|
}
|
|
3516
3544
|
return ((arg) => resolveBasicCalendarId(parseCalendarId(requireString(arg))))(arg);
|
|
3517
3545
|
}
|
|
3518
|
-
const durationSlotsMap =
|
|
3519
|
-
const Duration =
|
|
3546
|
+
const durationSlotsMap = /*@__PURE__*/ new WeakMap();
|
|
3547
|
+
const Duration = /*@__PURE__*/ defineTemporalClass(DurationBranding, class {
|
|
3520
3548
|
constructor(years = 0, months = 0, weeks = 0, days = 0, hours = 0, minutes = 0, seconds = 0, milliseconds = 0, microseconds = 0, nanoseconds = 0) {
|
|
3521
3549
|
const fields = validateDurationFields(mapProps(toStrictInteger, {
|
|
3522
3550
|
years,
|
|
@@ -3609,7 +3637,7 @@ function refinePublicRelativeTo(relativeTo) {
|
|
|
3609
3637
|
function initDuration(instance, slots) {
|
|
3610
3638
|
return durationSlotsMap.set(instance, slots), attachDebugString(instance), instance;
|
|
3611
3639
|
}
|
|
3612
|
-
const Now =
|
|
3640
|
+
const Now = /*@__PURE__*/ Object.defineProperties({}, {
|
|
3613
3641
|
...createStringTagDescriptors("Temporal.Now"),
|
|
3614
3642
|
...createPropDescriptors({
|
|
3615
3643
|
timeZoneId() {
|
|
@@ -3633,7 +3661,7 @@ const Now = /* @__PURE__ */ Object.defineProperties({}, {
|
|
|
3633
3661
|
}
|
|
3634
3662
|
})
|
|
3635
3663
|
});
|
|
3636
|
-
const Temporal$2 =
|
|
3664
|
+
const Temporal$2 = /*@__PURE__*/ Object.defineProperties({}, {
|
|
3637
3665
|
...createStringTagDescriptors("Temporal"),
|
|
3638
3666
|
...createPropDescriptors({
|
|
3639
3667
|
PlainYearMonth,
|
|
@@ -3652,6 +3680,64 @@ const Temporal$2 = /* @__PURE__ */ Object.defineProperties({}, {
|
|
|
3652
3680
|
const Temporal$1 = NativeTemporal || Temporal$2;
|
|
3653
3681
|
NativeTemporal && Date.prototype.toTemporalInstant;
|
|
3654
3682
|
//#endregion
|
|
3683
|
+
//#region src/follow.ts
|
|
3684
|
+
/**
|
|
3685
|
+
* Validate Follow activity and return follower actor if valid.
|
|
3686
|
+
* This validation is common to both Mastodon and LitePub relay protocols.
|
|
3687
|
+
*
|
|
3688
|
+
* @param ctx The federation context
|
|
3689
|
+
* @param follow The Follow activity to validate
|
|
3690
|
+
* @returns The follower Actor if valid, null otherwise
|
|
3691
|
+
*/
|
|
3692
|
+
async function validateFollowActivity(ctx, follow) {
|
|
3693
|
+
if (follow.id == null || follow.objectId == null) return null;
|
|
3694
|
+
const parsed = ctx.parseUri(follow.objectId);
|
|
3695
|
+
if (!(follow.objectId.href === "https://www.w3.org/ns/activitystreams#Public") && parsed?.type !== "actor") return null;
|
|
3696
|
+
const follower = await follow.getActor(ctx);
|
|
3697
|
+
if (follower == null || follower.id == null || follower.preferredUsername == null || follower.inboxId == null) return null;
|
|
3698
|
+
return follower;
|
|
3699
|
+
}
|
|
3700
|
+
/**
|
|
3701
|
+
* Send Accept or Reject response for a Follow activity.
|
|
3702
|
+
* This is common to both Mastodon and LitePub relay protocols.
|
|
3703
|
+
*
|
|
3704
|
+
* @param ctx The federation context
|
|
3705
|
+
* @param follow The Follow activity being responded to
|
|
3706
|
+
* @param follower The actor who sent the Follow
|
|
3707
|
+
* @param approved Whether the follow was approved
|
|
3708
|
+
*/
|
|
3709
|
+
async function sendFollowResponse(ctx, follow, follower, approved) {
|
|
3710
|
+
const relayActorUri = ctx.getActorUri(RELAY_SERVER_ACTOR);
|
|
3711
|
+
const Activity = approved ? _fedify_vocab.Accept : _fedify_vocab.Reject;
|
|
3712
|
+
const action = approved ? "accepts" : "rejects";
|
|
3713
|
+
await ctx.sendActivity({ identifier: RELAY_SERVER_ACTOR }, follower, new Activity({
|
|
3714
|
+
id: new URL(`#${action}`, relayActorUri),
|
|
3715
|
+
actor: relayActorUri,
|
|
3716
|
+
object: follow
|
|
3717
|
+
}));
|
|
3718
|
+
}
|
|
3719
|
+
/**
|
|
3720
|
+
* Handle Undo activity for Follow.
|
|
3721
|
+
* This logic is identical for both Mastodon and LitePub relay protocols.
|
|
3722
|
+
*
|
|
3723
|
+
* @param ctx The federation context
|
|
3724
|
+
* @param undo The Undo activity to handle
|
|
3725
|
+
* @param logger The logger instance to use for warnings
|
|
3726
|
+
*/
|
|
3727
|
+
async function handleUndoFollow(ctx, undo, logger) {
|
|
3728
|
+
const activity = await undo.getObject({
|
|
3729
|
+
crossOrigin: "trust",
|
|
3730
|
+
...ctx
|
|
3731
|
+
});
|
|
3732
|
+
if (activity instanceof _fedify_vocab.Follow) {
|
|
3733
|
+
if (activity.id == null || activity.actorId == null) return;
|
|
3734
|
+
await ctx.data.kv.delete(["follower", activity.actorId.href]);
|
|
3735
|
+
} else logger.warn("Unsupported object type ({type}) for Undo activity: {object}", {
|
|
3736
|
+
type: activity?.constructor.name,
|
|
3737
|
+
object: activity
|
|
3738
|
+
});
|
|
3739
|
+
}
|
|
3740
|
+
//#endregion
|
|
3655
3741
|
//#region src/base.ts
|
|
3656
3742
|
/**
|
|
3657
3743
|
* Abstract base class for relay implementations.
|
|
@@ -3671,25 +3757,6 @@ var BaseRelay = class {
|
|
|
3671
3757
|
return await (await this.#getFederation()).fetch(request, { contextData: this.options });
|
|
3672
3758
|
}
|
|
3673
3759
|
/**
|
|
3674
|
-
* Helper method to parse and validate follower data from storage.
|
|
3675
|
-
* Deserializes JSON-LD actor data and validates it.
|
|
3676
|
-
*
|
|
3677
|
-
* @param actorId The actor ID of the follower
|
|
3678
|
-
* @param data Raw data from KV store
|
|
3679
|
-
* @returns RelayFollower object if valid, null otherwise
|
|
3680
|
-
* @internal
|
|
3681
|
-
*/
|
|
3682
|
-
async parseFollowerData(actorId, data) {
|
|
3683
|
-
if (!isRelayFollowerData(data)) return null;
|
|
3684
|
-
const actor = await _fedify_vocab.Object.fromJsonLd(data.actor);
|
|
3685
|
-
if (!(0, _fedify_vocab.isActor)(actor)) return null;
|
|
3686
|
-
return {
|
|
3687
|
-
actorId,
|
|
3688
|
-
actor,
|
|
3689
|
-
state: data.state
|
|
3690
|
-
};
|
|
3691
|
-
}
|
|
3692
|
-
/**
|
|
3693
3760
|
* Lists all followers of the relay.
|
|
3694
3761
|
*
|
|
3695
3762
|
* @returns An async iterator of follower entries
|
|
@@ -3718,7 +3785,7 @@ var BaseRelay = class {
|
|
|
3718
3785
|
for await (const entry of this.options.kv.list(["follower"])) {
|
|
3719
3786
|
const actorId = entry.key[1];
|
|
3720
3787
|
if (typeof actorId !== "string") continue;
|
|
3721
|
-
const follower = await
|
|
3788
|
+
const follower = await parseRelayFollowerData(actorId, entry.value);
|
|
3722
3789
|
if (follower) yield follower;
|
|
3723
3790
|
}
|
|
3724
3791
|
}
|
|
@@ -3751,8 +3818,35 @@ var BaseRelay = class {
|
|
|
3751
3818
|
* @since 2.0.0
|
|
3752
3819
|
*/
|
|
3753
3820
|
async getFollower(actorId) {
|
|
3754
|
-
|
|
3755
|
-
|
|
3821
|
+
return await parseRelayFollowerData(actorId, await this.options.kv.get(["follower", actorId]));
|
|
3822
|
+
}
|
|
3823
|
+
shouldSkipFollow(_ctx, _follower) {
|
|
3824
|
+
return Promise.resolve(false);
|
|
3825
|
+
}
|
|
3826
|
+
afterFollowApproved(_ctx, _follower) {
|
|
3827
|
+
return Promise.resolve();
|
|
3828
|
+
}
|
|
3829
|
+
async #handleFollow(ctx, follow) {
|
|
3830
|
+
const follower = await validateFollowActivity(ctx, follow);
|
|
3831
|
+
if (follower?.id == null || await this.shouldSkipFollow(ctx, follower)) return;
|
|
3832
|
+
const approved = await this.options.subscriptionHandler(ctx, follower);
|
|
3833
|
+
if (approved) await ctx.data.kv.set(["follower", follower.id.href], {
|
|
3834
|
+
actor: await follower.toJsonLd(),
|
|
3835
|
+
state: this.initialFollowerState
|
|
3836
|
+
});
|
|
3837
|
+
await sendFollowResponse(ctx, follow, follower, approved);
|
|
3838
|
+
if (approved) await this.afterFollowApproved(ctx, follower);
|
|
3839
|
+
}
|
|
3840
|
+
async #relayActivity(ctx, activity) {
|
|
3841
|
+
const senderId = activity.actorId;
|
|
3842
|
+
const excludeBaseUris = senderId == null ? [] : [senderId];
|
|
3843
|
+
await this.deliverActivity(ctx, activity, excludeBaseUris);
|
|
3844
|
+
}
|
|
3845
|
+
setupInboxListeners() {
|
|
3846
|
+
if (this.federation == null) throw new Error("Federation must be initialized before inbox listeners");
|
|
3847
|
+
const listeners = this.federation.setInboxListeners("/users/{identifier}/inbox", "/inbox");
|
|
3848
|
+
listeners.on(_fedify_vocab.Follow, async (ctx, follow) => await this.#handleFollow(ctx, follow)).on(_fedify_vocab.Undo, async (ctx, undo) => await handleUndoFollow(ctx, undo, this.logger)).on(_fedify_vocab.Create, async (ctx, create) => await this.#relayActivity(ctx, create)).on(_fedify_vocab.Delete, async (ctx, deleteActivity) => await this.#relayActivity(ctx, deleteActivity)).on(_fedify_vocab.Move, async (ctx, move) => await this.#relayActivity(ctx, move)).on(_fedify_vocab.Update, async (ctx, update) => await this.#relayActivity(ctx, update)).on(_fedify_vocab.Announce, async (ctx, announce) => await this.#relayActivity(ctx, announce));
|
|
3849
|
+
return listeners;
|
|
3756
3850
|
}
|
|
3757
3851
|
async #getFederation() {
|
|
3758
3852
|
if (this.federation == null) {
|
|
@@ -3772,64 +3866,6 @@ var BaseRelay = class {
|
|
|
3772
3866
|
}
|
|
3773
3867
|
};
|
|
3774
3868
|
//#endregion
|
|
3775
|
-
//#region src/follow.ts
|
|
3776
|
-
/**
|
|
3777
|
-
* Validate Follow activity and return follower actor if valid.
|
|
3778
|
-
* This validation is common to both Mastodon and LitePub relay protocols.
|
|
3779
|
-
*
|
|
3780
|
-
* @param ctx The federation context
|
|
3781
|
-
* @param follow The Follow activity to validate
|
|
3782
|
-
* @returns The follower Actor if valid, null otherwise
|
|
3783
|
-
*/
|
|
3784
|
-
async function validateFollowActivity(ctx, follow) {
|
|
3785
|
-
if (follow.id == null || follow.objectId == null) return null;
|
|
3786
|
-
const parsed = ctx.parseUri(follow.objectId);
|
|
3787
|
-
if (!(follow.objectId.href === "https://www.w3.org/ns/activitystreams#Public") && parsed?.type !== "actor") return null;
|
|
3788
|
-
const follower = await follow.getActor(ctx);
|
|
3789
|
-
if (follower == null || follower.id == null || follower.preferredUsername == null || follower.inboxId == null) return null;
|
|
3790
|
-
return follower;
|
|
3791
|
-
}
|
|
3792
|
-
/**
|
|
3793
|
-
* Send Accept or Reject response for a Follow activity.
|
|
3794
|
-
* This is common to both Mastodon and LitePub relay protocols.
|
|
3795
|
-
*
|
|
3796
|
-
* @param ctx The federation context
|
|
3797
|
-
* @param follow The Follow activity being responded to
|
|
3798
|
-
* @param follower The actor who sent the Follow
|
|
3799
|
-
* @param approved Whether the follow was approved
|
|
3800
|
-
*/
|
|
3801
|
-
async function sendFollowResponse(ctx, follow, follower, approved) {
|
|
3802
|
-
const relayActorUri = ctx.getActorUri(RELAY_SERVER_ACTOR);
|
|
3803
|
-
const Activity = approved ? _fedify_vocab.Accept : _fedify_vocab.Reject;
|
|
3804
|
-
const action = approved ? "accepts" : "rejects";
|
|
3805
|
-
await ctx.sendActivity({ identifier: RELAY_SERVER_ACTOR }, follower, new Activity({
|
|
3806
|
-
id: new URL(`#${action}`, relayActorUri),
|
|
3807
|
-
actor: relayActorUri,
|
|
3808
|
-
object: follow
|
|
3809
|
-
}));
|
|
3810
|
-
}
|
|
3811
|
-
/**
|
|
3812
|
-
* Handle Undo activity for Follow.
|
|
3813
|
-
* This logic is identical for both Mastodon and LitePub relay protocols.
|
|
3814
|
-
*
|
|
3815
|
-
* @param ctx The federation context
|
|
3816
|
-
* @param undo The Undo activity to handle
|
|
3817
|
-
* @param logger The logger instance to use for warnings
|
|
3818
|
-
*/
|
|
3819
|
-
async function handleUndoFollow(ctx, undo, logger) {
|
|
3820
|
-
const activity = await undo.getObject({
|
|
3821
|
-
crossOrigin: "trust",
|
|
3822
|
-
...ctx
|
|
3823
|
-
});
|
|
3824
|
-
if (activity instanceof _fedify_vocab.Follow) {
|
|
3825
|
-
if (activity.id == null || activity.actorId == null) return;
|
|
3826
|
-
await ctx.data.kv.delete(["follower", activity.actorId.href]);
|
|
3827
|
-
} else logger.warn("Unsupported object type ({type}) for Undo activity: {object}", {
|
|
3828
|
-
type: activity?.constructor.name,
|
|
3829
|
-
object: activity
|
|
3830
|
-
});
|
|
3831
|
-
}
|
|
3832
|
-
//#endregion
|
|
3833
3869
|
//#region src/litepub.ts
|
|
3834
3870
|
const Temporal = Temporal$1;
|
|
3835
3871
|
const logger$1 = (0, _logtape_logtape.getLogger)([
|
|
@@ -3845,9 +3881,23 @@ const logger$1 = (0, _logtape_logtape.getLogger)([
|
|
|
3845
3881
|
* @since 2.0.0
|
|
3846
3882
|
*/
|
|
3847
3883
|
var LitePubRelay = class extends BaseRelay {
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3884
|
+
initialFollowerState = "pending";
|
|
3885
|
+
logger = logger$1;
|
|
3886
|
+
async shouldSkipFollow(ctx, follower) {
|
|
3887
|
+
if (follower.id == null) return true;
|
|
3888
|
+
const existingFollow = await ctx.data.kv.get(["follower", follower.id.href]);
|
|
3889
|
+
return await parseRelayFollowerData(follower.id.href, existingFollow) != null;
|
|
3890
|
+
}
|
|
3891
|
+
async afterFollowApproved(ctx, follower) {
|
|
3892
|
+
if (follower.id == null) return;
|
|
3893
|
+
const relayActorUri = ctx.getActorUri(RELAY_SERVER_ACTOR);
|
|
3894
|
+
await ctx.sendActivity({ identifier: RELAY_SERVER_ACTOR }, follower, new _fedify_vocab.Follow({
|
|
3895
|
+
actor: relayActorUri,
|
|
3896
|
+
object: follower.id,
|
|
3897
|
+
to: follower.id
|
|
3898
|
+
}));
|
|
3899
|
+
}
|
|
3900
|
+
async deliverActivity(ctx, activity, excludeBaseUris) {
|
|
3851
3901
|
const announce = new _fedify_vocab.Announce({
|
|
3852
3902
|
id: new URL(`/announce#${crypto.randomUUID()}`, ctx.origin),
|
|
3853
3903
|
actor: ctx.getActorUri(RELAY_SERVER_ACTOR),
|
|
@@ -3861,25 +3911,7 @@ var LitePubRelay = class extends BaseRelay {
|
|
|
3861
3911
|
});
|
|
3862
3912
|
}
|
|
3863
3913
|
setupInboxListeners() {
|
|
3864
|
-
|
|
3865
|
-
const follower = await validateFollowActivity(ctx, follow);
|
|
3866
|
-
if (!follower || !follower.id) return;
|
|
3867
|
-
if ((await ctx.data.kv.get(["follower", follower.id.href]))?.state === "pending") return;
|
|
3868
|
-
const approved = await this.options.subscriptionHandler(ctx, follower);
|
|
3869
|
-
if (approved) {
|
|
3870
|
-
await ctx.data.kv.set(["follower", follower.id.href], {
|
|
3871
|
-
actor: await follower.toJsonLd(),
|
|
3872
|
-
state: "pending"
|
|
3873
|
-
});
|
|
3874
|
-
await sendFollowResponse(ctx, follow, follower, approved);
|
|
3875
|
-
const relayActorUri = ctx.getActorUri(RELAY_SERVER_ACTOR);
|
|
3876
|
-
await ctx.sendActivity({ identifier: RELAY_SERVER_ACTOR }, follower, new _fedify_vocab.Follow({
|
|
3877
|
-
actor: relayActorUri,
|
|
3878
|
-
object: follower.id,
|
|
3879
|
-
to: follower.id
|
|
3880
|
-
}));
|
|
3881
|
-
} else await sendFollowResponse(ctx, follow, follower, approved);
|
|
3882
|
-
}).on(_fedify_vocab.Accept, async (ctx, accept) => {
|
|
3914
|
+
return super.setupInboxListeners().on(_fedify_vocab.Accept, async (ctx, accept) => {
|
|
3883
3915
|
const follow = await accept.getObject({
|
|
3884
3916
|
crossOrigin: "trust",
|
|
3885
3917
|
...ctx
|
|
@@ -3887,18 +3919,19 @@ var LitePubRelay = class extends BaseRelay {
|
|
|
3887
3919
|
if (!(follow instanceof _fedify_vocab.Follow)) return;
|
|
3888
3920
|
const relayActorId = follow.actorId;
|
|
3889
3921
|
if (relayActorId == null) return;
|
|
3890
|
-
const followerActor = await accept.getActor();
|
|
3922
|
+
const followerActor = await accept.getActor(ctx);
|
|
3891
3923
|
if (!(0, _fedify_vocab.isActor)(followerActor) || !followerActor.id) return;
|
|
3892
3924
|
const parsed = ctx.parseUri(relayActorId);
|
|
3893
3925
|
if (parsed == null || parsed.type !== "actor") return;
|
|
3894
3926
|
const followerData = await ctx.data.kv.get(["follower", followerActor.id.href]);
|
|
3895
|
-
if (followerData
|
|
3927
|
+
if (!isRelayFollowerData(followerData)) return;
|
|
3928
|
+
if (await parseRelayFollowerData(followerActor.id.href, followerData) == null) return;
|
|
3896
3929
|
const updatedFollowerData = {
|
|
3897
3930
|
...followerData,
|
|
3898
3931
|
state: "accepted"
|
|
3899
3932
|
};
|
|
3900
3933
|
await ctx.data.kv.set(["follower", followerActor.id.href], updatedFollowerData);
|
|
3901
|
-
})
|
|
3934
|
+
});
|
|
3902
3935
|
}
|
|
3903
3936
|
};
|
|
3904
3937
|
//#endregion
|
|
@@ -3916,27 +3949,15 @@ const logger = (0, _logtape_logtape.getLogger)([
|
|
|
3916
3949
|
* @since 2.0.0
|
|
3917
3950
|
*/
|
|
3918
3951
|
var MastodonRelay = class extends BaseRelay {
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3952
|
+
initialFollowerState = "accepted";
|
|
3953
|
+
logger = logger;
|
|
3954
|
+
async deliverActivity(ctx, _activity, excludeBaseUris) {
|
|
3922
3955
|
await ctx.forwardActivity({ identifier: RELAY_SERVER_ACTOR }, "followers", {
|
|
3923
3956
|
skipIfUnsigned: true,
|
|
3924
3957
|
excludeBaseUris,
|
|
3925
3958
|
preferSharedInbox: true
|
|
3926
3959
|
});
|
|
3927
3960
|
}
|
|
3928
|
-
setupInboxListeners() {
|
|
3929
|
-
if (this.federation != null) this.federation.setInboxListeners("/users/{identifier}/inbox", "/inbox").on(_fedify_vocab.Follow, async (ctx, follow) => {
|
|
3930
|
-
const follower = await validateFollowActivity(ctx, follow);
|
|
3931
|
-
if (!follower || !follower.id) return;
|
|
3932
|
-
const approved = await this.options.subscriptionHandler(ctx, follower);
|
|
3933
|
-
if (approved) await ctx.data.kv.set(["follower", follower.id.href], {
|
|
3934
|
-
actor: await follower.toJsonLd(),
|
|
3935
|
-
state: "accepted"
|
|
3936
|
-
});
|
|
3937
|
-
await sendFollowResponse(ctx, follow, follower, approved);
|
|
3938
|
-
}).on(_fedify_vocab.Undo, async (ctx, undo) => await handleUndoFollow(ctx, undo, logger)).on(_fedify_vocab.Create, async (ctx, create) => await this.#forwardToFollowers(ctx, create)).on(_fedify_vocab.Delete, async (ctx, deleteActivity) => await this.#forwardToFollowers(ctx, deleteActivity)).on(_fedify_vocab.Move, async (ctx, move) => await this.#forwardToFollowers(ctx, move)).on(_fedify_vocab.Update, async (ctx, update) => await this.#forwardToFollowers(ctx, update)).on(_fedify_vocab.Announce, async (ctx, announce) => await this.#forwardToFollowers(ctx, announce));
|
|
3939
|
-
}
|
|
3940
3961
|
};
|
|
3941
3962
|
//#endregion
|
|
3942
3963
|
//#region src/factory.ts
|