2023-10-17 18:25:38 +02:00
## MAIN FUNCTIONS FILE FOR BACK-BACKEND OF FLASK
import mariadb as sql
from os import environ
2023-10-19 13:25:59 +02:00
import time , re
2023-10-20 00:26:56 +02:00
from config import *
2023-10-17 18:25:38 +02:00
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
## params populated with environment variables, get data from config if environment variables not set
2023-10-17 18:25:38 +02:00
conn_params = {
2023-10-19 19:39:54 +02:00
" user " : environ . get ( ' MARIADB_USER ' ) if environ . get ( ' MARIADB_USER ' ) else MARIADB_USER ,
" password " : environ . get ( ' MARIADB_PASSWORD ' ) if environ . get ( ' MARIADB_PASSWORD ' ) else MARIADB_PASSWORD ,
" host " : environ . get ( ' MARIADB_HOST ' ) if environ . get ( ' MARIADB_HOST ' ) else MARIADB_HOST ,
2023-10-20 00:26:56 +02:00
" database " : environ . get ( ' MARIADB_DB ' ) if environ . get ( ' MARIADB_DB ' ) else MARIADB_DB
2023-10-17 18:25:38 +02:00
}
class db :
def __init__ ( self ) :
self . conn = sql . connect ( * * conn_params )
2023-10-18 12:55:20 +02:00
self . conn . autocommit = True
2023-10-17 18:25:38 +02:00
self . cur = self . conn . cursor ( )
## Creates all archives, if they don't exist already
## Called only on startup, hence the name
def startup ( self ) :
2023-10-18 12:55:20 +02:00
self . cur . execute ( """ CREATE TABLE IF NOT EXISTS Archs(
2023-10-17 18:25:38 +02:00
ID int PRIMARY KEY AUTO_INCREMENT ,
NAME text NOT NULL ,
2023-10-19 13:25:59 +02:00
HASH text NOT NULL UNIQUE ,
2023-10-20 13:13:22 +02:00
SIZE bigint NOT NULL ,
2023-10-17 18:25:38 +02:00
IMPORTED int ,
CATEGORY int ,
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
OWNER int ) ; """ )
2023-10-18 12:55:20 +02:00
self . cur . execute ( """ CREATE TABLE IF NOT EXISTS Users(
2023-10-17 18:25:38 +02:00
ID int PRIMARY KEY AUTO_INCREMENT ,
2023-10-19 19:14:18 +02:00
UNAME text NOT NULL UNIQUE ,
2023-10-17 18:25:38 +02:00
DNAME text NOT NULL ,
CREATED int NOT NULL ,
STATE text ,
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
PASSHASH text NOT NULL ) ; """ )
2023-10-18 12:55:20 +02:00
self . cur . execute ( """ CREATE TABLE IF NOT EXISTS Sessions(
2023-10-17 18:25:38 +02:00
ID int PRIMARY KEY AUTO_INCREMENT ,
2023-10-19 19:14:18 +02:00
SESSKEY text NOT NULL UNIQUE ,
2023-10-18 12:55:20 +02:00
USERID int NOT NULL ,
2023-10-17 18:25:38 +02:00
CREATED int NOT NULL ,
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
LIFE int ) ; """ )
2023-10-18 12:55:20 +02:00
self . cur . execute ( """ CREATE TABLE IF NOT EXISTS Cats(
2023-10-17 18:25:38 +02:00
ID int PRIMARY KEY AUTO_INCREMENT ,
CATEGORY text NOT NULL ,
PARENT int ,
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
DESCRIPTION text ) ; """ )
2023-10-18 12:55:20 +02:00
self . cur . execute ( """ CREATE TABLE IF NOT EXISTS ArchLab(
2023-10-17 18:25:38 +02:00
ID int PRIMARY KEY AUTO_INCREMENT ,
ARCHID int NOT NULL ,
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
LABID int NOT NULL ) ; """ )
2023-10-19 13:25:59 +02:00
self . cur . execute ( """ CREATE TABLE IF NOT EXISTS CatLabType(
ID int PRIMARY KEY AUTO_INCREMENT ,
CATID int NOT NULL ,
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
LABID int NOT NULL ) ; """ )
2023-10-18 12:55:20 +02:00
self . cur . execute ( """ CREATE TABLE IF NOT EXISTS Labs(
2023-10-17 18:25:38 +02:00
ID int PRIMARY KEY AUTO_INCREMENT ,
LABEL text NOT NULL ,
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
TYPE int NOT NULL ) ; """ )
2023-10-18 12:55:20 +02:00
self . cur . execute ( """ CREATE TABLE IF NOT EXISTS LabType(
2023-10-17 18:25:38 +02:00
ID int PRIMARY KEY AUTO_INCREMENT ,
NAME text NOT NULL ,
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
DESCRIPTION text ) ; """ )
2023-10-18 12:55:20 +02:00
## Gets the passhash from a specific user
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
## OUTPUT: (If user exists) bool=True, ID:int, passhash:str
## (If user does not exist) bool=False, Exception:str
2023-10-18 12:55:20 +02:00
def get_passhash ( self , username : str ) :
self . cur . execute ( f " SELECT ID,PASSHASH FROM Users WHERE UNAME= ' { username } ' " )
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
resp = self . cur . fetchone ( )
if not resp :
return False , " The user does not exist! " , None
return True , resp [ 0 ] , resp [ 1 ]
2023-10-18 12:55:20 +02:00
## Checks if sesskey exists and is not expired
## OUTPUT: (if valiid) bool=True, USERID:str
## (in invalid) bool=False, str=""
def check_sesskey ( self , sesskey : str ) :
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
self . cur . execute ( f " SELECT SESSKEY,USERID,CREATED,LIFE FROM Sessions WHERE SESSKEY= ' { sesskey } ' " )
2023-10-18 12:55:20 +02:00
entry = self . cur . fetchone ( )
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
if entry and sesskey in entry and time . time ( ) < entry [ 2 ] + entry [ 3 ] :
2023-10-18 12:55:20 +02:00
return True , entry [ 1 ]
else :
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
return False , " The session key is expired or does not exist! "
2023-10-18 12:55:20 +02:00
## Sets a session key. That's it.
def set_sesskey ( self , sesskey : str , userid : int , lifetime : int ) :
self . cur . execute ( f " INSERT INTO Sessions(SESSKEY,USERID,CREATED,LIFE) VALUES( ' { sesskey } ' , { userid } , { time . time ( ) } , { lifetime } ) " )
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
## Removes the session key from the database (doesn't delete the cookie)
2023-10-20 15:27:25 +02:00
def logout_user ( self , sesskey : str ) :
self . cur . execute ( f " DELETE FROM Sessions WHERE SESSKEY= ' { sesskey } ' " )
2023-10-18 12:55:20 +02:00
## Gets and returns all user info about one (1) user
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
## OUTPUT: (if successful) bool=True, tuple=(ID:int,UNAME:str,DNAME:str,CREATED:int,STATE:text,PASSHASH:text)
## (if unsuccessful) bool=False, error:str
def get_user_info ( self , identifier ) :
match identifier :
case int ( ) :
query = f " ID= { identifier } "
case str ( ) :
query = f " UNAME= ' { identifier } ' "
case _ :
return False , " Wrong identifier type! "
2023-10-17 18:25:38 +02:00
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
self . cur . execute ( f " SELECT * FROM Users WHERE { query } " )
return True , self . cur . fetchone ( )
2023-10-20 16:50:05 +02:00
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
## updates a value of a user in the database (if allowed in the dictionary)
## OUTPUT: (if successful) bool=True, str="Updated"
## (if unsuccessful) bool=False, str="Not allowed"
def update_user_info ( self , userid : int , update_type : str , value ) :
allowed_types = { " DNAME " : str , " PASSHASH " : str } # only allow to edit these columns!
2023-10-20 16:50:05 +02:00
if update_type . upper ( ) not in allowed_types :
return False , " Not allowed "
self . cur . execute ( f """ UPDATE Users SET { update_type } = { value if allowed_types [ update_type ] == int else f " ' { value } ' " } WHERE ID= { userid } """ )
return True , " Updated "
2023-10-19 13:25:59 +02:00
## Checks information for errors and adds archive to the DB
## OUTPUT: (if successful) res:bool=True, ID:int
## (if unsuccessful) res:bool=False, str
def add_archive ( self , archive : dict ) :
# Check everything for errors or malicious things
archive [ " hash " ] = archive [ " hash " ] . upper ( )
if not re . match ( ' [A-Z0-9] {40} ' , archive [ " hash " ] ) :
return False , " Hash needs to be 40 characters in hexadecimal (SHA-1). "
2023-10-19 18:24:36 +02:00
if re . match ( ' .*[^A-Za-z0-9 \ . +_-].* ' , archive [ " name " ] ) :
2023-10-19 13:25:59 +02:00
return False , " The name contains illegal characters. Allowed chars: ' [A-Za-z0-9 \ . _-] ' "
print ( archive [ " name " ] )
curtime = time . time ( )
try :
self . cur . execute ( f " INSERT INTO Archs(NAME,HASH,SIZE,IMPORTED,CATEGORY,OWNER) VALUES( ' { archive [ ' name ' ] } ' , ' { archive [ ' hash ' ] } ' , { archive [ ' size ' ] } , { curtime } , { archive [ ' category ' ] } , { archive [ ' owner ' ] } ) " )
except Exception as e : # hash needs to be unique
return False , e
self . cur . execute ( f " SELECT ID FROM Archs WHERE HASH= ' { archive [ ' hash ' ] } ' " )
archid = self . cur . fetchone ( )
return True , archid [ 0 ]
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
## Deletes all relevant entries from Archs and ArchLab
2023-10-19 19:14:18 +02:00
def delete_archive ( self , archid : int ) :
self . cur . execute ( f """ DELETE FROM Archs WHERE ID= { archid } """ )
self . cur . execute ( f """ DELETE FROM ArchLab WHERE ARCHID= { archid } """ )
2023-10-19 13:25:59 +02:00
2023-10-17 18:25:38 +02:00
## Returns all relevant information about one (1) archive
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
## OUTPUT: (if archive doesn't exist) bool=False, error:str
## (if archive exists) bool=True,
## archive:tuple=(ID:int,NAME:str,HASH:str,SIZE:int,IMPORTED[UNIX]:int,CATEGORY.ID:int,CATEGORY,str,CATEGORY.DESCRIPTION:str,USER.ID:int,DNAME:str),
## category:tuple=(ID:int,CATEGORY:str,DESCRIPTION:str,PID:int,PCAT:str,PDESC:str),
2023-10-20 15:27:25 +02:00
## labels:list=[…,(ID:int,LABEL:str,LABTYPE:int,LABDESC:str),…]
2023-10-19 18:24:36 +02:00
def get_archive_info ( self , archid : int ) :
# get info about archive itself
self . cur . execute ( f """ SELECT Archs.ID,Archs.NAME,Archs.HASH,Archs.SIZE,Archs.IMPORTED,Cats.ID,Cats.CATEGORY,Cats.DESCRIPTION,Users.ID,Users.DNAME FROM Archs
2023-10-17 18:25:38 +02:00
JOIN Cats ON Cats . ID = Archs . CATEGORY
JOIN Users ON Users . ID = Archs . OWNER
2023-10-19 18:24:36 +02:00
WHERE Archs . ID = ' {archid} ' """ )
2023-10-17 18:25:38 +02:00
archive = self . cur . fetchone ( )
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
if not archive :
return False , " The archive does to exist! " , None , None
2023-10-19 18:24:36 +02:00
# get info about category and it's parent
self . cur . execute ( f """ SELECT c.ID,c.CATEGORY,c.DESCRIPTION,p.ID AS PID,p.CATEGORY as PCAT,p.DESCRIPTION AS PDESC FROM Cats c, Cats p
WHERE c . ID = { archive [ 5 ] } AND c . PARENT = p . ID """ )
category = self . cur . fetchone ( )
# get info about labels of archive
2023-10-20 15:27:25 +02:00
labels = self . get_label_info ( archid )
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
return True , archive , category , labels
2023-10-17 18:25:38 +02:00
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
## Gets all labels and their parents of an archive
## OUTPUT: list=[…,(ID:int,LABEL:str,LABTYPE:int,LABDESC:str),…]
2023-10-20 15:27:25 +02:00
def get_label_info ( self , archid : int ) :
self . cur . execute ( f """ SELECT Labs.ID,Labs.LABEL,LabType.ID AS LABTYPE,LabType.DESCRIPTION AS LABDESC FROM ArchLab
JOIN Archs ON Archs . ID = ArchLab . ARCHID
JOIN Labs ON Labs . ID = ArchLab . LABID
JOIN LabType ON Labs . TYPE = LabType . ID
WHERE ARCHID = { archid } ; """ )
return self . cur . fetchall ( )
2023-10-18 17:24:59 +02:00
## Returns all categories.
## OUTPUT: array=[…,(ID:int,CATEGORY:str,PARENT:int,DESCRIPTION:str),…]
2023-10-19 18:24:36 +02:00
def get_categories ( self ) :
2023-10-18 17:24:59 +02:00
self . cur . execute ( " SELECT * FROM Cats; " )
return self . cur . fetchall ( )
2023-11-07 12:58:40 +01:00
## Gets and returns all info about one (1) category
## OUTPUT: tup=(ID:int,CATEGORY:str,PARENT:int,DESCRIPTION:str)
def get_category_info ( self , catid : int ) :
self . cur . execute ( f " SELECT * FROM Cats WHERE ID= { catid } " )
return self . cur . fetchone ( )
2023-10-19 18:24:36 +02:00
## get all labeltypes and their respective labels based on a category parent
## OUTPUT: res_dict:dict={…,LabType.NAME:[…,(ID:int,NAME:str),…],…}
def get_label_labeltypes ( self , catparentid : int ) :
# gets all relevant labtypes: […,(ID.int,NAME:str),…]
self . cur . execute ( f """ SELECT LabType.ID,LabType.NAME FROM CatLabType
JOIN Cats ON Cats . ID = CatLabType . CATID
JOIN LabType ON LabType . ID = CatLabType . LABID
WHERE Cats . ID = { catparentid }
ORDER BY LabType . NAME ASC """ )
labtypes_list = self . cur . fetchall ( )
labtypes_ids , labtypes_names = [ ] , [ ]
for w , e in labtypes_list :
labtypes_ids . append ( str ( w ) )
labtypes_names . append ( e )
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
ltids_string = " ( " + " , " . join ( labtypes_ids ) + " ) "
2023-10-19 18:24:36 +02:00
# gets all relevant labs: […,(ID:int,NAME:str,LTNAME:str),…]
self . cur . execute ( f """ SELECT Labs.ID,Labs.LABEL,LabType.NAME AS LTNAME FROM Labs
JOIN LabType ON Labs . TYPE = LabType . ID
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
WHERE LabType . ID IN { ltids_string }
2023-10-19 18:24:36 +02:00
ORDER BY Labs . LABEL ASC """ )
labs_list = self . cur . fetchall ( )
res_dict = { }
# creates all labtype entries in dict
for i in labtypes_names :
res_dict [ i ] = [ ]
# puts all labs into their respective labtype
for entry in labs_list :
res_dict [ entry [ 2 ] ] . append ( entry [ : 2 ] )
return res_dict
## get a list of enabled labels and update the DB to reflect that state
## OUTPUT: (if on_labels empty) bool=False, str
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
## (else) bool=True, str=""
2023-10-19 19:14:18 +02:00
def update_labels ( self , archid : int , on_labels : list ) :
2023-10-19 18:24:36 +02:00
# fail if no labels passed
if len ( on_labels ) == 0 :
return False , " You have to select at least one label! "
# get all relevant labels
self . cur . execute ( f """ SELECT ArchLab.LABID FROM ArchLab
WHERE ArchLab . ARCHID = { archid } """ )
existing_labs = [ ]
for i in self . cur . fetchall ( ) :
existing_labs . append ( i [ 0 ] )
to_add = [ ]
# get all missing labels to add
for lab in on_labels :
if int ( lab ) not in existing_labs :
to_add . append ( lab )
# remove all labels which are not on
self . cur . execute ( f """ DELETE FROM ArchLab WHERE ARCHID= { archid } AND LABID NOT IN ( { " , " . join ( on_labels ) } ) """ )
to_add_list = [ ]
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
# creates all entries as strings and puts them into a list
2023-10-19 18:24:36 +02:00
for i in to_add :
to_add_list . append ( " ( " + str ( archid ) + " , " + str ( i ) + " ) " )
# add all new labels
self . cur . execute ( f """ INSERT INTO ArchLab(ARCHID,LABID) VALUES { " , " . join ( to_add_list ) } """ )
return True , " "
2023-10-18 17:24:59 +02:00
Many fixes and improvements
Fixes: #20,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#46,#48
2023-11-02 15:20:03 +01:00
## Returns n archives, sorted by a column
2023-11-07 12:58:40 +01:00
## OUTPUT: archives:array=[…,(ID:int,NAME:str,SIZE:str,IMPORTED[UNIX]:int),…], total_count:int
def get_n_archives ( self , sorttype : str = " time " , category : int = 0 , keywords : list = [ ] , count : int = 20 , labels : list = None , page : int = 1 ) : # TODO: CLEANN!!!!!
2023-10-17 18:25:38 +02:00
match sorttype :
case " size " :
2023-11-07 12:58:40 +01:00
sorttype = " Archs.SIZE DESC "
2023-10-18 17:24:59 +02:00
case " time " :
2023-11-07 12:58:40 +01:00
sorttype = " Archs.IMPORTED DESC "
2023-10-18 17:24:59 +02:00
case " za " :
2023-11-07 12:58:40 +01:00
sorttype = " Archs.NAME DESC "
2023-10-17 18:25:38 +02:00
case _ :
2023-11-07 12:58:40 +01:00
sorttype = " Archs.NAME ASC "
2023-10-18 17:24:59 +02:00
# create SQL query for keywords
keyword_string = " "
for w in keywords :
2023-11-07 12:58:40 +01:00
keyword_string + = f " AND Archs.NAME LIKE ' % { w } % ' "
2023-10-18 17:24:59 +02:00
if len ( keywords ) == 1 :
2023-11-07 12:58:40 +01:00
keyword_string + = f " OR Archs.HASH = ' { keywords [ 0 ] } ' "
2023-10-18 17:24:59 +02:00
2023-10-20 15:27:25 +02:00
# get all children of category (if exist) and put into query string
2023-10-19 18:24:36 +02:00
categories = self . get_categories ( )
2023-10-19 13:25:59 +02:00
catlist = [ str ( category ) ]
2023-10-18 17:24:59 +02:00
for i in categories :
if i [ 2 ] == int ( category ) :
catlist . append ( str ( i [ 0 ] ) )
2023-10-19 13:25:59 +02:00
categories = " ( " + " , " . join ( catlist ) + " ) "
2023-10-18 17:24:59 +02:00
2023-11-07 12:58:40 +01:00
# select all archives by keywords, categories and labels
self . cur . execute ( f """ SELECT DISTINCT Archs.ID,Archs.NAME,Archs.SIZE,Archs.IMPORTED FROM Archs
JOIN ArchLab ON Archs . ID = ArchLab . ArchID
{ " WHERE 1=1 " if category == 0 else " WHERE Archs.CATEGORY IN " + categories }
{ f " AND ArchLab.LabID IN ( { ' , ' . join ( labels ) } ) " if labels else " " }
2023-10-18 17:24:59 +02:00
{ keyword_string }
2023-11-07 12:58:40 +01:00
GROUP BY Archs . ID
{ f " HAVING COUNT(Archs.ID)= { len ( labels ) } " if labels else " " }
ORDER BY { sorttype } """ )
2023-10-17 18:25:38 +02:00
archives = self . cur . fetchall ( )
2023-11-07 12:58:40 +01:00
res_archives = archives [ page * count - count : page * count ] # get archives for the selected page
total_count = len ( archives )
2023-10-20 15:27:25 +02:00
2023-11-07 12:58:40 +01:00
return res_archives , total_count
2023-10-17 18:25:38 +02:00
if __name__ == " __main__ " :
#startup()
db = db ( conn_params )
db . cur . close ( )
db . conn . close ( )
exit ( )