2023-08-07 01:14:11 +00:00
|
|
|
import { type Filter, Sqlite } from '@/deps.ts';
|
2023-08-06 20:03:29 +00:00
|
|
|
import { SignedEvent } from '@/event.ts';
|
2023-07-09 16:47:19 +00:00
|
|
|
|
2023-08-06 17:54:00 +00:00
|
|
|
interface User {
|
|
|
|
pubkey: string;
|
|
|
|
username: string;
|
|
|
|
inserted_at: Date;
|
|
|
|
}
|
2023-07-09 16:47:19 +00:00
|
|
|
|
2023-08-06 17:54:00 +00:00
|
|
|
class DittoDB {
|
|
|
|
#db: Sqlite;
|
2023-07-09 16:47:19 +00:00
|
|
|
|
2023-08-06 17:54:00 +00:00
|
|
|
constructor(db: Sqlite) {
|
|
|
|
this.#db = db;
|
2023-07-09 17:27:10 +00:00
|
|
|
|
2023-08-06 17:54:00 +00:00
|
|
|
this.#db.execute(`
|
2023-08-06 20:03:29 +00:00
|
|
|
CREATE TABLE IF NOT EXISTS events (
|
2023-08-06 17:54:00 +00:00
|
|
|
id TEXT PRIMARY KEY,
|
|
|
|
kind INTEGER NOT NULL,
|
|
|
|
pubkey TEXT NOT NULL,
|
|
|
|
content TEXT NOT NULL,
|
|
|
|
created_at INTEGER NOT NULL,
|
|
|
|
tags TEXT NOT NULL,
|
|
|
|
sig TEXT NOT NULL
|
|
|
|
);
|
|
|
|
|
2023-08-06 20:03:29 +00:00
|
|
|
CREATE INDEX IF NOT EXISTS idx_events_kind ON events(kind);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_events_pubkey ON events(pubkey);
|
2023-08-06 17:54:00 +00:00
|
|
|
|
2023-08-06 20:03:29 +00:00
|
|
|
CREATE TABLE IF NOT EXISTS tags (
|
2023-08-06 17:54:00 +00:00
|
|
|
tag TEXT NOT NULL,
|
|
|
|
value_1 TEXT,
|
|
|
|
value_2 TEXT,
|
|
|
|
value_3 TEXT,
|
|
|
|
event_id TEXT NOT NULL,
|
|
|
|
FOREIGN KEY(event_id) REFERENCES events(id) ON DELETE CASCADE
|
|
|
|
);
|
|
|
|
|
2023-08-06 20:03:29 +00:00
|
|
|
CREATE INDEX IF NOT EXISTS idx_tags_tag ON tags(tag);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_tags_value_1 ON tags(value_1);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_tags_event_id ON tags(event_id);
|
2023-08-06 17:54:00 +00:00
|
|
|
|
2023-08-06 20:03:29 +00:00
|
|
|
CREATE TABLE IF NOT EXISTS users (
|
2023-08-06 17:54:00 +00:00
|
|
|
pubkey TEXT PRIMARY KEY,
|
|
|
|
username TEXT NOT NULL,
|
|
|
|
inserted_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL
|
|
|
|
);
|
|
|
|
|
2023-08-06 20:03:29 +00:00
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_users_username ON users(username);
|
2023-08-06 17:54:00 +00:00
|
|
|
`);
|
|
|
|
}
|
|
|
|
|
|
|
|
insertUser(user: Pick<User, 'pubkey' | 'username'>): void {
|
|
|
|
this.#db.query(
|
|
|
|
'INSERT INTO users(pubkey, username) VALUES (?, ?)',
|
|
|
|
[user.pubkey, user.username],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
getUserByUsername(username: string): User | null {
|
|
|
|
const result = this.#db.query<[string, string, Date]>(
|
|
|
|
'SELECT pubkey, username, inserted_at FROM users WHERE username = ?',
|
|
|
|
[username],
|
|
|
|
)[0];
|
|
|
|
if (!result) return null;
|
|
|
|
return {
|
|
|
|
pubkey: result[0],
|
|
|
|
username: result[1],
|
|
|
|
inserted_at: result[2],
|
|
|
|
};
|
|
|
|
}
|
2023-08-06 20:03:29 +00:00
|
|
|
|
|
|
|
insertEvent(event: SignedEvent): void {
|
|
|
|
this.#db.transaction(() => {
|
|
|
|
this.#db.query(
|
|
|
|
`
|
|
|
|
INSERT INTO events(id, kind, pubkey, content, created_at, tags, sig)
|
|
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
|
|
`,
|
|
|
|
[
|
|
|
|
event.id,
|
|
|
|
event.kind,
|
|
|
|
event.pubkey,
|
|
|
|
event.content,
|
|
|
|
event.created_at,
|
|
|
|
JSON.stringify(event.tags),
|
|
|
|
event.sig,
|
|
|
|
],
|
|
|
|
);
|
|
|
|
|
|
|
|
for (const [tag, value1, value2, value3] of event.tags) {
|
|
|
|
if (['p', 'e', 'q', 'd', 't', 'proxy'].includes(tag)) {
|
|
|
|
this.#db.query(
|
|
|
|
`
|
|
|
|
INSERT INTO tags(event_id, tag, value_1, value_2, value_3)
|
|
|
|
VALUES (?, ?, ?, ?, ?)
|
|
|
|
`,
|
|
|
|
[event.id, tag, value1 || null, value2 || null, value3 || null],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2023-08-07 01:14:11 +00:00
|
|
|
|
|
|
|
getFilter<K extends number = number>(filter: Filter<K>) {
|
|
|
|
}
|
2023-08-06 17:54:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const db = new DittoDB(
|
|
|
|
new Sqlite('data/db.sqlite3'),
|
|
|
|
);
|
2023-08-07 01:14:11 +00:00
|
|
|
|
2023-07-09 17:27:10 +00:00
|
|
|
export { db };
|