import json from flask import Flask from .databaseController import DatabaseController from .endpoints.query import Query, QueryOld from .endpoints.command import Command, CommandOld from .endpoints.commands import Commands, CommandsOld from .endpoints.post import GetPost, GetPostOld from .endpoints.posts import GetPosts, GetPostsOld from .endpoints.new_query import NewQuery, NewQueryOld from .endpoints.set_action import SetAction, SetActionOld from .endpoints.posts_count import GetPostsCount, GetPostsCountOld from .endpoints.account_stats import AccountStats, AccountStatsOld class Database: db : DatabaseController = None app : Flask = None def __init__(self, api, database_name, database_path) -> None: self.app = api.app if database_name in self.app.databases: del self.app.databases[database_name] self.reload_data(database_path) self.app.databases[database_name] = self if database_name == "Archive": api.add_resource(Query, "/Archive/Query") api.add_resource(NewQuery, "/Archive/NewQuery") api.add_resource(Command, "/Archive/Command") api.add_resource(Commands, "/Archive/Commands") api.add_resource(GetPost, "/Archive/GetPost/") api.add_resource(GetPosts, "/Archive/GetPosts") api.add_resource(GetPostsCount, "/Archive/GetPosts/Count") api.add_resource(AccountStats, "/Archive/AccountStats") api.add_resource(SetAction, "/Archive/SetAction") elif database_name == "ArchiveOld": api.add_resource(QueryOld, "/ArchiveOld/Query") api.add_resource(NewQueryOld, "/ArchiveOld/NewQuery") api.add_resource(CommandOld, "/Archive/Command") api.add_resource(CommandsOld, "/Archive/Commands") api.add_resource(GetPostOld, "/ArchiveOld/GetPost/") api.add_resource(GetPostsOld, "/ArchiveOld/GetPosts") api.add_resource(GetPostsCountOld, "/ArchiveOld/GetPosts/Count") api.add_resource(AccountStatsOld, "/ArchiveOld/AccountStats") api.add_resource(SetActionOld, "/ArchiveOld/SetAction") def get_accounts(self): query = f''' SELECT x_handle, id FROM accounts ORDER BY x_handle ASC''' return self.db.run_query(query) def get_account_stats(self): query = '''SELECT x_handle, SUM(IIF(x_posts.action_taken = 0, 1, 0)) as undecided, SUM(IIF(x_posts.action_taken = 1, 1, 0)) as approved, SUM(IIF(x_posts.action_taken = 2, 1, 0)) as deleted, SUM(IIF(x_posts.action_taken = 3, 1, 0)) as hidden, SUM(IIF(x_post_details.id is NULL, 1, 0)) as invalid FROM accounts LEFT JOIN x_posts on accounts.id = x_posts.account_id LEFT JOIN x_post_details on x_post_details.id = x_posts.id WHERE accounts.download_mode != 4 GROUP BY account_id ORDER BY x_handle''' return self.db.run_query(query) def get_post(self, id): query = f'''SELECT x_posts.id, cast(x_posts.id as TEXT) as id_str, x_posts.error_id, x_posts.action_taken, x_post_details.text, x_post_details.files, x_post_details.date, accounts.x_handle, accounts.rating from x_posts LEFT JOIN x_post_details ON x_posts.id = x_post_details.id LEFT JOIN accounts ON x_posts.account_id = accounts.id WHERE x_posts.id = {id} LIMIT 1''' result = self.db.run_query(query) if len(result) == 0: return None else: #return most recent post return result[-1] def build_where_query(self, artist, actions_taken = [0, 1, 2, 3], last_id = -1, include_ratings = ["SFW", "NSFW"]): where_query = "WHERE x_post_details.id NOT NULL AND x_posts.error_id = 0" if last_id != -1: where_query += f" AND x_posts.id < {last_id}" if actions_taken != [0, 1, 2, 3]: where_query += " AND (" + " OR ".join([f"x_posts.action_taken = {action}" for action in actions_taken]) + ")" if include_ratings != ["SFW", "NSFW", "NSFL"]: where_query += " AND (" + " OR ".join([f'accounts.rating = "{rating}"' for rating in include_ratings]) + ")" if artist is not None and artist != "": where_query += f' AND accounts.x_handle = "{artist}"' return where_query def get_posts_count(self, artist, actions_taken = [0, 1, 2, 3], last_id = -1, include_ratings = ["SFW", "NSFW"]): where_query = self.build_where_query(artist, actions_taken, last_id, include_ratings) query = f''' SELECT count(*) as count FROM x_posts LEFT JOIN x_post_details ON x_posts.id = x_post_details.id LEFT JOIN accounts ON x_posts.account_id = accounts.id {where_query}''' result = self.db.run_query(query) return result[0]["count"] def get_posts(self, num_posts, artist, actions_taken = [0, 1, 2, 3], last_id = -1, offset = 0, include_ratings = ["SFW", "NSFW"], order = "DESC"): num_posts = max(1, min(num_posts, 100)) order_by = "RANDOM()" if order == "RAND" else "x_posts.id ASC" if order == "ASC" else "x_posts.id DESC" where_query = self.build_where_query(artist, actions_taken, last_id, include_ratings) query = f''' SELECT x_posts.id, cast(x_posts.id as TEXT) as id_str, x_posts.action_taken, x_post_details.text, x_post_details.files, x_post_details.date, accounts.x_handle, accounts.rating FROM x_posts LEFT JOIN x_post_details ON x_posts.id = x_post_details.id LEFT JOIN accounts ON x_posts.account_id = accounts.id {where_query} ORDER BY {order_by} LIMIT {num_posts} OFFSET {offset}''' return self.db.run_query(query) def wrap_query_response(self, result, mode = "json"): if result is None: response = self.app.response_class(status=400) else: if mode == "json": response = self.app.response_class( response=json.dumps(result, ensure_ascii=False, indent=1), status=200, mimetype='application/json' ) elif mode == "text": response = self.app.response_class( response=str(result), status=200, mimetype='text/plain' ) response.headers.add("Access-Control-Allow-Origin", "*") return response def reload_data(self, database_path): self.db = DatabaseController(database_path)