summaryrefslogtreecommitdiff
path: root/src/db.py
blob: 78b10310abd1f62312171d02d3d710257b991356 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import dataclasses
import datetime
import ipaddress as ipaddr
import uuid

import asyncpg
import quart as q


def get_db() -> asyncpg.Pool:
    return q.current_app.pool  # pyright: ignore[reportAttributeAccessIssue]


@dataclasses.dataclass
class BlogPost:
    id: uuid.UUID
    title: str
    description: str | None
    text: str
    original: str
    created_at: datetime.datetime
    public: bool

    @classmethod
    def from_record(cls, record: asyncpg.Record):
        return cls(
            id=record["id"],
            title=record["title"],
            description=record.get("description"),
            text=record["text"],
            original=record["original"],
            created_at=record["created_at"],
            public=record["public"],
        )


@dataclasses.dataclass
class BlogComment:
    id: uuid.UUID
    author: str
    text: str
    created_at: datetime.datetime
    post: uuid.UUID | None = None
    video: uuid.UUID | None = None

    @classmethod
    def from_record(cls, record: asyncpg.Record):
        return cls(
            id=record["id"],
            author=record["author"],
            text=record["text"],
            created_at=record["created_at"],
            post=record.get("post_id"),
            video=record.get("video_id"),
        )


@dataclasses.dataclass
class AdminLogin:
    id: int
    addr: ipaddr.IPv4Interface | ipaddr.IPv6Interface
    created_at: datetime.datetime

    @classmethod
    def from_record(cls, record: asyncpg.Record):
        return cls(
            id=record["id"],
            addr=record["ipaddr"],
            created_at=record["created_at"],
        )


async def get_post(post: str, *, public_only: bool = True):
    query = "SELECT * FROM posts WHERE posts.id = $1"
    if public_only:
        query += " AND posts.public = true"
    query += ";"

    pool = get_db()
    async with pool.acquire() as conn:
        res = await conn.fetch(query, post)
        if not res:
            return None

        return BlogPost.from_record(res[0])


async def get_posts(*, public_only: bool = True):
    query = "SELECT * FROM posts"
    if public_only:
        query += " WHERE posts.public = true"
    query += ";"

    pool = get_db()
    async with pool.acquire() as conn:
        res = await conn.fetch(query)
        return [BlogPost.from_record(r) for r in res]


async def get_post_comments(post: str):
    pool = get_db()
    async with pool.acquire() as conn:
        res = await conn.fetch(
            "SELECT * FROM comments WHERE comments.post_id = $1 ORDER BY comments.created_at",
            post,
        )
        finals = [BlogComment.from_record(r) for r in res]
        return finals