diff --git a/data/schema.sql b/data/schema.sql index e6bca01..619bc38 100644 --- a/data/schema.sql +++ b/data/schema.sql @@ -259,6 +259,31 @@ CREATE TABLE subscriber_events ( ); +CREATE VIEW event_details AS +SELECT + events.event_id AS event_id, + events.user_id AS user_id, + events.document_id AS document_id, + events.user_name AS user_name, + events.event_type AS event_type, + events.occurred_at AS occurred_at, + events.created_at AS created_at, + plain_events.message AS plain_message, + raid_events.visitor_count AS raid_visitor_count, + cheer_events.amount AS cheer_amount, + cheer_events.cheer_type AS cheer_type, + cheer_events.message AS cheer_message, + subscriber_events.subscribed_length AS subscriber_length, + subscriber_events.tier AS subscriber_tier, + subscriber_events.message AS subscriber_message, +FROM + events +LEFT JOIN plain_events USING (event_id) +LEFT JOIN raid_events USING (event_id) +LEFT JOIN cheer_events USING (event_id) +LEFT JOIN subscriber_events USING (event_id) +ORDER BY events.occurred_at ASC; + -- }}} -- Specimens {{{ diff --git a/src/datamodels.py b/src/datamodels.py new file mode 100644 index 0000000..32ee5ae --- /dev/null +++ b/src/datamodels.py @@ -0,0 +1,273 @@ +from enum import Enum +from data import Registry, RowModel, Table, RegisterEnum +from data.columns import Integer, String, Timestamp, Column + + +class EventType(Enum): + SUBSCRIBER = 'subscriber', + RAID = 'raid', + CHEER = 'cheer', + PLAIN = 'plain', + + +class DataModel(Registry): + _EventType = RegisterEnum(EventType, 'EventType') + + class UserPreferences(RowModel): + """ + Schema + ------ + CREATE TABLE user_preferences ( + profileid INTEGER PRIMARY KEY REFERENCES user_profiles (profileid) ON DELETE CASCADE, + twitch_name TEXT, + preferences TEXT + ); + """ + _tablename_ = 'user_preferences' + _cache_ = {} + + profileid = Integer(primary=True) + twitch_name = String() + preferences = String() + + class Dreamer(RowModel): + """ + Schema + ------ + CREATE VIEW dreamers AS + SELECT + user_profiles.profileid AS user_id, + user_preferences.twitch_name AS name, + profiles_twitch.userid AS twitch_id, + user_preferences.preferences AS preferences, + user_profiles.created_at AS created_at + FROM + user_profiles + LEFT JOIN profiles_twitch USING (profileid) + LEFT JOIN user_preferences USING (profileid); + """ + _tablename_ = '' + _readonly_ = True + + profileid = Integer(primary=True) + name = String() + twitch_id = Integer() + preferences = String() + created_at = Timestamp() + + class Transaction(RowModel): + """ + Schema + ------ + CREATE TABLE user_wallet ( + transaction_id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + user_id INTEGER NOT NULL REFERENCES user_profiles (profileid) ON DELETE CASCADE, + amount INTEGER NOT NULL, + description TEXT NOT NULL, + reference TEXT, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() + ); + """ + _tablename_ = 'user_wallet' + _cache_ = {} + _immutable_ = True + + transaction_id = Integer(primary=True) + user_id = Integer() + amount = Integer() + description = String() + reference = String() + created_at = Timestamp() + + + class StampType(RowModel): + """ + Schema + ------ + CREATE TABLE stamp_types ( + stamp_type_id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + stamp_type_name TEXT UNIQUE NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() + ); + """ + _tablename_ = 'stamp_types' + _cache_ = {} + + stamp_type_id = Integer(primary=True) + stamp_type_name = String() + created_at = Timestamp() + + class Document(RowModel): + """ + Schema + ------ + CREATE TABLE documents ( + document_id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + document_data VARCHAR NOT NULL, + seal INTEGER NOT NULL, + metadata TEXT + ); + """ + _tablename_ = 'documents' + _cache_ = {} + + document_id = Integer(primary=True) + document_data = Column() + seal = Integer() + metadata = String() + + class DocumentStamp(RowModel): + """ + Schema + ------ + CREATE TABLE document_stamps ( + stamp_id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + document_id INTEGER NOT NULL REFERENCES documents (document_id) ON DELETE CASCADE, + stamp_type INTEGER NOT NULL REFERENCES stamp_types (stamp_type_id) ON DELETE CASCADE, + position_x INTEGER NOT NULL, + position_y INTEGER NOT NULL, + rotation REAL NOT NULL DEFAULT 0, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() + ); + """ + _tablename_ = 'document_stamps' + _cache_ = {} + + stamp_id = Integer(primary=True) + document_id = Integer() + stamp_type = Integer() + position_x = Integer() + position_y = Integer() + rotation: Column[float] = Column() + created_at = Timestamp() + + class Events(RowModel): + """ + Schema + ------ + CREATE TABLE events ( + event_id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + user_id INTEGER NOT NULL REFERENCES user_profiles (profileid) ON DELETE CASCADE, + document_id INTEGER REFERENCES documents (document_id) ON DELETE SET NULL, + user_name TEXT, + event_type EventType NOT NULL, + occurred_at TIMESTAMPTZ NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE (event_id, event_type) + ); + """ + _tablename_ = 'events' + _cache_ = {} + + event_id = Integer(primary=True) + user_id = Integer() + document_id = Integer() + user_name = String() + event_type: Column[EventType] = Column() + occured_at = Timestamp() + created_at = Timestamp() + + plain_events = Table('plain_events') + raid_events = Table('raid_events') + cheer_events = Table('cheer_events') + subscriber_events = Table('subscriber_events') + + class EventDetails(RowModel): + """ + Schema + ------ + CREATE TABLE plain_events ( + event_id integer PRIMARY KEY, + event_type EventType NOT NULL DEFAULT 'plain' CHECK (event_type = 'plain'), + message TEXT NOT NULL, + FOREIGN KEY (event_id, event_type) REFERENCES events (event_id, event_type) + ); + + CREATE TABLE raid_events ( + event_id integer PRIMARY KEY, + event_type EventType NOT NULL DEFAULT 'raid' CHECK (event_type = 'raid'), + visitor_count INTEGER NOT NULL, + FOREIGN KEY (event_id, event_type) REFERENCES events (event_id, event_type) + ); + + CREATE TABLE cheer_events ( + event_id integer PRIMARY KEY, + event_type EventType NOT NULL DEFAULT 'cheer' CHECK (event_type = 'cheer'), + amount INTEGER NOT NULL, + cheer_type TEXT, + message TEXT, + FOREIGN KEY (event_id, event_type) REFERENCES events (event_id, event_type) + ); + + CREATE TABLE subscriber_events ( + event_id integer PRIMARY KEY, + event_type EventType NOT NULL DEFAULT 'subscriber' CHECK (event_type = 'subscriber'), + subscribed_length INTEGER NOT NULL, + tier INTEGER NOT NULL, + message TEXT, + FOREIGN KEY (event_id, event_type) REFERENCES events (event_id, event_type) + ); + + CREATE VIEW event_details AS + SELECT + events.event_id AS event_id, + events.user_id AS user_id, + events.document_id AS document_id, + events.user_name AS user_name, + events.event_type AS event_type, + events.occurred_at AS occurred_at, + events.created_at AS created_at, + plain_events.message AS plain_message, + raid_events.visitor_count AS raid_visitor_count, + cheer_events.amount AS cheer_amount, + cheer_events.cheer_type AS cheer_type, + cheer_events.message AS cheer_message, + subscriber_events.subscribed_length AS subscriber_length, + subscriber_events.tier AS subscriber_tier, + subscriber_events.message AS subscriber_message, + FROM + events + LEFT JOIN plain_events USING (event_id) + LEFT JOIN raid_events USING (event_id) + LEFT JOIN cheer_events USING (event_id) + LEFT JOIN subscriber_events USING (event_id) + ORDER BY events.occurred_at ASC; + """ + _tablename_ = 'event_details' + _readonly_ = True + + event_id = Integer(primary=True) + user_id = Integer() + document_id = Integer() + user_name = String() + event_type: Column[EventType] = Column() + occurred_at = Timestamp() + created_at = Timestamp() + plain_message = String() + raid_visitor_count = Integer() + cheer_amount = Integer() + cheer_type = String() + cheer_message = String() + subscriber_length = Integer() + subscriber_tier = Integer() + subscriber_message = String() + + + class Specimen(RowModel): + """ + Schema + ------ + CREATE TABLE user_specimens ( + specimen_id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + owner_id INTEGER NOT NULL REFERENCES user_profiles (profileid) ON DELETE CASCADE, + born_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + forgotten_at TIMESTAMPTZ + ); + """ + _tablename_ = 'user_specimens' + _cache_ = {} + + specimen_id = Integer(primary=True) + owner_id = Integer(primary=True) + born_at = Timestamp() + forgotten_at = Timestamp()