Skip to content

Commit

Permalink
mentions() predicate function
Browse files Browse the repository at this point in the history
  • Loading branch information
dahlia committed Jan 12, 2025
1 parent c17f7e8 commit 8a45da7
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 0 deletions.
29 changes: 29 additions & 0 deletions docs/concepts/text.md
Original file line number Diff line number Diff line change
Expand Up @@ -452,3 +452,32 @@ The above code will create a text like this:
> [!NOTE]
> The `markdown()` function does not support raw HTML syntax.
Determining if the text mentions an account
-------------------------------------------
You can determine if the text mentions an account by using the `mentions()`
function. It returns `true` if the text mentions the account,
otherwise `false`:
~~~~ typescript
import { type Actor, markdown, mention, mentions, text } from "@fedify/botkit";
const actor: Actor = getActor( // A hypothetical function that returns an Actor object
"@[email protected]"
);
const actor2: Actor = getActor("@[email protected]");
const md = markdown("Hello, @[email protected]!");
console.log(await mentions(md, actor)); // true
console.log(await mentions(md, actor2)); // false
const txt = text`Hi, ${actor2}!`
console.log(await mentions(txt, actor)); // false
console.log(await mentions(txt, actor2)); // true
const noMention = text`Hello, world!`;
console.log(await mentions(noMention, actor)); // false
console.log(await mentions(noMention, actor2)); // false
~~~~
17 changes: 17 additions & 0 deletions src/text.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
link,
markdown,
mention,
mentions,
type Text,
text,
} from "./text.ts";
Expand Down Expand Up @@ -134,6 +135,22 @@ Deno.test("isText()", () => {
assertFalse(isText("Hello, World"));
});

Deno.test("mentions()", async () => {
const session = bot.getSession("https://example.com");
const actor = new URL("https://hollo.social/@fedify");
const actor2 = new URL("https://example.com/users/john");
const actor3 = new Person({ id: actor });
const t: Text<"block", void> = text`Hello, world!`;
assertFalse(await mentions(session, t, actor));
assertFalse(await mentions(session, t, actor2));
assertFalse(await mentions(session, t, actor3));

const m: Text<"inline", void> = mention(actor);
assert(await mentions(session, m, actor));
assertFalse(await mentions(session, m, actor2));
assert(await mentions(session, m, actor3));
});

Deno.test({
name: "text`...`",
permissions: {},
Expand Down
23 changes: 23 additions & 0 deletions src/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,29 @@ export function isText<TContextData>(
(value.type === "block" || value.type === "inline");
}

/**
* Checks if a given `actor` is mentioned in a `text`.
* @param session The bot session.
* @param text The text object to check.
* @param actor The actor to check. It can be either an `Actor` object or
* an actor URI.
* @returns `true` if the actor is mentioned in the text, `false` otherwise.
*/
export async function mentions<TContextData>(
session: Session<TContextData>,
text: Text<"block" | "inline", TContextData>,
actor: Actor | URL,
): Promise<boolean> {
if (isActor(actor)) {
if (actor.id == null) return false;
actor = actor.id;
}
for await (const tag of text.getTags(session)) {
if (tag instanceof Mention && tag.href?.href === actor.href) return true;
}
return false;
}

/**
* A text tree that renders a template string with values. You normally
* don't need to instantiate this directly; use the {@link text} function
Expand Down

0 comments on commit 8a45da7

Please sign in to comment.