kopia lustrzana https://github.com/cloudflare/wildebeest
add Actor cache to webfinger
rodzic
dd8662ba57
commit
a876ef9ad2
|
@ -18,17 +18,17 @@ export async function getAccount(domain: string, accountId: string, db: Database
|
|||
} else if (handle.domain !== null) {
|
||||
// Retrieve the statuses of a remote actor
|
||||
const acct = `${handle.localPart}@${handle.domain}`
|
||||
return getRemoteAccount(handle, acct)
|
||||
return getRemoteAccount(handle, acct, db)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async function getRemoteAccount(handle: Handle, acct: string): Promise<MastodonAccount | null> {
|
||||
async function getRemoteAccount(handle: Handle, acct: string, db: D1Database): Promise<MastodonAccount | null> {
|
||||
// TODO: using webfinger isn't the optimal implementation. We could cache
|
||||
// the object in D1 and directly query the remote API, indicated by the actor's
|
||||
// url field. For now, let's keep it simple.
|
||||
const actor = await queryAcct(handle.domain!, acct)
|
||||
const actor = await queryAcct(handle.domain!, db, acct)
|
||||
if (actor === null) {
|
||||
return null
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import type { APObject } from 'wildebeest/backend/src/activitypub/objects'
|
|||
import type { Actor } from 'wildebeest/backend/src/activitypub/actors'
|
||||
import { type Database } from 'wildebeest/backend/src/database'
|
||||
|
||||
export async function getMentions(input: string, instanceDomain: string): Promise<Array<Actor>> {
|
||||
export async function getMentions(input: string, instanceDomain: string, db: Database): Promise<Array<Actor>> {
|
||||
const mentions: Array<Actor> = []
|
||||
|
||||
for (let i = 0, len = input.length; i < len; i++) {
|
||||
|
@ -34,7 +34,7 @@ export async function getMentions(input: string, instanceDomain: string): Promis
|
|||
const handle = parseHandle(buffer)
|
||||
const domain = handle.domain ? handle.domain : instanceDomain
|
||||
const acct = `${handle.localPart}@${domain}`
|
||||
const targetActor = await queryAcct(domain!, acct)
|
||||
const targetActor = await queryAcct(domain!, db, acct)
|
||||
if (targetActor === null) {
|
||||
console.warn(`actor ${acct} not found`)
|
||||
continue
|
||||
|
|
|
@ -11,12 +11,12 @@ const headers = {
|
|||
accept: 'application/jrd+json',
|
||||
}
|
||||
|
||||
export async function queryAcct(domain: string, acct: string): Promise<Actor | null> {
|
||||
export async function queryAcct(domain: string, db: D1Database, acct: string): Promise<Actor | null> {
|
||||
const url = await queryAcctLink(domain, acct)
|
||||
if (url === null) {
|
||||
return null
|
||||
}
|
||||
return actors.get(url)
|
||||
return actors.getAndCache(url, db)
|
||||
}
|
||||
|
||||
export async function queryAcctLink(domain: string, acct: string): Promise<URL | null> {
|
||||
|
|
|
@ -976,24 +976,24 @@ describe('Mastodon APIs', () => {
|
|||
{
|
||||
rel: 'self',
|
||||
type: 'application/activity+json',
|
||||
href: 'https://social.com/sven',
|
||||
href: `https://${domain}/ap/users/actor`,
|
||||
},
|
||||
],
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
if (request.url === 'https://social.com/sven') {
|
||||
if (request.url === `https://${domain}/ap/users/actor`) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
id: `https://${domain}/ap/users/actor`,
|
||||
type: 'Person',
|
||||
inbox: 'https://example.com/inbox',
|
||||
inbox: `https://${domain}/ap/users/actor/inbox`,
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
if (request.url === 'https://example.com/inbox') {
|
||||
if (request.url === `https://${domain}/ap/users/actor/inbox`) {
|
||||
assert.equal(request.method, 'POST')
|
||||
receivedActivity = await request.json()
|
||||
return new Response('')
|
||||
|
@ -1040,7 +1040,7 @@ describe('Mastodon APIs', () => {
|
|||
|
||||
const connectedActor = actor
|
||||
|
||||
const req = new Request('https://example.com', { method: 'POST' })
|
||||
const req = new Request('https://' + domain, { method: 'POST' })
|
||||
const res = await accounts_unfollow.handleRequest(req, db, 'actor@' + domain, connectedActor, userKEK)
|
||||
assert.equal(res.status, 200)
|
||||
assertCORS(res)
|
||||
|
|
|
@ -202,6 +202,7 @@ describe('Mastodon APIs', () => {
|
|||
return new Response(
|
||||
JSON.stringify({
|
||||
id: 'https://social.com/users/sven',
|
||||
type: 'Person',
|
||||
inbox: 'https://social.com/sven/inbox',
|
||||
})
|
||||
)
|
||||
|
@ -404,6 +405,7 @@ describe('Mastodon APIs', () => {
|
|||
})
|
||||
|
||||
test('get mentions from status', async () => {
|
||||
const db = await makeDB()
|
||||
globalThis.fetch = async (input: RequestInfo) => {
|
||||
if (input.toString() === 'https://instance.horse/.well-known/webfinger?resource=acct%3Asven%40instance.horse') {
|
||||
return new Response(
|
||||
|
@ -467,6 +469,7 @@ describe('Mastodon APIs', () => {
|
|||
return new Response(
|
||||
JSON.stringify({
|
||||
id: 'https://instance.horse/users/sven',
|
||||
type: 'Person',
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@ -474,6 +477,7 @@ describe('Mastodon APIs', () => {
|
|||
return new Response(
|
||||
JSON.stringify({
|
||||
id: 'https://cloudflare.com/users/sven',
|
||||
type: 'Person',
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@ -481,6 +485,7 @@ describe('Mastodon APIs', () => {
|
|||
return new Response(
|
||||
JSON.stringify({
|
||||
id: 'https://cloudflare.com/users/a',
|
||||
type: 'Person',
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@ -488,6 +493,7 @@ describe('Mastodon APIs', () => {
|
|||
return new Response(
|
||||
JSON.stringify({
|
||||
id: 'https://cloudflare.com/users/b',
|
||||
type: 'Person',
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@ -496,42 +502,42 @@ describe('Mastodon APIs', () => {
|
|||
}
|
||||
|
||||
{
|
||||
const mentions = await getMentions('test status', domain)
|
||||
const mentions = await getMentions('test status', domain, db)
|
||||
assert.equal(mentions.length, 0)
|
||||
}
|
||||
|
||||
{
|
||||
const mentions = await getMentions('no-json@actor.com', domain)
|
||||
const mentions = await getMentions('no-json@actor.com', domain, db)
|
||||
assert.equal(mentions.length, 0)
|
||||
}
|
||||
|
||||
{
|
||||
const mentions = await getMentions('@sven@instance.horse test status', domain)
|
||||
const mentions = await getMentions('@sven@instance.horse test status', domain, db)
|
||||
assert.equal(mentions.length, 1)
|
||||
assert.equal(mentions[0].id.toString(), 'https://instance.horse/users/sven')
|
||||
}
|
||||
|
||||
{
|
||||
const mentions = await getMentions('@sven test status', domain)
|
||||
const mentions = await getMentions('@sven test status', domain, db)
|
||||
assert.equal(mentions.length, 1)
|
||||
assert.equal(mentions[0].id.toString(), 'https://' + domain + '/users/sven')
|
||||
}
|
||||
|
||||
{
|
||||
const mentions = await getMentions('@a @b', domain)
|
||||
const mentions = await getMentions('@a @b', domain, db)
|
||||
assert.equal(mentions.length, 2)
|
||||
assert.equal(mentions[0].id.toString(), 'https://' + domain + '/users/a')
|
||||
assert.equal(mentions[1].id.toString(), 'https://' + domain + '/users/b')
|
||||
}
|
||||
|
||||
{
|
||||
const mentions = await getMentions('<p>@sven</p>', domain)
|
||||
const mentions = await getMentions('<p>@sven</p>', domain, db)
|
||||
assert.equal(mentions.length, 1)
|
||||
assert.equal(mentions[0].id.toString(), 'https://' + domain + '/users/sven')
|
||||
}
|
||||
|
||||
{
|
||||
const mentions = await getMentions('<p>@unknown</p>', domain)
|
||||
const mentions = await getMentions('<p>@unknown</p>', domain, db)
|
||||
assert.equal(mentions.length, 0)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -31,6 +31,7 @@ describe('Wildebeest', () => {
|
|||
return new Response(
|
||||
JSON.stringify({
|
||||
id: 'https://social.com/someone',
|
||||
type: 'Person',
|
||||
})
|
||||
)
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ export async function handleRequest(
|
|||
}
|
||||
|
||||
const acct = `${handle.localPart}@${handle.domain}`
|
||||
const targetActor = await webfinger.queryAcct(handle.domain!, acct)
|
||||
const targetActor = await webfinger.queryAcct(handle.domain!, db, acct)
|
||||
if (targetActor === null) {
|
||||
return new Response('', { status: 404 })
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ export async function handleRequest(
|
|||
|
||||
const hashtags = getHashtags(body.status)
|
||||
|
||||
const mentions = await getMentions(body.status, domain)
|
||||
const mentions = await getMentions(body.status, domain, db)
|
||||
if (mentions.length > 0) {
|
||||
extraProperties.tag = mentions.map(newMention)
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ export async function handleRequest(db: Database, request: Request): Promise<Res
|
|||
|
||||
if (useWebFinger && query.domain !== null) {
|
||||
const acct = `${query.localPart}@${query.domain}`
|
||||
const res = await queryAcct(query.domain, acct)
|
||||
const res = await queryAcct(query.domain, db, acct)
|
||||
if (res !== null) {
|
||||
out.accounts.push(await loadExternalMastodonAccount(acct, res))
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ export async function handleRequestPost(db: Database, request: Request, connecte
|
|||
console.warn("account migration within an instance isn't supported")
|
||||
return new Response('', { status: 400 })
|
||||
}
|
||||
const actor = await queryAcct(handle.domain, acct)
|
||||
const actor = await queryAcct(handle.domain, db, acct)
|
||||
if (actor === null) {
|
||||
return errors.resourceNotFound('actor', acct)
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue