| [fe97cc3] | 1 | // Inbound mentions — a remote note whose Mention tag targets one of our actors becomes a
|
|---|
| 2 | // notification, even when it isn't a reply to our content. localMentionSlugs is the detection
|
|---|
| 3 | // core: only OUR base counts, the slug must exist, deduped. In-memory SQLite. Run: npm test
|
|---|
| 4 | import { test } from 'node:test';
|
|---|
| 5 | import assert from 'node:assert/strict';
|
|---|
| 6 |
|
|---|
| 7 | process.env.DATABASE_PATH = ':memory:';
|
|---|
| 8 | process.env.PUBLIC_BASE_URL = 'https://test.example';
|
|---|
| 9 |
|
|---|
| 10 | const dbMod = await import('../src/config/database.js');
|
|---|
| 11 | const db = dbMod.default;
|
|---|
| 12 | dbMod.initializeDatabase();
|
|---|
| 13 | const AP = (await import('../src/services/ActivityPubService.js')).default;
|
|---|
| 14 |
|
|---|
| 15 | const BASE = 'https://test.example';
|
|---|
| 16 | db.prepare('INSERT INTO users (id, username, email, password_hash, role) VALUES (?,?,?,?,?)').run('u1', 'u1', 'u1@test', 'x', 'god');
|
|---|
| 17 | db.prepare('INSERT INTO sites (id, slug, title, owner_id, is_primary) VALUES (?,?,?,?,?)').run('s1', 'demo', 'Demo', 'u1', 1);
|
|---|
| 18 |
|
|---|
| 19 | test('a Mention tag with our actor href resolves to the site slug', () => {
|
|---|
| 20 | const tags = [
|
|---|
| 21 | { type: 'Mention', href: `${BASE}/ap/users/demo`, name: '@demo@test.example' },
|
|---|
| 22 | { type: 'Hashtag', href: `${BASE}/tag/x`, name: '#x' },
|
|---|
| 23 | ];
|
|---|
| 24 | assert.deepEqual(AP.localMentionSlugs(tags, BASE), ['demo']);
|
|---|
| 25 | });
|
|---|
| 26 |
|
|---|
| 27 | test('a remote host with the same /ap/users path is NOT ours', () => {
|
|---|
| 28 | const tags = [{ type: 'Mention', href: 'https://other.example/ap/users/demo', name: '@demo@other.example' }];
|
|---|
| 29 | assert.deepEqual(AP.localMentionSlugs(tags, BASE), []);
|
|---|
| 30 | });
|
|---|
| 31 |
|
|---|
| 32 | test('a mention of a non-existent slug is ignored; duplicates dedupe', () => {
|
|---|
| 33 | const tags = [
|
|---|
| 34 | { type: 'Mention', href: `${BASE}/ap/users/ghost`, name: '@ghost' },
|
|---|
| 35 | { type: 'Mention', href: `${BASE}/ap/users/demo`, name: '@demo' },
|
|---|
| 36 | { type: 'Mention', href: `${BASE}/ap/users/demo`, name: '@demo' },
|
|---|
| 37 | ];
|
|---|
| 38 | assert.deepEqual(AP.localMentionSlugs(tags, BASE), ['demo']);
|
|---|
| 39 | });
|
|---|
| 40 |
|
|---|
| 41 | test('a stored mention shows up in the notifications', () => {
|
|---|
| 42 | db.prepare('INSERT OR IGNORE INTO ap_mentions (slug, object_uri, note_url, actor_uri, actor_name, actor_handle, content) VALUES (?,?,?,?,?,?,?)')
|
|---|
| 43 | .run('demo', 'https://m.example/notes/1', 'https://m.example/@a/1', 'https://m.example/users/a', 'Anna', '@a@m.example', '<p>hi @demo</p>');
|
|---|
| 44 | const items = AP.getNotifications('demo', 20);
|
|---|
| 45 | const m = items.find((n) => n.type === 'mention');
|
|---|
| 46 | assert.ok(m, 'mention notification present');
|
|---|
| 47 | assert.equal(m.handle, '@a@m.example');
|
|---|
| 48 | assert.equal(m.note_url, 'https://m.example/@a/1');
|
|---|
| 49 | });
|
|---|