backend: prepare to adding posts to database

This commit is contained in:
OleSTEEP 2025-10-05 22:07:45 +03:00
parent 59d092c9d0
commit c95aed01b5
4 changed files with 65 additions and 39 deletions

View file

@ -67,4 +67,4 @@ async def upload_screenshot(scrshot: Annotated[bytes, File()], filename: str):
@app.post("/api/file") @app.post("/api/file")
async def upload_file(file: Annotated[bytes, File()], filename: str): async def upload_file(file: Annotated[bytes, File()], filename: str):
return {"file_size": save_file(file, "files", filename)} return {"file_size": save_file(file, "files", filename)}

View file

@ -1,7 +1,9 @@
from datetime import datetime
import sqlite3 import sqlite3
import json
from utils import asset from utils import asset
from vntypes import Mark from vntypes import *
class VNDB: class VNDB:
@ -14,7 +16,8 @@ class VNDB:
CREATE TABLE IF NOT EXISTS marks ( CREATE TABLE IF NOT EXISTS marks (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
type TEXT NOT NULL, type TEXT NOT NULL,
value TEXT NOT NULL value TEXT NOT NULL,
UNIQUE(id, value)
); );
''') ''')
@ -23,7 +26,8 @@ class VNDB:
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL, title TEXT NOT NULL,
description TEXT NOT NULL, description TEXT NOT NULL,
thumbnail TEXT NOT NULL thumbnail TEXT NOT NULL,
UNIQUE(id, title, description, thumbnail)
); );
''') ''')
@ -31,58 +35,77 @@ class VNDB:
CREATE TABLE IF NOT EXISTS novels ( CREATE TABLE IF NOT EXISTS novels (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL, title TEXT NOT NULL,
author INTEGER NOT NULL author INTEGER NOT NULL,
UNIQUE(id, title, author)
); );
''') ''')
cursor.execute(''' cursor.execute('''
CREATE TABLE IF NOT EXISTS posts_log ( CREATE TABLE IF NOT EXISTS posts_log (
novel INTEGER NOT NULL,
novel INTEGER NOT NULL, channel INTEGER NOT NULL,
marks JSON NOT NULL,
channel INTEGER NOT NULL, title TEXT NOT NULL,
description TEXT NOT NULL,
marks JSON NOT NULL, author INTEGER NOT NULL,
files_on_disk JSON NOT NULL,
title TEXT NOT NULL, post_info JSON,
post_at INTEGER NOT NULL,
description TEXT NOT NULL, created_at INTEGER NOT NULL
author INTEGER NOT NULL,
files_on_disk JSON NOT NULL,
post_info JSON,
post_at INTEGER NOT NULL,
created_at INTEGER NOT NULL
); );
''') ''')
connection.commit() connection.commit()
def __execute(self, sql: str, params: tuple): def __execute(self, sql: str, params: tuple = ()):
with sqlite3.connect(self.__db_name) as connection: with sqlite3.connect(self.__db_name) as connection:
connection.cursor().execute(sql, params) connection.cursor().execute(sql, params)
connection.commit() connection.commit()
def __fetch(self, sql: str, params: tuple): def __fetch(self, sql: str, params: tuple = ()):
with sqlite3.connect(self.__db_name) as connection: with sqlite3.connect(self.__db_name) as connection:
cursor = connection.cursor() cursor = connection.cursor()
cursor.execute(sql, params) cursor.execute(sql, params)
return cursor.fetchall() return cursor.fetchall()
def insert_mark(self, type: str, value: str):
self.__execute("INSERT INTO marks (type, value) "
"VALUES (?, ?)", (type, value))
def search_mark(self, query: Mark): def search_author(self, title: str):
return self.__fetch("SELECT type, value FROM marks " return self.__fetch("SELECT * FROM authors "
"WHERE title LIKE ?", (title,))
def search_mark(self, mark: Mark):
return self.__fetch("SELECT * FROM marks "
"WHERE value LIKE ? " "WHERE value LIKE ? "
"AND type = ?", ('%'+query.value+'%',query.type)) "AND type = ?", ('%'+mark.value+'%',mark.type))
def insert_novel(self, title: str, author_id: int): def search_novel(self, title: str):
self.__execute("INSERT INTO novels (title, author) " return self.__fetch("SELECT * FROM novels "
"VALUES (?, ?)", (title, author_id)) "WHERE title LIKE ? ", (title,))
def insert_author(self, title: str, desc: str, thumb: str): def insert_author(self, title: str, desc: str, thumb: str):
self.__execute("INSERT INTO authors (title, description, thumbnail) " self.__execute("INSERT INTO authors (title, description, thumbnail) "
"VALUES (?, ?, ?)", (title, desc, thumb)) "VALUES (?, ?, ?)", (title, desc, thumb))
def insert_mark(self, type: str, value: str):
self.__execute("INSERT INTO marks (type, value) "
"VALUES (?, ?)", (type, value))
def insert_novel(self, novel: Novel):
self.__execute("INSERT INTO novels (title, author) "
f"SELECT {novel.title}, {novel.author_id} "
f"WHERE NOT EXISTS(SELECT 1 FROM novels WHERE title = {novel.title} AND author = {novel.author_id});")
# FIXME: SQL Types
def insert_post(self, full_novel: FullNovel):
self.insert_novel(full_novel.data)
self.__execute("INSERT INTO posts_log (novel, channel, marks, title, description, author, files_on_disk, post_at, created_at) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
(self.search_novel(full_novel.data.title)[0],
full_novel.data.tg_channel,
json.dumps(full_novel.data.marks),
full_novel.data.title,
full_novel.data.description,
full_novel.data.author_id,
json.dumps(full_novel.files),
full_novel.data.post_at,
datetime.now()))

View file

@ -14,14 +14,14 @@ class NovelFile(BaseModel):
class Novel(BaseModel): class Novel(BaseModel):
title: str title: str
description: str description: str
author_id: int
vndb: int | None = None vndb: int | None = None
hours_to_read: int hours_to_read: int
tags: list[str] marks: list[Mark]
genres: list[str]
badges: list[str]
tg_channel: int # maybe not here
tg_post: str | None = None #url::Url tg_post: str | None = None #url::Url
post_at: datetime | None = None post_at: datetime | None = None

View file

@ -53,11 +53,14 @@ CREATE TABLE IF NOT EXISTS posts_log (
-- <POST_LINK> - ссылка на пост в соответствующем канале с файлами, может -- <POST_LINK> - ссылка на пост в соответствующем канале с файлами, может
-- быть null. Не должно быть null, если post_info != NULL (то есть если уже запостили). -- быть null. Не должно быть null, если post_info != NULL (то есть если уже запостили).
files_on_disk JSON NOT NULL, files_on_disk JSON NOT NULL,
-- не NULL, если пост успешно запостили. -- не NULL, если пост успешно запостили.
-- {"link": <ссылка на пост>} -- {"link": <ссылка на пост>}
post_info JSON, post_info JSON,
-- Когда ВН должна быть запощена, second-precise unix timestamp. -- Когда ВН должна быть запощена, second-precise unix timestamp.
post_at INTEGER NOT NULL, post_at INTEGER NOT NULL,
-- Когда запись в бд была создана, second-precise unix timestamp. -- Когда запись в бд была создана, second-precise unix timestamp.
created_at INTEGER NOT NULL created_at INTEGER NOT NULL
); );