Refactor moderation to apply to accounts, profiles, and posts correctly (#548)
* Add ScreenHider component * Add blur attribute to UserAvatar and UserBanner * Remove dead suggested posts component and model * Bump @atproto/api@0.2.10 * Rework moderation tooling to give a more precise DSL * Add label mocks * Apply finer grained moderation controls * Refactor ProfileCard to just take the profile object * Apply moderation to user listings and banner * Apply moderation to notifications * Fix lint * Tune avatar & banner blur settings per platform * 1.24
This commit is contained in:
parent
51be8474db
commit
1d50ddb378
40 changed files with 1195 additions and 763 deletions
149
jest/test-pds.ts
149
jest/test-pds.ts
|
@ -2,6 +2,7 @@ import {AddressInfo} from 'net'
|
|||
import os from 'os'
|
||||
import net from 'net'
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
import * as crypto from '@atproto/crypto'
|
||||
import {PDS, ServerConfig, Database, MemoryBlobStore} from '@atproto/pds'
|
||||
import * as plc from '@did-plc/lib'
|
||||
|
@ -104,9 +105,13 @@ export async function createServer(
|
|||
await pds.start()
|
||||
const pdsUrl = `http://localhost:${port}`
|
||||
|
||||
const profilePic = fs.readFileSync(
|
||||
path.join(__dirname, '..', 'assets', 'default-avatar.jpg'),
|
||||
)
|
||||
|
||||
return {
|
||||
pdsUrl,
|
||||
mocker: new Mocker(pdsUrl),
|
||||
mocker: new Mocker(pds, pdsUrl, profilePic),
|
||||
async close() {
|
||||
await pds.destroy()
|
||||
await plcServer.destroy()
|
||||
|
@ -118,7 +123,11 @@ class Mocker {
|
|||
agent: BskyAgent
|
||||
users: Record<string, TestUser> = {}
|
||||
|
||||
constructor(public service: string) {
|
||||
constructor(
|
||||
public pds: PDS,
|
||||
public service: string,
|
||||
public profilePic: Uint8Array,
|
||||
) {
|
||||
this.agent = new BskyAgent({service})
|
||||
}
|
||||
|
||||
|
@ -152,6 +161,15 @@ class Mocker {
|
|||
handle: name + '.test',
|
||||
password: 'hunter2',
|
||||
})
|
||||
await agent.upsertProfile(async () => {
|
||||
const blob = await agent.uploadBlob(this.profilePic, {
|
||||
encoding: 'image/jpeg',
|
||||
})
|
||||
return {
|
||||
displayName: name,
|
||||
avatar: blob.data.blob,
|
||||
}
|
||||
})
|
||||
this.users[name] = {
|
||||
did: res.data.did,
|
||||
email,
|
||||
|
@ -192,6 +210,133 @@ class Mocker {
|
|||
await this.follow('carla', 'alice')
|
||||
await this.follow('carla', 'bob')
|
||||
}
|
||||
|
||||
async createPost(user: string, text: string) {
|
||||
const agent = this.users[user]?.agent
|
||||
if (!agent) {
|
||||
throw new Error(`Not a user: ${user}`)
|
||||
}
|
||||
return await agent.post({
|
||||
text,
|
||||
createdAt: new Date().toISOString(),
|
||||
})
|
||||
}
|
||||
|
||||
async createQuotePost(
|
||||
user: string,
|
||||
text: string,
|
||||
{uri, cid}: {uri: string; cid: string},
|
||||
) {
|
||||
const agent = this.users[user]?.agent
|
||||
if (!agent) {
|
||||
throw new Error(`Not a user: ${user}`)
|
||||
}
|
||||
return await agent.post({
|
||||
text,
|
||||
embed: {$type: 'app.bsky.embed.record', record: {uri, cid}},
|
||||
createdAt: new Date().toISOString(),
|
||||
})
|
||||
}
|
||||
|
||||
async createReply(
|
||||
user: string,
|
||||
text: string,
|
||||
{uri, cid}: {uri: string; cid: string},
|
||||
) {
|
||||
const agent = this.users[user]?.agent
|
||||
if (!agent) {
|
||||
throw new Error(`Not a user: ${user}`)
|
||||
}
|
||||
return await agent.post({
|
||||
text,
|
||||
reply: {root: {uri, cid}, parent: {uri, cid}},
|
||||
createdAt: new Date().toISOString(),
|
||||
})
|
||||
}
|
||||
|
||||
async like(user: string, {uri, cid}: {uri: string; cid: string}) {
|
||||
const agent = this.users[user]?.agent
|
||||
if (!agent) {
|
||||
throw new Error(`Not a user: ${user}`)
|
||||
}
|
||||
return await agent.like(uri, cid)
|
||||
}
|
||||
|
||||
async labelAccount(label: string, user: string) {
|
||||
const did = this.users[user]?.did
|
||||
if (!did) {
|
||||
throw new Error(`Invalid user: ${user}`)
|
||||
}
|
||||
const ctx = this.pds.ctx
|
||||
if (!ctx) {
|
||||
throw new Error('Invalid PDS')
|
||||
}
|
||||
|
||||
await ctx.db.db
|
||||
.insertInto('label')
|
||||
.values([
|
||||
{
|
||||
src: ctx.cfg.labelerDid,
|
||||
uri: did,
|
||||
cid: '',
|
||||
val: label,
|
||||
neg: 0,
|
||||
cts: new Date().toISOString(),
|
||||
},
|
||||
])
|
||||
.execute()
|
||||
}
|
||||
|
||||
async labelProfile(label: string, user: string) {
|
||||
const agent = this.users[user]?.agent
|
||||
const did = this.users[user]?.did
|
||||
if (!did) {
|
||||
throw new Error(`Invalid user: ${user}`)
|
||||
}
|
||||
|
||||
const profile = await agent.app.bsky.actor.profile.get({
|
||||
repo: user + '.test',
|
||||
rkey: 'self',
|
||||
})
|
||||
|
||||
const ctx = this.pds.ctx
|
||||
if (!ctx) {
|
||||
throw new Error('Invalid PDS')
|
||||
}
|
||||
await ctx.db.db
|
||||
.insertInto('label')
|
||||
.values([
|
||||
{
|
||||
src: ctx.cfg.labelerDid,
|
||||
uri: profile.uri,
|
||||
cid: profile.cid,
|
||||
val: label,
|
||||
neg: 0,
|
||||
cts: new Date().toISOString(),
|
||||
},
|
||||
])
|
||||
.execute()
|
||||
}
|
||||
|
||||
async labelPost(label: string, {uri, cid}: {uri: string; cid: string}) {
|
||||
const ctx = this.pds.ctx
|
||||
if (!ctx) {
|
||||
throw new Error('Invalid PDS')
|
||||
}
|
||||
await ctx.db.db
|
||||
.insertInto('label')
|
||||
.values([
|
||||
{
|
||||
src: ctx.cfg.labelerDid,
|
||||
uri,
|
||||
cid,
|
||||
val: label,
|
||||
neg: 0,
|
||||
cts: new Date().toISOString(),
|
||||
},
|
||||
])
|
||||
.execute()
|
||||
}
|
||||
}
|
||||
|
||||
const checkAvailablePort = (port: number) =>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue