import os,shutil,hashlib,re from uuid import uuid4 import sqlite3 as sql from config import * class database(): def __init__(self,filepath): self.connection=None self.crsr=None if not os.path.exists(filepath) : self.create_database(filepath) else: self.connection = sql.connect(filepath) self.crsr = self.connection.cursor() def add_index(self,vallist): # compile the options into a command for the SQLite database colstring=",".join(self.collist) valstring="'{}'".format("','".join(vallist)) self.crsr.execute("""INSERT INTO {table} ({cols}) VALUES ({vals}); """.format(table=self.name,cols=colstring,vals=valstring)) self.connection.commit() def create_database(self, filepath): # create the database and tables self.connection = sql.connect(filepath) self.crsr = self.connection.cursor() sqlcommand = """CREATE TABLE FILES( FILE TEXT PRIMARY KEY NOT NULL, HASH TEXT NOT NULL, TITLE TEXT , SOURCE TEXT , CATEGORY TEXT NOT NULL, TAGS TEXT , CONTENT TEXT ); """ self.crsr.execute(sqlcommand) '''sqlcommand = """CREATE TABLE META( TAGS TEXT PRIMARY KEY NOT NULL ); """ self.crsr.execute(sqlcommand)''' def delete_index(self,typ,item): self.crsr.execute("DELETE FROM {} WHERE {}='{}'".format(self.name,typ,item)) self.connection.commit() return def get_col(self,column = "*"): # get the column of some table. If no options given, return all columns self.crsr.execute("SELECT {} FROM {}".format(column,self.name)) tres=self.crsr.fetchall() res=[] for i in tres: res.append(i) # if the table is empty, return ".". #print(column,"res ",res) if not res: res="." return res def get_item(self,column,where): tres=[] if column == "*": for col in self.collist: temp_list=[] self.crsr.execute("SELECT * FROM {} WHERE {} GLOB '*{}*'".format(self.name,col,where)) temp_list=self.crsr.fetchall() if temp_list: for i in temp_list: if not i in tres: tres.append(i) else: self.crsr.execute("SELECT * FROM {} WHERE {} GLOB '*{}*'".format(self.name,column,where)) tres=self.crsr.fetchall() #print("Tres: ",tres) n=0 res=[] for i in tres: m=0 for j in tres: if i in j and n!=m: continue else: res.append(i) m+=1 n+=1 #print("RES: ",tres) # if the table is empty, return ".". if not res: return ["."] return res def update_index(self,typ,update,filehash): self.crsr.execute("UPDATE {} SET {}='{}' WHERE HASH='{}'".format(self.name,typ,update,filehash)) self.connection.commit() return True class metatable(database): def __init__(self,filepath = CONFIG_DIR + "/index.db"): self.name="META" self.collist=["TAGS"] super().__init__(filepath) def add_index(self): super().add_index(vallist) class filestable(database): def __init__(self,filepath = CONFIG_DIR + "/index.db"): self.name="FILES" self.collist=["FILE","HASH","TITLE","SOURCE","CATEGORY","TAGS","CONTENT"] super().__init__(filepath) def add_index(self,filepath,category,title="",source="",tags="",content=""): filehash=self.get_hash(filepath) # make of hash of file before copy n=0 category="default" if not category else category if filehash in self.get_col("HASH"): print("This file already exists!") return filetype=os.path.splitext(filepath)[1] filename=str(uuid4()) + filetype if not os.path.exists("{}/{}".format(ROOT_DIR,category)): os.makedirs("{}/{}".format(ROOT_DIR,category)) # try to copy the file, return if error. try: shutil.copy(filepath,"{}/{}/{}".format(ROOT_DIR,category,filename)) except Exception as e: print(e) print("COULDN'T COPY FILE TO DESTINATION!") return #print("Executing") vallist=[filename,filehash,title,source,category,tags,content] super().add_index(vallist) def check_index(self): hash_list=[] path_list=[] for i in self.get_col(): filename=i[0] category=i[4] filehash1=i[1] filepath="{}/{}/{}".format(ROOT_DIR,category,filename) if not os.path.exists(filepath): path_list.append(i) try: filehash2=self.get_hash(filepath) if not filehash1 == filehash2: hash_list.append(i) except Exception: path_list.append(i) return hash_list,path_list def delete_index(self,sel_list): self.get_item("HASH",sel_list[1]) super().delete_index("HASH",sel_list[1]) def update_index(self,typ,update,sel_list): typ=typ.upper() if typ in ["FILE","HASH"]: print("This type can't be changed!") return 1 category=sel_list[4] filehash=sel_list[1] filename=sel_list[0] super().update_index(typ, update, filehash) if typ in ["CATEGORY"]: if not os.path.exists("{}/{}".format(ROOT_DIR,update)): os.makedirs("{}/{}".format(ROOT_DIR,update)) shutil.move("{}/{}/{}".format(ROOT_DIR,category,filename), "{}/{}/{}".format(ROOT_DIR,update,filename)) def sql_compare_list(self,typ,firstlist,secondlist): if firstlist: n=0 temp_list=[] if not secondlist: n=0 for i in self.get_col(typ): #print(i) success=0 for j in firstlist: #print(j) if j in str(i): #print("Yay") if not success == -1: success=1 else: success=-1 if success > 0: #print("Hey",i[0]) if typ == "*": temp_list.append(self.get_item("*",i[0])[0]) else: #print("TE",n,self.get_item(typ,i[0])[1]) for k in self.get_item(typ,i[0]): if not k in temp_list: temp_list.append(k) #print("Self: ",self.get_item(typ,i[0])[n]) #print(temp_list) n+=1 else: #print("Second: ",secondlist) if not secondlist[0] == ".": for i in secondlist: for j in firstlist: if j in i: temp_list.append(secondlist[n]) n+=1 else: #print("secondlist") return secondlist #print("Temp_list: ",temp_list) if not temp_list: return ["."] return temp_list return secondlist def get_hash(self,filepath): #https://www.quickprogrammingtips.com/python/how-to-calculate-md5-hash-of-a-file-in-python.html md5_hash = hashlib.md5() # hash selected file in chunks of 4KiB, read the link above if you ask why. with open(filepath,"rb") as f: for byte_block in iter(lambda: f.read(4096),b""): md5_hash.update(byte_block) f.close() return str(md5_hash.hexdigest()) def search_index(self,args,quiet=False): #print(args) #### ## WARNING!!!!!! UGLY CODE INCOMING!!!!!! #### snext="all" shash=[] alle=[] category=[] sfile=[] content=[] source=[] title=[] tags=[] for arg in args: if re.match('^[-]\w{1}$', arg): if arg == "-h": snext="hash" elif arg == "-a": # technically unneeded because of else at the end snext="all" elif arg == "-c": snext="category" elif arg == "-f": snext="file" elif arg == "-i": # Inhalt snext="content" elif arg == "-s": snext="source" elif arg == "-t": snext="title" elif arg == "-g": # Gruppe snext="tags" else: snext="all" continue if snext == "hash": shash.append(arg) elif snext == "all": alle.append(arg) elif snext == "category": category.append(arg) elif snext == "file": sfile.append(arg) elif snext == "content": content.append(arg) elif snext == "source": source.append(arg) elif snext == "title": title.append(arg) elif snext == "tags": tags.append(arg) else: alle.append(arg) # search for the right items selection=[] selection=self.sql_compare_list("*",alle,selection) selection=self.sql_compare_list("HASH",shash,selection) selection=self.sql_compare_list("CATEGORY",category,selection) selection=self.sql_compare_list("FILE",sfile,selection) selection=self.sql_compare_list("CONTENT",content,selection) selection=self.sql_compare_list("SOURCE",source,selection) selection=self.sql_compare_list("TITLE",title,selection) selection=self.sql_compare_list("TAGS",tags,selection) #print("Selection: ",selection) if selection: res=[] if len(selection) > 1: n=0 print("Found several matches:") for tup in selection: temp_list=[] for j in tup: temp_list.append(j) #print("sdf",temp_list) print("Match [{}]".format(n)) print("\tTitle:\t ",temp_list[2]) print("\tCategory:",temp_list[4]) print("\tTags:\t ",temp_list[5]) n+=1 eingabe=input("Enter number(s) (0-{}; '*' for all entries): ".format(n-1)) if not eingabe: return ["."] num_list=[] if re.match('[*]',eingabe): for i in range(0,n): num_list.append(i) else: num_list=eingabe.split(' ') nminus=0 for i in num_list: if int(i) >= n: print("The number {} is too big!".format(i)) nminus+=1 continue res.append(selection[int(i)]) if not quiet: print("\n\nFinal match{}:".format("es" if len(num_list)-nminus > 1 else "")) else: if selection[0] == ".": print("No matching entry found!") return ["."] res=selection print("\nMatch found!") return res return 1