@fedify/fedify 0.9.0-dev.171 → 0.9.0-dev.173

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.

Potentially problematic release.


This version of @fedify/fedify might be problematic. Click here for more details.

package/CHANGES.md CHANGED
@@ -8,10 +8,28 @@ Version 0.9.0
8
8
 
9
9
  To be released.
10
10
 
11
+ - Added `Hashtag` class to Activity Vocabulary API. [[#48]]
12
+
13
+ - Added `Emoji` class to Activity Vocabulary API. [[#48]]
14
+
15
+ - Added an actor handle normalization function.
16
+
17
+ - Added `normalizeActorHandle()` function.
18
+ - Added `NormalizeActorHandleOptions` interface.
19
+ - The `getActorHandle()` function now guarantees that the returned
20
+ actor handle is normalized.
21
+ - Added the second optional parameter to `getActorHandle()` function.
22
+ - The return type of `getActorHandle()` function became
23
+ ``Promise<`@${string}@${string}` | `${string}@${string}`>``
24
+ (was ``Promise<`@${string}@${string}`>``).
25
+
11
26
  - Added more log messages using the [LogTape] library. Currently the below
12
27
  logger categories are used:
13
28
 
14
29
  - `["fedify", "federation", "actor"]`
30
+ - `["fedify", "federation", "http"]`
31
+
32
+ [#48]: https://github.com/dahlia/fedify/issues/48
15
33
 
16
34
 
17
35
  Version 0.8.0
@@ -22,7 +40,7 @@ Released on May 6, 2024.
22
40
  - The CLI toolchain for testing and debugging is now available on JSR:
23
41
  [@fedify/cli]. You can install it with
24
42
  `deno install -A --unstable-fs --unstable-kv --unstable-temporal -n fedify
25
- jsr:@fedify/cli`, or download a standalone exectuable from the [releases]
43
+ jsr:@fedify/cli`, or download a standalone executable from the [releases]
26
44
  page.
27
45
 
28
46
  - Added `fedify` command.
@@ -843,7 +843,26 @@ export class Federation {
843
843
  * @returns The response to the request.
844
844
  * @since 0.6.0
845
845
  */
846
- async fetch(request, { onNotFound, onNotAcceptable, onUnauthorized, contextData, }) {
846
+ async fetch(request, options) {
847
+ const response = await this.#fetch(request, options);
848
+ const logger = getLogger(["fedify", "federation", "http"]);
849
+ const url = new URL(request.url);
850
+ const logTpl = "{method} {path}: {status}";
851
+ const values = {
852
+ method: request.method,
853
+ path: `${url.pathname}${url.search}`,
854
+ url: request.url,
855
+ status: response.status,
856
+ };
857
+ if (response.status >= 500)
858
+ logger.error(logTpl, values);
859
+ else if (response.status >= 400)
860
+ logger.warn(logTpl, values);
861
+ else
862
+ logger.info(logTpl, values);
863
+ return response;
864
+ }
865
+ async #fetch(request, { onNotFound, onNotAcceptable, onUnauthorized, contextData, }) {
847
866
  onNotFound ??= notFound;
848
867
  onNotAcceptable ??= notAcceptable;
849
868
  onUnauthorized ??= unauthorized;
@@ -1,3 +1,4 @@
1
+ import { toASCII, toUnicode } from "node:punycode";
1
2
  import { lookupWebFinger } from "../webfinger/lookup.js";
2
3
  import { Application, Group, Organization, Person, Service } from "./vocab.js";
3
4
  /**
@@ -66,13 +67,15 @@ export function getActorClassByTypeName(typeName) {
66
67
  * ```
67
68
  *
68
69
  * @param actor The actor or actor URI to get the handle from.
70
+ * @param options The options for normalizing the actor handle.
69
71
  * @returns The actor handle. It starts with `@` and is followed by the
70
- * username and domain, separated by `@`.
72
+ * username and domain, separated by `@` by default (it can be
73
+ * customized with the options).
71
74
  * @throws {TypeError} If the actor does not have enough information to get the
72
75
  * handle.
73
76
  * @since 0.4.0
74
77
  */
75
- export async function getActorHandle(actor) {
78
+ export async function getActorHandle(actor, options = {}) {
76
79
  const actorId = actor instanceof URL ? actor : actor.id;
77
80
  if (actorId != null) {
78
81
  const result = await lookupWebFinger(actorId);
@@ -82,14 +85,37 @@ export async function getActorHandle(actor) {
82
85
  aliases.unshift(result.subject);
83
86
  for (const alias of aliases) {
84
87
  const match = alias.match(/^acct:([^@]+)@([^@]+)$/);
85
- if (match != null)
86
- return `@${match[1]}@${match[2]}`;
88
+ if (match != null) {
89
+ return normalizeActorHandle(`@${match[1]}@${match[2]}`, options);
90
+ }
87
91
  }
88
92
  }
89
93
  }
90
94
  if (!(actor instanceof URL) && actor.preferredUsername != null &&
91
95
  actor.id != null) {
92
- return `@${actor.preferredUsername}@${actor.id.host}`;
96
+ return normalizeActorHandle(`@${actor.preferredUsername}@${actor.id.host}`, options);
93
97
  }
94
98
  throw new TypeError("Actor does not have enough information to get the handle.");
95
99
  }
100
+ /**
101
+ * Normalizes the given actor handle.
102
+ * @param handle The full handle of the actor to normalize.
103
+ * @param options The options for normalizing the actor handle.
104
+ * @returns The normalized actor handle.
105
+ * @throws {TypeError} If the actor handle is invalid.
106
+ */
107
+ export function normalizeActorHandle(handle, options = {}) {
108
+ handle = handle.replace(/^@/, "");
109
+ const atPos = handle.indexOf("@");
110
+ if (atPos < 1)
111
+ throw new TypeError("Invalid actor handle.");
112
+ let domain = handle.substring(atPos + 1);
113
+ if (domain.length < 1 || domain.includes("@")) {
114
+ throw new TypeError("Invalid actor handle.");
115
+ }
116
+ domain = domain.toLowerCase();
117
+ domain = options.punycode ? toASCII(domain) : toUnicode(domain);
118
+ domain = domain.toLowerCase();
119
+ const user = handle.substring(0, atPos);
120
+ return options.trimLeadingAt ? `${user}@${domain}` : `@${user}@${domain}`;
121
+ }
@@ -7,5 +7,10 @@ description: |
7
7
  Indicates that the `actor` is calling the `target`'s attention the `object`.
8
8
 
9
9
  The `origin` typically has no defined meaning.
10
- defaultContext: "https://www.w3.org/ns/activitystreams"
10
+ defaultContext:
11
+ - "https://www.w3.org/ns/activitystreams"
12
+ - toot: "http://joinmastodon.org/ns#"
13
+ sensitive: "as:sensitive"
14
+ Emoji: "toot:Emoji"
15
+ Hashtag: "as:Hashtag"
11
16
  properties: []
@@ -4,5 +4,10 @@ uri: "https://www.w3.org/ns/activitystreams#Article"
4
4
  extends: "https://www.w3.org/ns/activitystreams#Object"
5
5
  entity: true
6
6
  description: Represents any kind of multi-paragraph written work.
7
- defaultContext: "https://www.w3.org/ns/activitystreams"
7
+ defaultContext:
8
+ - "https://www.w3.org/ns/activitystreams"
9
+ - toot: "http://joinmastodon.org/ns#"
10
+ sensitive: "as:sensitive"
11
+ Emoji: "toot:Emoji"
12
+ Hashtag: "as:Hashtag"
8
13
  properties: []
@@ -4,5 +4,10 @@ uri: "https://www.w3.org/ns/activitystreams#Create"
4
4
  extends: "https://www.w3.org/ns/activitystreams#Activity"
5
5
  entity: true
6
6
  description: Indicates that the `actor` has created the `object`.
7
- defaultContext: "https://www.w3.org/ns/activitystreams"
7
+ defaultContext:
8
+ - "https://www.w3.org/ns/activitystreams"
9
+ - toot: "http://joinmastodon.org/ns#"
10
+ sensitive: "as:sensitive"
11
+ Emoji: "toot:Emoji"
12
+ Hashtag: "as:Hashtag"
8
13
  properties: []
@@ -0,0 +1,11 @@
1
+ $schema: ../codegen/schema.yaml
2
+ name: Emoji
3
+ uri: "http://joinmastodon.org/ns#Emoji"
4
+ extends: "https://www.w3.org/ns/activitystreams#Object"
5
+ entity: true
6
+ description: Represents a custom emoji.
7
+ defaultContext:
8
+ - "https://www.w3.org/ns/activitystreams"
9
+ - toot: "http://joinmastodon.org/ns#"
10
+ Emoji: "toot:Emoji"
11
+ properties: []
@@ -0,0 +1,13 @@
1
+ $schema: ../codegen/schema.yaml
2
+ name: Hashtag
3
+ uri: "https://www.w3.org/ns/activitystreams#Hashtag"
4
+ extends: "https://www.w3.org/ns/activitystreams#Link"
5
+ entity: false
6
+ description: |
7
+ A specialized {@link Link} that represents an #hashtag.
8
+
9
+ See also <https://swicg.github.io/miscellany/#Hashtag>.
10
+ defaultContext:
11
+ - "https://www.w3.org/ns/activitystreams"
12
+ - Hashtag: "as:Hashtag"
13
+ properties: []
@@ -6,5 +6,10 @@ entity: true
6
6
  description: |
7
7
  Represents a short written work typically less than a single paragraph in
8
8
  length.
9
- defaultContext: "https://www.w3.org/ns/activitystreams"
9
+ defaultContext:
10
+ - "https://www.w3.org/ns/activitystreams"
11
+ - toot: "http://joinmastodon.org/ns#"
12
+ sensitive: "as:sensitive"
13
+ Emoji: "toot:Emoji"
14
+ Hashtag: "as:Hashtag"
10
15
  properties: []
@@ -9,5 +9,10 @@ description: |
9
9
  set of modifications made to `object`.
10
10
 
11
11
  The `target` and `origin` typically have no defined meaning.
12
- defaultContext: "https://www.w3.org/ns/activitystreams"
12
+ defaultContext:
13
+ - "https://www.w3.org/ns/activitystreams"
14
+ - toot: "http://joinmastodon.org/ns#"
15
+ sensitive: "as:sensitive"
16
+ Emoji: "toot:Emoji"
17
+ Hashtag: "as:Hashtag"
13
18
  properties: []