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:
Paul Frazee 2023-04-27 12:38:23 -05:00 committed by GitHub
parent 51be8474db
commit 1d50ddb378
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 1195 additions and 763 deletions

View file

@ -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) =>