Merge branch 'main' into ipad-fixes

This commit is contained in:
Samuel Newman
2024-03-31 16:30:55 -07:00
940 changed files with 154123 additions and 32274 deletions
+167 -65
View File
@@ -1,8 +1,8 @@
import {AtUri, BskyAgent} from '@atproto/api'
import {TestNetwork, TestPds} from '@atproto/dev-env'
import fs from 'fs'
import net from 'net'
import path from 'path'
import fs from 'fs'
import {TestNetworkNoAppView} from '@atproto/dev-env'
import {AtUri, BskyAgent} from '@atproto/api'
export interface TestUser {
email: string
@@ -18,19 +18,115 @@ export interface TestPDS {
close: () => Promise<void>
}
class StringIdGenerator {
_nextId = [0]
constructor(
public _chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
) {}
next() {
const r = []
for (const char of this._nextId) {
r.unshift(this._chars[char])
}
this._increment()
return r.join('')
}
_increment() {
for (let i = 0; i < this._nextId.length; i++) {
const val = ++this._nextId[i]
if (val >= this._chars.length) {
this._nextId[i] = 0
} else {
return
}
}
this._nextId.push(0)
}
*[Symbol.iterator]() {
while (true) {
yield this.next()
}
}
}
const ids = new StringIdGenerator()
export async function createServer(
{inviteRequired}: {inviteRequired: boolean} = {inviteRequired: false},
{
inviteRequired,
phoneRequired,
}: {inviteRequired: boolean; phoneRequired: boolean} = {
inviteRequired: false,
phoneRequired: false,
},
): Promise<TestPDS> {
const port = await getPort()
const port = 3000
const port2 = await getPort(port + 1)
const port3 = await getPort(port2 + 1)
const pdsUrl = `http://localhost:${port}`
const testNet = await TestNetworkNoAppView.create({
pds: {port, publicUrl: pdsUrl, inviteRequired},
const id = ids.next()
const phoneParams = phoneRequired
? {
phoneVerificationRequired: true,
phoneVerificationProvider: 'twilio',
twilioAccountSid: 'ACXXXXXXX',
twilioAuthToken: 'AUTH',
twilioServiceSid: 'VAXXXXXXXX',
}
: {}
const testNet = await TestNetwork.create({
pds: {
port,
hostname: 'localhost',
dbPostgresSchema: `pds_${id}`,
inviteRequired,
...phoneParams,
},
bsky: {
dbPostgresSchema: `bsky_${id}`,
port: port3,
publicUrl: 'http://localhost:2584',
},
plc: {port: port2},
})
mockTwilio(testNet.pds)
// add the test mod authority
if (!phoneRequired) {
const agent = new BskyAgent({service: pdsUrl})
const res = await agent.api.com.atproto.server.createAccount({
email: 'mod-authority@test.com',
handle: 'mod-authority.test',
password: 'hunter2',
})
agent.api.setHeader('Authorization', `Bearer ${res.data.accessJwt}`)
await agent.api.app.bsky.actor.profile.create(
{repo: res.data.did},
{
displayName: 'Dev-env Moderation',
description: `The pretend version of mod.bsky.app`,
},
)
await agent.api.app.bsky.labeler.service.create(
{repo: res.data.did, rkey: 'self'},
{
policies: {
labelValues: ['!hide', '!warn'],
labelValueDefinitions: [],
},
createdAt: new Date().toISOString(),
},
)
}
const pic = fs.readFileSync(
path.join(__dirname, '..', 'assets', 'default-avatar.jpg'),
path.join(__dirname, '..', 'assets', 'default-avatar.png'),
)
return {
@@ -48,7 +144,7 @@ class Mocker {
users: Record<string, TestUser> = {}
constructor(
public testNet: TestNetworkNoAppView,
public testNet: TestNetwork,
public service: string,
public pic: Uint8Array,
) {
@@ -59,6 +155,10 @@ class Mocker {
return this.testNet.pds
}
get bsky() {
return this.testNet.bsky
}
get plc() {
return this.testNet.plc
}
@@ -81,11 +181,7 @@ class Mocker {
const inviteRes = await agent.api.com.atproto.server.createInviteCode(
{useCount: 1},
{
headers: {
authorization: `Basic ${btoa(
`admin:${this.pds.ctx.cfg.adminPassword}`,
)}`,
},
headers: this.pds.adminAuthHeaders('admin'),
encoding: 'application/json',
},
)
@@ -96,6 +192,8 @@ class Mocker {
email,
handle: name + '.test',
password: 'hunter2',
verificationPhone: '1234567890',
verificationCode: '000000',
})
await agent.upsertProfile(async () => {
const blob = await agent.uploadBlob(this.pic, {
@@ -260,11 +358,7 @@ class Mocker {
await agent.api.com.atproto.server.createInviteCode(
{useCount: 1, forAccount},
{
headers: {
authorization: `Basic ${btoa(
`admin:${this.pds.ctx.cfg.adminPassword}`,
)}`,
},
headers: this.pds.adminAuthHeaders('admin'),
encoding: 'application/json',
},
)
@@ -275,24 +369,22 @@ class Mocker {
if (!did) {
throw new Error(`Invalid user: ${user}`)
}
const ctx = this.pds.ctx
const ctx = this.bsky.ctx
if (!ctx) {
throw new Error('Invalid PDS')
throw new Error('Invalid appview')
}
await ctx.db.db
.insertInto('label')
.values([
{
src: ctx.cfg.labelerDid,
uri: did,
cid: '',
val: label,
neg: 0,
cts: new Date().toISOString(),
},
])
.execute()
const labelSrvc = ctx.services.label(ctx.db.getPrimary())
await labelSrvc.createLabels([
{
// @ts-ignore
src: ctx.cfg.labelerDid,
uri: did,
cid: '',
val: label,
neg: false,
cts: new Date().toISOString(),
},
])
}
async labelProfile(label: string, user: string) {
@@ -307,43 +399,41 @@ class Mocker {
rkey: 'self',
})
const ctx = this.pds.ctx
const ctx = this.bsky.ctx
if (!ctx) {
throw new Error('Invalid PDS')
throw new Error('Invalid appview')
}
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()
const labelSrvc = ctx.services.label(ctx.db.getPrimary())
await labelSrvc.createLabels([
{
// @ts-ignore
src: ctx.cfg.labelerDid,
uri: profile.uri,
cid: profile.cid,
val: label,
neg: false,
cts: new Date().toISOString(),
},
])
}
async labelPost(label: string, {uri, cid}: {uri: string; cid: string}) {
const ctx = this.pds.ctx
const ctx = this.bsky.ctx
if (!ctx) {
throw new Error('Invalid PDS')
throw new Error('Invalid appview')
}
await ctx.db.db
.insertInto('label')
.values([
{
src: ctx.cfg.labelerDid,
uri,
cid,
val: label,
neg: 0,
cts: new Date().toISOString(),
},
])
.execute()
const labelSrvc = ctx.services.label(ctx.db.getPrimary())
await labelSrvc.createLabels([
{
// @ts-ignore
src: ctx.cfg.labelerDid,
uri,
cid,
val: label,
neg: false,
cts: new Date().toISOString(),
},
])
}
async createMuteList(user: string, name: string): Promise<string> {
@@ -393,3 +483,15 @@ async function getPort(start = 3000) {
}
throw new Error('Unable to find an available port')
}
export const mockTwilio = (pds: TestPds) => {
if (!pds.ctx.phoneVerifier) return
pds.ctx.phoneVerifier.sendCode = async (_number: string) => {
// do nothing
}
pds.ctx.phoneVerifier.verifyCode = async (_number: string, code: string) => {
return code === '000000'
}
}