117 lines
3.9 KiB
Python
117 lines
3.9 KiB
Python
import os
|
|
import secrets
|
|
import sqlite3
|
|
from user_handler import UserHandler
|
|
from werkzeug.datastructures.file_storage import FileStorage
|
|
import re
|
|
|
|
|
|
class SolutionHandler:
|
|
connection: sqlite3.Connection = sqlite3.connect("../data/database.db", check_same_thread=False)
|
|
cursor: sqlite3.Cursor = connection.cursor()
|
|
|
|
# Save solution
|
|
@classmethod
|
|
def submit_solution(cls, files: list[FileStorage], bounty_identifier: int, creator_identifier: int):
|
|
solution_id = secrets.token_urlsafe(40)
|
|
os.mkdir(f"../assets/solutions/{solution_id}/")
|
|
for file in files:
|
|
print(file.filename)
|
|
if not file.filename:
|
|
file.filename = secrets.token_urlsafe(5)
|
|
file.filename = "".join(re.findall("[a-zA-Z 0-9-./]", file.filename))
|
|
file.filename = file.filename.replace("/", r"|")
|
|
file.save(f"../assets/solutions/{solution_id}/{file.filename}")
|
|
|
|
cls.cursor.execute(
|
|
f"""
|
|
INSERT INTO solutions(user_id, bounty_id, solution_id)
|
|
values(?, ?, ?)
|
|
""",
|
|
(creator_identifier, bounty_identifier, solution_id)
|
|
)
|
|
cls.connection.commit()
|
|
|
|
# Get solution by id
|
|
@staticmethod
|
|
def get_solution_by_id(solution_id: str):
|
|
path = f"../assets/solutions/{solution_id}/"
|
|
if not os.path.isdir(path):
|
|
raise KeyError("Solution doesn't exist")
|
|
formated_solutions: dict[str, str | dict] = {}
|
|
file_paths = os.listdir(path)
|
|
for file_path in file_paths:
|
|
current_folder = formated_solutions
|
|
for folder in file_path.split("|")[:-1]:
|
|
print(folder)
|
|
current_folder[folder] = {}
|
|
current_folder: dict = current_folder[folder]
|
|
file_name = file_path.split("|")[-1]
|
|
try:
|
|
with open(path + file_path, "r") as file:
|
|
current_folder[file_name] = file.read()
|
|
except UnicodeDecodeError:
|
|
current_folder[file_name] = "<NOT-TEXT>"
|
|
|
|
return formated_solutions
|
|
|
|
|
|
@classmethod
|
|
def get_solution_list(cls, identifier: int) -> list[dict]:
|
|
solutions = cls.cursor.execute(
|
|
f"""
|
|
SELECT user_id, solution_id FROM solutions
|
|
WHERE bounty_id = ?;
|
|
""",
|
|
(identifier, )
|
|
).fetchall()
|
|
return [
|
|
{
|
|
"user_id": solution[0],
|
|
"creator_display_name": UserHandler.get_display_name(solution[0]),
|
|
"solution_id": solution[1],
|
|
"likes": cls.get_likes(solution[1])
|
|
} for solution in solutions
|
|
]
|
|
|
|
@classmethod
|
|
def like(cls, solution_id: int, user_id: int):
|
|
cls.cursor.execute(
|
|
f"""
|
|
INSERT INTO solution_likes(user_id, solution_id) values(?, ?)
|
|
""",
|
|
(user_id, solution_id)
|
|
)
|
|
cls.connection.commit()
|
|
|
|
@classmethod
|
|
def unlike(cls, solution_id: int, user_id: int):
|
|
cls.cursor.execute(
|
|
f"""
|
|
DELETE FROM solution_likes WHERE solution_id = ? AND user_id = ?
|
|
""",
|
|
(solution_id, user_id)
|
|
)
|
|
cls.connection.commit()
|
|
|
|
@classmethod
|
|
def get_likes(cls, solution_id: int) -> int:
|
|
likes = cls.cursor.execute(
|
|
f"""
|
|
SELECT COUNT(*) FROM solution_likes WHERE solution_id = ?
|
|
""",
|
|
(solution_id, )
|
|
).fetchall()[0]
|
|
return likes[0] if likes else 0
|
|
|
|
@classmethod
|
|
def has_user_liked(cls, solution_id: int, user_id: int) -> bool:
|
|
|
|
likes = cls.cursor.execute(
|
|
f"""
|
|
SELECT 1 FROM solution_likes WHERE solution_id = ?
|
|
""",
|
|
(solution_id, )
|
|
).fetchall()
|
|
return bool(likes)
|