Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions src/auctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,35 @@ export class AuctionHouse {
const columns = this.db.query<{ name: string }, []>('PRAGMA table_info(auction_artworks)').all().map((c) => c.name)
if (!columns.includes('topic')) this.db.exec("ALTER TABLE auction_artworks ADD COLUMN topic TEXT NOT NULL DEFAULT ''")
this.db.exec('CREATE INDEX IF NOT EXISTS auction_artworks_topic ON auction_artworks(topic, created_at DESC)')

// Archive Anthony's test post privately, then remove it from every public artwork route.
const cleanupId = '0RZW_lLDiS_z_1lM'
const migrationName = 'remove-test-artwork-' + cleanupId
this.db.exec(
'CREATE TABLE IF NOT EXISTS auction_migrations (name TEXT PRIMARY KEY, applied_at INTEGER NOT NULL); ' +
"CREATE TABLE IF NOT EXISTS auction_artwork_archive (" +
"id TEXT PRIMARY KEY, title TEXT NOT NULL, artist TEXT NOT NULL, medium TEXT NOT NULL DEFAULT '', " +
"description TEXT NOT NULL DEFAULT '', image_type TEXT NOT NULL, image BLOB NOT NULL, topic TEXT NOT NULL DEFAULT '', " +
'created_at INTEGER NOT NULL, removed_at INTEGER NOT NULL, reason TEXT NOT NULL)',
)
if (!this.db.query<{ name: string }, [string]>('SELECT name FROM auction_migrations WHERE name = ?').get(migrationName)) {
this.db.exec('BEGIN IMMEDIATE')
try {
const removedAt = Date.now()
this.db.query(
'INSERT OR IGNORE INTO auction_artwork_archive ' +
'(id, title, artist, medium, description, image_type, image, topic, created_at, removed_at, reason) ' +
'SELECT id, title, artist, medium, description, image_type, image, topic, created_at, ?, ? ' +
'FROM auction_artworks WHERE id = ?',
).run(removedAt, 'Anthony requested removal of this test post', cleanupId)
this.db.query('DELETE FROM auction_artworks WHERE id = ?').run(cleanupId)
this.db.query('INSERT INTO auction_migrations (name, applied_at) VALUES (?, ?)').run(migrationName, removedAt)
this.db.exec('COMMIT')
} catch (error) {
this.db.exec('ROLLBACK')
throw error
}
}
}

list(limit = 48, topic?: AuctionTopic): Artwork[] {
Expand Down
35 changes: 35 additions & 0 deletions test/auctions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,4 +222,39 @@ describe('Art Auctions House', () => {
house.db.close()
require('node:fs').rmSync(path, { force: true }); require('node:fs').rmSync(`${path}-wal`, { force: true }); require('node:fs').rmSync(`${path}-shm`, { force: true })
})


it('archives and removes the requested test post once', async () => {
const { Database } = require('bun:sqlite')
const fs = require('node:fs')
const path = require('node:os').tmpdir() + '/auctions-remove-test-post-' + process.pid + '.db'
const id = '0RZW_lLDiS_z_1lM'
const originalImage = Uint8Array.from([1, 2, 3, 4])
const old = new Database(path, { create: true })
old.exec("CREATE TABLE auction_artworks (id TEXT PRIMARY KEY, title TEXT NOT NULL, artist TEXT NOT NULL, medium TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', image_type TEXT NOT NULL, image BLOB NOT NULL, topic TEXT NOT NULL DEFAULT '', created_at INTEGER NOT NULL)")
old.query('INSERT INTO auction_artworks VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)').run(id, 'Test post', 'Anthony', 'PNG', 'test artwork', 'image/png', originalImage, '', 1)
old.close()

const house = new AuctionHouse(path)
expect(house.get(id)).toBeNull()
expect(house.image(id)).toBeNull()
const archived = house.db.query<{ title: string; artist: string; image: Uint8Array; reason: string }, [string]>(
'SELECT title, artist, image, reason FROM auction_artwork_archive WHERE id = ?',
).get(id)!
expect(archived).toMatchObject({ title: 'Test post', artist: 'Anthony', reason: 'Anthony requested removal of this test post' })
expect(new Uint8Array(archived.image)).toEqual(originalImage)

const app = createAuctionApp(house)
const home = await (await app.fetch(new Request('https://auctions.pit.world/'))).text()
expect(home).not.toContain('Test post')
expect((await app.fetch(new Request('https://auctions.pit.world/art/' + id))).status).toBe(404)
expect((await app.fetch(new Request('https://auctions.pit.world/image/' + id))).status).toBe(404)
house.db.close()

const reopened = new AuctionHouse(path)
expect(reopened.get(id)).toBeNull()
expect(reopened.db.query<{ count: number }, [string]>('SELECT COUNT(*) AS count FROM auction_artwork_archive WHERE id = ?').get(id)?.count).toBe(1)
reopened.db.close()
fs.rmSync(path, { force: true }); fs.rmSync(path + '-wal', { force: true }); fs.rmSync(path + '-shm', { force: true })
})
})
Loading