Compare commits
4 Commits
8421c5359d
...
5efcdd6709
| Author | SHA1 | Date | |
|---|---|---|---|
| 5efcdd6709 | |||
| 0adccaae02 | |||
| a7afa5001d | |||
| d271248812 |
@@ -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 {{{
|
-- Specimens {{{
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ async def main():
|
|||||||
config=conf,
|
config=conf,
|
||||||
initial_extensions=[
|
initial_extensions=[
|
||||||
'core',
|
'core',
|
||||||
|
'twitch',
|
||||||
'modules',
|
'modules',
|
||||||
],
|
],
|
||||||
web_client=session,
|
web_client=session,
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ class Connector:
|
|||||||
return AsyncConnectionPool(
|
return AsyncConnectionPool(
|
||||||
self._conn_args,
|
self._conn_args,
|
||||||
open=False,
|
open=False,
|
||||||
min_size=4,
|
min_size=1,
|
||||||
max_size=8,
|
max_size=4,
|
||||||
configure=self._setup_connection,
|
configure=self._setup_connection,
|
||||||
kwargs=self._conn_kwargs
|
kwargs=self._conn_kwargs
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from psycopg import AsyncCursor, sql
|
from psycopg import AsyncCursor, sql
|
||||||
from psycopg.abc import Query, Params
|
from psycopg.abc import Query, Params
|
||||||
from psycopg._encodings import pgconn_encoding
|
from psycopg._encodings import conn_encoding
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ class AsyncLoggingCursor(AsyncCursor):
|
|||||||
elif isinstance(query, (sql.SQL, sql.Composed)):
|
elif isinstance(query, (sql.SQL, sql.Composed)):
|
||||||
msg = query.as_string(self)
|
msg = query.as_string(self)
|
||||||
elif isinstance(query, bytes):
|
elif isinstance(query, bytes):
|
||||||
msg = query.decode(pgconn_encoding(self._conn.pgconn), 'replace')
|
msg = query.decode(conn_encoding(self._conn.pgconn), 'replace')
|
||||||
else:
|
else:
|
||||||
msg = repr(query)
|
msg = repr(query)
|
||||||
return msg
|
return msg
|
||||||
|
|||||||
273
src/datamodels.py
Normal file
273
src/datamodels.py
Normal file
@@ -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()
|
||||||
@@ -203,7 +203,7 @@ class LionBot(Bot):
|
|||||||
# TODO: Some of these could have more user-feedback
|
# TODO: Some of these could have more user-feedback
|
||||||
logger.debug(f"Handling command error for {ctx}: {exception}")
|
logger.debug(f"Handling command error for {ctx}: {exception}")
|
||||||
if isinstance(ctx.command, HybridCommand) and ctx.command.app_command:
|
if isinstance(ctx.command, HybridCommand) and ctx.command.app_command:
|
||||||
cmd_str = ctx.command.app_command.to_dict()
|
cmd_str = ctx.command.app_command.to_dict(self.tree)
|
||||||
else:
|
else:
|
||||||
cmd_str = str(ctx.command)
|
cmd_str = str(ctx.command)
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ class LionTree(CommandTree):
|
|||||||
return
|
return
|
||||||
|
|
||||||
set_logging_context(action=f"Run {command.qualified_name}")
|
set_logging_context(action=f"Run {command.qualified_name}")
|
||||||
logger.debug(f"Running command '{command.qualified_name}': {command.to_dict()}")
|
logger.debug(f"Running command '{command.qualified_name}': {command.to_dict(self)}")
|
||||||
try:
|
try:
|
||||||
await command._invoke_with_namespace(interaction, namespace)
|
await command._invoke_with_namespace(interaction, namespace)
|
||||||
except AppCommandError as e:
|
except AppCommandError as e:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
this_package = 'modules'
|
this_package = 'modules'
|
||||||
|
|
||||||
active = [
|
active = [
|
||||||
|
'.profiles',
|
||||||
'.sysadmin',
|
'.sysadmin',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ from discord.ext import commands as cmds
|
|||||||
from twitchAPI.helper import first
|
from twitchAPI.helper import first
|
||||||
from twitchAPI.type import AuthScope
|
from twitchAPI.type import AuthScope
|
||||||
import twitchio
|
import twitchio
|
||||||
from twitchio.ext import commands
|
|
||||||
from twitchio import User
|
|
||||||
from twitchAPI.object.api import TwitchUser
|
from twitchAPI.object.api import TwitchUser
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,8 @@ import discord
|
|||||||
from discord.ext import commands as cmds
|
from discord.ext import commands as cmds
|
||||||
|
|
||||||
from twitchAPI.oauth import UserAuthenticator
|
from twitchAPI.oauth import UserAuthenticator
|
||||||
from twitchAPI.twitch import AuthType, Twitch
|
from twitchAPI.twitch import Twitch
|
||||||
from twitchAPI.type import AuthScope
|
from twitchAPI.type import AuthScope
|
||||||
import twitchio
|
|
||||||
from twitchio.ext import commands
|
from twitchio.ext import commands
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user