__module_name__ = "RLSdb" __module_version__ = "038" __module_description__ = "RLSdb for X-Chat" import xchat, sqlite3, os, re, string, time, cPickle, threading zzzmsg = "\0034" + __module_name__ + " " + __module_version__ + " has been loaded\003" zzzmsg2 = "MSG #rlsdb \0034" + __module_name__+ " " + __module_version__+ " has been loaded\003" print zzzmsg #uncomment below to announce to chan when the script is loaded #xchat.command(zzzmsg2) color = {"white":"\00300", "black":"\00301", "lblue":"\00302", "green":"\00303", "red":"\00304", "dred":"\00305", "purple":"\00306", "dyellow":"\00307", "yellow":"\00308", "bgreen":"\00309", "dgreen":"\00310", "green":"\00311", "lblue":"\00312", "bpurple":"\00313", "dgrey":"\00314", "lgrey":"\00315", "closec":"\003", "closea":"\017", "closeb":"\002", "bold":"\002"} results_keeper = {"index":0} #Change this to the name of the chan the bot will be operating in annchan = "#sceneaccess" def main(): global rls_regx, dmobj, results_folder, results_file rls_regx = re.compile('(.*)NEW in (.*): -> ([^\s]*.) \((.*)\) - \(http:\/\/www.sceneaccess.org\/details.php\?id=(\d+)\)(.*)') #YOU MUST USE DOUBLE BACKSLASHES, NOT SINGLE! OTHERWISE YOU WILL GET ERRORS CONNECTING TO THE DATABASE #Forward slashes dont have to be doubled dmobj = dataman("/home/kyle/rlsdb_databases", "rlsdb_bigbase2-linux-base_v034.db") #Load up saved results_keeper from a pickled object on file. You can change its initial location here btw. results_folder = "/home/kyle/rlsdb_databases" results_file = "results_keeper.pkl" rlsts_fct("load") class dataman: def __init__(self, path, filename): '''Upon initilizing this will make sure that the supplied database exists and is valid, otherwise it will create it. Path is the path to the database, i.e. C:\databases Filename is the name of the database file, i.e. mybase.db.''' #The databases file open status. This is a bool. True if the file database is open, false if its closed self.database_open = False #Database file name self.database_name = filename #Base path where the database file is located self.database_basedir = path #A combination of both base path and file name self.database_fpath = os.path.join(path, filename) #A variable global to each dataman object instance that tells if the database is ok to use or not #Its very important to limit the number of functions that set the status of this variable. Prefered that only main 'master' functions do this. # 0 = Not open, not usable # 1 = Database not valid, no usable # 2 = Database valid, doesnt contain our data. # 3 = Database open, usable # 4 = Created new base, usable self.database_status = 0 #Upon creation of this object, we make sure the supplied database exists and is valid. ready_to_operate = self.__datainit__() if ready_to_operate is False: #Set up the error messages: if self.database_status == 0: ecode = "0 (Database not open, not usable)" if self.database_status == 1: ecode = "1 (Database not valid, no usable)" if self.database_status == 2: ecode = "2 (Database valid, doesnt contain our data)" #If you ever see either of these two error codes, run to the hills! if self.database_status == 3: ecode = "3 (Database open, usable) aka 'WTF error'" if self.database_status == 4: ecode = "4 (Created new base, usable) aka 'WTF error'" raise Exception("DATAMAN_ERROR. Code: " + ecode) def __datainit__(self): '''This will make sure that self.database exists and is a valid database. If not, it will start the creation process''' exist_chk = os.access(self.database_fpath, os.W_OK) #Database file does exist, but we need to make sure its a valid database, and that its the correct database if exist_chk is True: #If theres any problem with the database, we wont do anything. #The reason we dont do anything is incase the user gave the wrong filename. We dont want to overwrite a file thats not ours. db = sqlite3.connect(self.database_fpath) self.database_open = True db_cur = db.cursor() try: table_list = db_cur.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name").fetchall() except sqlite3.DatabaseError: self.database_status = 1 db.close() self.database_open = False return False #if we're this far then we can make sure the database has our tables in it #At this point we are done with the database so we can close the connection db.close() self.database_open = False #Out table_list looks like this: a unicode name of a table, inside a tuple, inside a list. #Not something you can easily use, so first we convert it into a simple list. new_list = None num = 0 while True: try: z = str(table_list[num][0]) except: break if num == 0: new_list = [z] else: new_list.append(z) num += 1 #Now we'll have a very sane list of tables that we can easily work with. #We're looking for the 2 main tables. If they're not there, then set the database_status and return False. try: ta = new_list.index("rdb_global_data") tb = new_list.index("rdb_release_data") except ValueError: self.database_status = 2 return False #just double check that everything is ok if ta is not None and tb is not None: self.database_status = 3 return True #If the file doesnt even exist, then we will create a new database with all the needed default tables and values. else: db = sqlite3.connect(self.database_fpath) self.database_open = True db_cur = db.cursor() #First we create our two tables, and their items. db_cur.execute('''CREATE TABLE rdb_global_data ( creation_date TEXT, total_indexes INTEGER, last_add_id INTEGER, accsize NUMERIC, grabaccsize NUMERIC, ExtraData TEXT ) ''') db_cur.execute('''CREATE TABLE rdb_release_data ( IndexID INTEGER, torID INTEGER, AddDate TEXT, AddDateUnix TEXT, EntryStat TEXT, RLSName TEXT, RLSCat TEXT, RLSSize NUMERIC, RLSPreTime TEXT, RLSLink TEXT, SCCwGrabbed TEXT, SCCwGrabInit TEXT, SCCwGrabTag TEXT, SCCwGrabState TEXT, SCCwGrabDate TEXT, SCCwGrabURL TEXT, SCCwSaveLoc TEXT, SCCwGrabTries INTEGER, ExtraData TEXT ) ''') #And now we set up the default global values. current_time = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime()) data_tuple = (current_time, 0, 0, 0, 0, "Nothing") db_cur.execute("INSERT INTO rdb_global_data VALUES (?,?,?,?,?,?)", data_tuple) #Commit the changes and close the database. db.commit() db.close() self.database_open = False #Database is ready to roll, return true self.database_status = 4 print "RLSdb Warning: Creating new database @ : " + self.database_fpath print "RLSdb Warning: Created new database for use because supplied filename was not found." print "RLSdb Warning: This is not an error, just a notification. Everything is fine :)" return True def Querybyname(self, querytext): '''Query the database by release name. Will return 2 values, a status code and a list of data. If the status code is GOOD, then the list will be a list of IndexID's for the matched entries. If the status code is NONE, the second value is actuall a NoneType. MANY means more than 1 result was found, and you need to be more specific. NONE means no entries were found''' #Connect to the database: db = sqlite3.connect(self.database_fpath) self.database_open = True db_cur = db.cursor() querytext = str(querytext) self._queryreturn = db_cur.execute("select IndexID from rdb_release_data where RLSname like ? order by AddDateUnix desc", (querytext, )).fetchall() db.close() self.database_open = False #Once again we have ourselves quite a mess of return, so we cleen it up n = 0 self._clean_return = None #first, length checks. No sense cleaning empty data :p query_size = len(self._queryreturn) if query_size > 0: while True: try: z = str(self._queryreturn[n][0]) except: break if n == 0: self._clean_return = [z] else: self._clean_return.append(z) n += 1 return("GOOD", self._clean_return) if query_size == 0: return("NONE", None) def Querybynamegrp(self, grp, args): #Connect to the database: db = sqlite3.connect(self.database_fpath) self.database_open = True db_cur = db.cursor() grp = str(grp) args = str(args) qtup = (grp, args) self._queryreturn = db_cur.execute("select IndexID from rdb_release_data where RLSCat like ? and RLSName like ? order by AddDateUnix desc", qtup).fetchall() db.close() self.database_open = False #Once again we have ourselves quite a mess of return, so we cleen it up n = 0 self._clean_return = None #first, length checks. No sense cleaning empty data :p query_size = len(self._queryreturn) if query_size > 0: while True: try: z = str(self._queryreturn[n][0]) except: break if n == 0: self._clean_return = [z] else: self._clean_return.append(z) n += 1 return("GOOD", self._clean_return) if query_size == 0: return("NONE", None) def Querybyid(self, queryid): '''Query the database by torrent ID. Will return 2 values, a status code and a list of IndexIDs matching the query. There should only be one. If the status code is GOOD, then the list will have the releases's page URL. If the status code is either MANY or NONE, the second value is actuall a NoneType. MANY means more than 1 result was found, and you need to be more specific. NONE means no entries were found''' #Connect to the database: db = sqlite3.connect(self.database_fpath) self.database_open = True db_cur = db.cursor() querytext = str(queryid) querytup = (querytext, ) db_cur.execute("select IndexID from rdb_release_data where torID = ?", querytup) self._queryreturn = db_cur.fetchall() db.close() self.database_open = False #Once again we have ourselves quite a mess of return, so we cleen it up n = 0 self._clean_return = None #first, length checks. No sense cleaning empty data :p query_size = len(self._queryreturn) if query_size > 0: while True: try: z = str(self._queryreturn[0][n]) except: break if n == 0: self._clean_return = [z] else: self._clean_return.append(z) n += 1 return("GOOD", self._clean_return) if query_size == 0: return("NONE", None) def QuerybyIndex(self, queryid): '''Query the database by torrent ID. Will return 2 values, a status code and a list of IndexIDs matching the query. There should only be one. If the status code is GOOD, then the list will have the releases's page URL. If the status code is either MANY or NONE, the second value is actuall a NoneType. MANY means more than 1 result was found, and you need to be more specific. NONE means no entries were found''' #Connect to the database: db = sqlite3.connect(self.database_fpath) self.database_open = True db_cur = db.cursor() querytext = str(queryid) querytup = (querytext, ) self._queryreturn = db_cur.execute("select * from rdb_release_data where IndexID = ?", querytup).fetchall() db.close() self.database_open = False #Once again we have ourselves quite a mess of return, so we cleen it up n = 0 self._clean_return = None #first, length checks. No sense cleaning empty data :p query_size = len(self._queryreturn) if query_size > 0: while True: try: z = str(self._queryreturn[0][n]) except: break if n == 0: self._clean_return = [z] else: self._clean_return.append(z) n += 1 return(self._clean_return) if query_size == 0: return("NONE", None) def Additem(self, IndexID, torID, AddDate, AddDateUnix, EntryStat, RLSName, RLSCat, RLSSize, RLSPreTime, RLSLink, SCCwGrabbed, SCCwGrabInit, SCCwGrabTag, SCCwGrabState, SCCwGrabDate, SCCwGrabURL, SCCwSaveLoc, SCCwGrabTries, ExtraData): '''Add an item to the database. You need to supply 18 values! ZOMG I KNOW CRAZY HUH?! Heres what you need to send, and in this order: IndexID torID AddDate AddDateUnix EntryStat RLSName RLSCat RLSSize RLSPreTime RLSLink SCCwGrabbed SCCwGrabInit SCCwGrabTag SCCwGrabState SCCwGrabDate SCCwGrabURL SCCwSaveLoc SCCwGrabTries ExtraData Everything starting with SCCw does not need to be initially supplied, so just leave them as blank data or whatever you prefer. Just don't set them to something stupid thats going to fux things up!''' #It should be noted here that the value for the RLSSize is extremely picky about being an int and nothing else. You'll get a big fat fail every time if you forget this. new_data_tuple = (IndexID, torID, AddDate, AddDateUnix, EntryStat, RLSName, RLSCat, RLSSize, RLSPreTime, RLSLink, SCCwGrabbed, SCCwGrabInit, SCCwGrabTag, SCCwGrabState, SCCwGrabDate, SCCwGrabURL, SCCwSaveLoc, SCCwGrabTries, ExtraData) db = sqlite3.connect(self.database_fpath) self.database_open = True db_cur = db.cursor() try: db_cur.execute("INSERT INTO rdb_release_data VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", new_data_tuple) db_cur.execute("UPDATE rdb_global_data SET total_indexes = total_indexes + 1") db_cur.execute("UPDATE rdb_global_data SET last_add_id = ?", (IndexID,)) db_cur.execute("UPDATE rdb_global_data SET accsize = accsize + ?", (int(RLSSize),)) rtval = "GOOD" except: rtval = "FAIL" db.commit() db.close() self.database_open = False return(rtval) def GetLastIndex(self): db = sqlite3.connect(self.database_fpath) self.database_open = True db_cur = db.cursor() lastid = db_cur.execute("select total_indexes from rdb_global_data").fetchall()[0][0] db.close() self.database_open = False return lastid def GetDBStats(self): db = sqlite3.connect(self.database_fpath) self.database_open = True db_cur = db.cursor() indextot = db_cur.execute("select total_indexes from rdb_global_data").fetchall()[0][0] lasid = db_cur.execute("select last_add_id from rdb_global_data").fetchall()[0][0] lasrls = db_cur.execute("select RLSName from rdb_release_data where IndexID = ?", (lasid, )).fetchall()[0][0] db.close() self.database_open = False dbsize = int(os.path.getsize(self.database_fpath)) / 1024 dbsize = str(dbsize) + "KB" rtdata = [indextot, lasrls, dbsize] return rtdata def rlsts_fct(op): global results_keeper fp = os.path.join(results_folder, results_file) if op == "load": exist_chk = os.access(fp, os.W_OK) if exist_chk is True: #load up the pickled data into results_keeper pickle_file = open(fp, "r") results_keeper = cPickle.load(pickle_file) pickle_file.close() else: print "Didn't find the pickle file so we're going to start a new one" if op == "save": #We have to remove the file first, otherwise the new data is just appened to the old data. That is BAD! Worse than constantly deleting and creating a file. :D exist_chk = os.access(fp, os.W_OK) if exist_chk is True: os.remove(fp) pickle_file = open(fp, "a") cPickle.dump(results_keeper, pickle_file) pickle_file.close() print "Pickle data saved successfully to: " + str(fp) def get_time_since(time_added_unix): current_time = int(time.time()) seconds_since = current_time - int(time_added_unix) weeks = (seconds_since / 604800) if weeks != 0: seconds_since = (seconds_since - (weeks * 604800)) days = (seconds_since / 86400) if days != 0: seconds_since = (seconds_since - (days * 86400)) hours = (seconds_since / 3600) if hours != 0: seconds_since = (seconds_since - (hours * 3600)) minutes = (seconds_since / 60) if minutes != 0: seconds_since = (seconds_since - (minutes * 60)) seconds = seconds_since if weeks != 0: upload_text = "Uploaded " + str(weeks) + "w " + str(days) + "d " + str(hours) + "h " + str(minutes) + "m " + str(seconds) + "s ago" elif days != 0: upload_text = "Uploaded " + str(days) + "d " + str(hours) + "h " + str(minutes) + "m " + str(seconds) + "s ago" elif hours != 0: upload_text = "Uploaded " + str(hours) + "h " + str(minutes) + "m " + str(seconds) + "s ago" elif minutes != 0: upload_text = "Uploaded " + str(minutes) + "m " + str(seconds) + "s ago" else: upload_text = "Uploaded " + str(seconds) + "s ago" return upload_text def log_parse_starter(word, word_eol, userdata): print "HERE WE GO!" thread_parse().start() class thread_parse(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): #Here we are going to parse a log file from the announce chan to add releases to the db. #Open up a new RLSdb object, with a new database bigbaseobj = dataman("/home/kyle/rlsdb_databases", "rlsdb_bigbase2-linux-base_v034.db") #Using a different regex specifically for the log file #Its easier to split off the extra bits at the beginning then to parse it as a whole. date_timergx = re.compile("(.*) <@?SCC>(.*)(NEW in(.*))") #group(1) = Date/Time stuff. The year is always 2009. example: Jul 25 20:18:42 #group(3) = Proper line log_regx = re.compile('(.*)NEW in (.*): -> ([^\s]*.) \((.*)\) - \(http:\/\/www.sceneaccess.org\/details.php\?id=(\d+)\)(.*)') log_regx2 = re.compile("(.*)NEW in (.*): -> (.*) \((.*)\) - \(http:\/\/www.sceneaccess.org\/details.php\?id=(\d+)\)(.*)") #group(2) = category. example: TV/XviD #group(3) = RLS name #group(4) = Pretime/size. Use normal ways to pull data from that mangled string #group(5) = Torrent ID timeseprgx = re.compile("(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([0-9]{1,2}) ([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})") #group(1) = Month #group(2) = Day of Month #group(3) = Hour #group(4) = Minute #group(5) = Second #specify here the folder and filename of the log log_folder = "/home/kyle/sccwatcher_node/database_snippets/rework/data" log_filename = "new_additions.log" full_path = os.path.join(log_folder, log_filename) #verify that the supplied log file actually exists. R_OK exist_chk = os.access(full_path, os.R_OK) monthnum = None if exist_chk is True: log_file = open(full_path, "r") cline = log_file.readline() n = 0 while cline != "": dtinfo = re.match(date_timergx, cline) timeinfo = dtinfo.group(1) #This will have the date/time in it releaseinfo = dtinfo.group(3) scctext = re.match(log_regx, releaseinfo) #and this will have the groups just like it normally does in the auto part of the script. #Error Detection try: scctext.group(4) except: scctext = re.match(log_regx2, releaseinfo) #After trying the second regex it should work, if not report the error try: scctext.group(4) except: print "SOMETHING WENT WRONG! HERES SOME INFOS" print "------------------------------------" print cline print "======" print dtinfo print "------------------------------------" #Now we convert everything so its ready to add to the database #Starting with the times, this is the hard part anyway. time_breakup = re.match(timeseprgx, timeinfo) #Match up months to numbers if time_breakup.group(1) == "Jan": monthnum = 1 elif time_breakup.group(1) == "Feb": monthnum = 2 elif time_breakup.group(1) == "Mar": monthnum = 3 elif time_breakup.group(1) == "Apr": monthnum = 4 elif time_breakup.group(1) == "May": monthnum = 5 elif time_breakup.group(1) == "Jun": monthnum = 6 elif time_breakup.group(1) == "Jul": monthnum = 7 elif time_breakup.group(1) == "Aug": monthnum = 8 elif time_breakup.group(1) == "Sep": monthnum = 9 elif time_breakup.group(1) == "Oct": monthnum = 10 elif time_breakup.group(1) == "Nov": monthnum = 11 elif time_breakup.group(1) == "Dec": monthnum = 12 time_tuple = (2009, monthnum, int(time_breakup.group(2)), int(time_breakup.group(3)), int(time_breakup.group(4)), int(time_breakup.group(5)), 0, 0, 1) current_time_unix = int(time.mktime(time_tuple)) current_time = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime(current_time_unix)) #ok now just the regular stuff is next #Size details sizedetail = scctext.group(4).replace(')', '') sizedetail = sizedetail.replace('(', '') sizedetail = re.search("([0-9]{1,6}\.[0-9]{2})(.*)(M|m|K|k|G|g)(.*)", sizedetail) #sizedetail.group(1) = 541.34 #sizedetail.group(3) = M nicesize = sizedetail.group(1)+sizedetail.group(3) if sizedetail.group(3) == "K" or sizedetail.group(3) == "k": multi=int(1024) if sizedetail.group(3) == "M" or sizedetail.group(3) == "m": multi=int(1048576) if sizedetail.group(3) == "G" or sizedetail.group(3) == "g": multi=int(1073741824) torrent_size_bytes = float(sizedetail.group(1)) * multi torrent_size_bytes = int(torrent_size_bytes) pretimere = re.search("Uploaded (.*) after pre", scctext.group(4)) if pretimere is not None: pretime = pretimere.group(1) else: pretime = "NOT_AVAILABLE" rls_link = "https://www.sceneaccess.org/details.php?id=" + str(scctext.group(5)) bigbaseobj.Additem(bigbaseobj.GetLastIndex(), scctext.group(5), current_time, current_time_unix, "Good", scctext.group(3), scctext.group(2), torrent_size_bytes, pretime, rls_link, "False", "__dm_blank_val__", "__dm_blank_val__", "__dm_blank_val__", "__dm_blank_val__", "__dm_blank_val__", "__dm_blank_val__", "__dm_blank_val__", "GOOD_DATA") #to_add_tuple = ("bigbaseobj.GetLastIndex()", scctext.group(5), current_time, current_time_unix, "Good", scctext.group(3), scctext.group(2), torrent_size_bytes, pretime, rls_link, "False", "__dm_blank_val__", "__dm_blank_val__", "__dm_blank_val__", "__dm_blank_val__", "__dm_blank_val__", "__dm_blank_val__", "__dm_blank_val__", "GOOD_DATA") #print to_add_tuple cline = log_file.readline() n += 1 log_file.close() print "Added " + str(n) + " new items to the database" def on_text(word, word_eol, userdata): global dmobj, results_keeper sttext = xchat.strip(word[1]) stnick = xchat.strip(word[0]) destination = xchat.get_context() if destination.get_info('channel') == "#scc-announce" and stnick == "SCC": #grep the line to get the infos scctext = re.match(rls_regx, xchat.strip(sttext)) #Size details sizedetail = scctext.group(4).replace(')', '') sizedetail = sizedetail.replace('(', '') sizedetail = re.search("([0-9]{1,6}\.[0-9]{2})(.*)(M|m|K|k|G|g)(.*)", sizedetail) #sizedetail.group(1) = 541.34 #sizedetail.group(3) = M nicesize = sizedetail.group(1)+sizedetail.group(3) if sizedetail.group(3) == "K" or sizedetail.group(3) == "k": multi=int(1024) if sizedetail.group(3) == "M" or sizedetail.group(3) == "m": multi=int(1048576) if sizedetail.group(3) == "G" or sizedetail.group(3) == "g": multi=int(1073741824) torrent_size_bytes = float(sizedetail.group(1)) * multi torrent_size_bytes = int(torrent_size_bytes) pretimere = re.search("Uploaded (.*) after pre", scctext.group(4)) if pretimere is not None: pretime = pretimere.group(1) else: pretime = "NOT_AVAILABLE" rls_link = "https://www.sceneaccess.org/details.php?id=" + str(scctext.group(5)) current_time = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime()) current_time_unix = int(time.time()) print "Adding " + scctext.group(3) + " to the RLSdb" dmobj.Additem(dmobj.GetLastIndex(), scctext.group(5), current_time, current_time_unix, "Good", scctext.group(3), scctext.group(2), torrent_size_bytes, pretime, rls_link, "False", "__dm_blank_val__", "__dm_blank_val__", "__dm_blank_val__", "__dm_blank_val__", "__dm_blank_val__", "__dm_blank_val__", "__dm_blank_val__", "GOOD_DATA") elif destination.get_info('channel') == annchan: loc = xchat.get_context() # stnick = Nick # sttext = Text st_args = "" text_split = re.split(' ', word[1], 1) st_cmd = text_split[0] try: st_args = text_split[1] except: text_split.append(None) st_args = text_split[1] if st_cmd.lower() == "!shelp": msg = "" if st_args is None: msg = "NOTICE " + stnick + " " + color["lblue"] + "Accepted commands: !search, !torinfo, !getresults, !dbstats, !groups. For further help with the listed commands, use !shelp ." xchat.command(msg) else: if st_args == "search" or st_args == "!search": msg = ["NOTICE " + stnick + " " + color["lblue"] + "!search " + color["dyellow"] + "[@grp] " + color["red"] + ""] msg.append("NOTICE " + stnick + " " + color["lblue"] + "This will search for torrents that either partially or fully match the supplied args. This accepts the following wildcards: * % ") msg.append("NOTICE " + stnick + " " + color["lblue"] + "The first part inside the [] is completely optional. It allows the option to search through a certain section/groups only. Here is an example of how to properly use this feature:") msg.append("NOTICE " + stnick + " " + color["lblue"] + "!search @TV/XviD Top.Gear*") msg.append("NOTICE " + stnick + " " + color["lblue"] + "This will search for Top.Gear* in the TV/XviD group. You can also wildcard the group. Again, the group part is completely optional. If you don't include it then RLSdb will search through all groups.") if st_args == "torinfo" or st_args == "!torinfo": msg = ["NOTICE " + stnick + " " + color["lblue"] + "!torinfo " + color["red"] + ""] msg.append("NOTICE " + stnick + " " + color["lblue"] + "This command will return extended info on the given torrent release name. It will return the following items: ") msg.append("NOTICE " + stnick + " " + color["lblue"] + "Release Name, Release Category, Release Size, SCC Page Link, Date Released, and Pre time.") if st_args == "rgxsearch" or st_args == "!rgxsearch": #msg = ["NOTICE " + stnick + " " + color["lblue"] + "!rgxsearch " + color["dyellow"] + "[@grp] " + color["red"] + "" + color["lblue"] +":"] #msg.append("NOTICE " + stnick + " " + color["lblue"] + "This is the same as !search except that it does not accept wildcards. Instead, it fully accepts regexes.") msg = ["NOTICE " + stnick + " " + color["lblue"] + "Command not yet working :("] if st_args == "id" or st_args == "!id": #msg = ["NOTICE " + stnick + " " + color["lblue"] + "!id " + color["red"] + "" + color["lblue"] +":"] #msg.append("NOTICE " + stnick + " " + color["lblue"] + "This will search for a torrent with the matching ID. The ID is the one SCC uses for its torrents.") msg = ["NOTICE " + stnick + " " + color["lblue"] + "Command not yet working :("] if st_args == "getresults" or st_args == "!getresults": msg = ["NOTICE " + stnick + " " + color["lblue"] + "!getresults " + color["red"] + ""] msg.append("NOTICE " + stnick + " " + color["lblue"] + "This will return the search results from the provided SearchID in a private notice.") if st_args == "dbstats" or st_args == "!dbstats": msg = ["NOTICE " + stnick + " " + color["lblue"] + "!dbstats"] msg.append("NOTICE " + stnick + " " + color["lblue"] + "This will return statistics on the database RLSdb is using.") for x in msg: xchat.command(x) elif st_cmd.lower() == "!search": print "D1" if re.search("(@.*) ", st_args) is None: print "D2" query = st_args.replace('*', '%') query = "%" + query + "%" query_data = dmobj.Querybyname(query) if query_data[0] == "GOOD": print "D3" result_size = str(len(query_data[1])) nextid = str(results_keeper["index"] + 1) results_keeper["index"] = int(nextid) if int(result_size) > 15: fnum = "first 15 results" elif int(result_size) == 1: fnum = "result" else: fnum = "the " + str(result_size) + " results" msg = "MSG " + annchan + " " + color["lblue"] + "Found " + color["purple"] + result_size + color["lblue"] + " entries that matched " + stnick + "'s query. Sending " + fnum + " in a PM. Search id: " + str(nextid) loc.command(msg) n = 1 res = None for x in query_data[1]: result = dmobj.QuerybyIndex(x) #here we make sure we are outputting the correct size with the correct suffex bytes = int(result[7]) if bytes < 1048576: #We can safely assume we're dealing with Kilobytes multi=float(1024) suffex = "KB" elif bytes < 1073741824: #We can safely assume we're dealing with Megabytes multi=float(1048576) suffex = "MB" elif bytes > 1073741824: #We can safely assume we're dealing with Gigabytes. multi=float(1073741824) suffex = "GB" #and now we just do the math :) bytes = float(bytes) sizeprop = str(float(round(bytes/multi, 2))) + suffex time_since = get_time_since(result[3]) nres = color["lblue"] + str(n) + ": " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + result[5] + color["closec"] + color["bold"] + ")" + color["closeb"] + " - " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + result[6] + color["closec"] + color["bold"] + ")" + color["closeb"] + " - " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + sizeprop + color["closec"] + color["bold"] + ")" + color["closeb"] + " - " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + time_since + color["closec"] + color["bold"] + ")" + color["closeb"] + " - " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + result[9] + color["closec"] + color["bold"] + ")" + color["closeb"] msg2 = "MSG " + stnick + " " + color["lblue"] + str(n) + ": " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + result[5] + color["closec"] + color["bold"] + ")" + color["closeb"] + " - " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + result[6] + color["closec"] + color["bold"] + ")" + color["closeb"] + " - " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + sizeprop + color["closec"] + color["bold"] + ")" + color["closeb"] + " - " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + time_since + color["closec"] + color["bold"] + ")" + color["closeb"] + " - " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + result[9] + color["closec"] + color["bold"] + ")" + color["closeb"] if n == 1: res = [nres] else: res.append(nres) if n < 16: loc.command(msg2) else: break n += 1 results_keeper[nextid] = res rlsts_fct("save") else: msg = "MSG " + annchan + " " + color["lblue"] + "Didn't find any matches for " + st_args loc.command(msg) else: print "D4" query = re.search("(@.*) (.*)", st_args) # query.group(1) = the group # query.group(2) = the args fxgrp = query.group(1).replace('@', '') fxgrp = fxgrp.replace('*', '%') fxargs = query.group(2).replace('*', '%') fxargs = "%" + fxargs + "%" query_data = dmobj.Querybynamegrp(fxgrp, fxargs) if query_data[0] == "GOOD": print "D5" result_size = str(len(query_data[1])) nextid = str(results_keeper["index"] + 1) results_keeper["index"] = int(nextid) if int(result_size) > 15: fnum = "first 15 results" elif int(result_size) == 1: fnum = "result" else: fnum = "the " + str(result_size) + " results" msg = "MSG " + annchan + " " + color["lblue"] + "Found " + color["purple"] + result_size + color["lblue"] + " entries that matched " + stnick + "'s query. Sending " + fnum + " in a PM. Search id: " + str(nextid) loc.command(msg) n = 1 res = None for x in query_data[1]: result = dmobj.QuerybyIndex(x) #here we make sure we are outputting the correct size with the correct suffex bytes = int(result[7]) if bytes < 1048576: #We can safely assume we're dealing with Kilobytes multi=float(1024) suffex = "KB" elif bytes < 1073741824: #We can safely assume we're dealing with Megabytes multi=float(1048576) suffex = "MB" elif bytes > 1073741824: #We can safely assume we're dealing with Gigabytes. multi=float(1073741824) suffex = "GB" #and now we just do the math :) bytes = float(bytes) sizeprop = str(float(round(bytes/multi, 2))) + suffex time_since = get_time_since(result[3]) nres = color["lblue"] + str(n) + ": " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + result[5] + color["closec"] + color["bold"] + ")" + color["closeb"] + " - " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + result[6] + color["closec"] + color["bold"] + ")" + color["closeb"] + " - " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + sizeprop + color["closec"] + color["bold"] + ")" + color["closeb"] + " - " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + time_since + color["closec"] + color["bold"] + ")" + color["closeb"] + " - " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + result[9] + color["closec"] + color["bold"] + ")" + color["closeb"] msg2 = "MSG " + stnick + " " + color["lblue"] + str(n) + ": " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + result[5] + color["closec"] + color["bold"] + ")" + color["closeb"] + " - " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + result[6] + color["closec"] + color["bold"] + ")" + color["closeb"] + " - " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + sizeprop + color["closec"] + color["bold"] + ")" + color["closeb"] + " - " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + time_since + color["closec"] + color["bold"] + ")" + color["closeb"] + " - " + color["closec"] + color["bold"] + "(" + color["closeb"] + color["dgrey"] + result[9] + color["closec"] + color["bold"] + ")" + color["closeb"] if n == 1: res = [nres] else: res.append(nres) if n < 16: loc.command(msg2) else: break n += 1 results_keeper[nextid] = res rlsts_fct("save") else: msg = "MSG " + annchan + " " + color["lblue"] + "Didn't find any matches for " + st_args loc.command(msg) elif st_cmd.lower() == "!id": if len(st_args) > 0: id = int(st_args) query_data = dmobj.Querybyid(id) if query_data[0] == "GOOD": print "YEY!" print query_data result_size = len(query_data[1]) else: print query_data else: msg = "NOTICE " + stnick + " " + color["lblue"] + "You need to specify an ID to query! Maybe you haven't used !help? " elif st_cmd.lower() == "!dbstats": dbstats = dmobj.GetDBStats() msg = ["NOTICE " + stnick + " " + color["red"] + color["bold"] + "RLSdb Database Stats"] msg.append("NOTICE " + stnick + " " + color["red"] + "RLSdb Version: " + color["lblue"] + __module_version__) msg.append("NOTICE " + stnick + " " + color["red"] + "Total Entries: " + color["lblue"] + str(dbstats[0])) msg.append("NOTICE " + stnick + " " + color["red"] + "Last Release Added: " + color["lblue"] + dbstats[1]) msg.append("NOTICE " + stnick + " " + color["red"] + "Database Size: " + color["lblue"] + dbstats[2]) for x in msg: xchat.command(x) elif st_cmd.lower() == "!getresults": try: int(st_args) scid = str(st_args) fail=False except: fail=True if fail is False: try: results_keeper[scid] sfail = False except: sfail = True if sfail is False: msg1 = "MSG " + annchan + " " + color["lblue"] + "Sending results from SearchID #" + scid + " to " + stnick loc.command(msg1) for x in results_keeper[scid]: msg = "NOTICE " + stnick + " " + x loc.command(msg) if sfail is True: msg1 = "MSG " + annchan + " " + color["lblue"] + "Couldn't find SearchID #" + scid loc.command(msg1) elif st_cmd.lower() == "!groups": msg = "NOTICE " + stnick + " " + color["lblue"] + "Apps/PC_ISO" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "DOX" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "Games/PC ISO" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "Games/PS2" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "Games/PS3" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "Games/PSP" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "Games/WII" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "Games/XBOX" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "Games/XBOX360" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "MiSC" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "Movies/DVDR" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "Movies/VCD" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "Movies/X264" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "Movies/XviD" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "TV-X264" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "TV/DVDR" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "TV/XviD" + color["black"] + color["bold"] + " - " + color["closeb"] + color["lblue"] + "XXX" loc.command(msg) elif st_cmd.lower() == "!torinfo": #This is basically the same code as the !search function except it doesnt allow any wildcards and the presentation is much nicer. It also doesn't allow for multiple results. #This also doesn't store its results in the results_keeper query = st_args.replace('%', '') query_data = dmobj.Querybyname(query) if query_data[0] == "GOOD": result_size = str(len(query_data[1])) if int(result_size) < 2 and int(result_size) > 0: result = dmobj.QuerybyIndex(query_data[1][0]) msg = "MSG " + annchan + " " + color["lblue"] + "Sending extended torrent info for " + query + " to " + stnick loc.command(msg) #here we make sure we are outputting the correct size with the correct suffex bytes = int(result[7]) if bytes < 1048576: #We can safely assume we're dealing with Kilobytes multi=float(1024) suffex = "KB" elif bytes < 1073741824: #We can safely assume we're dealing with Megabytes multi=float(1048576) suffex = "MB" elif bytes > 1073741824: #We can safely assume we're dealing with Gigabytes. multi=float(1073741824) suffex = "GB" #and now we just do the math :) bytes = float(bytes) sizeprop = str(float(round(bytes/multi, 2))) + suffex time_since = get_time_since(result[3]) msg = ["NOTICE " + stnick + " " + color["red"] + color["bold"] + "Extended Torrent Info:"] msg.append("NOTICE " + stnick + " " + color["lblue"] + "Name: " + color["closec"] + color["bold"] + result[5]) msg.append("NOTICE " + stnick + " " + color["lblue"] + "Category: " + color["closec"] + color["bold"] + result[6]) msg.append("NOTICE " + stnick + " " + color["lblue"] + "Size: " + color["closec"] + color["bold"] + sizeprop) msg.append("NOTICE " + stnick + " " + color["lblue"] + "SCC Page: " + color["closec"] + color["bold"] + result[9]) msg.append("NOTICE " + stnick + " " + color["lblue"] + "Released on: " + color["closec"] + color["bold"] + result[2] + " (" + time_since + ")") msg.append("NOTICE " + stnick + " " + color["lblue"] + "Pretime: " + color["closec"] + color["bold"] + result[8]) for x in msg: xchat.command(x) else: msg = "MSG " + annchan + " " + color["lblue"] + "Couldn't find a torrent with the name " + st_args + " in the database." loc.command(msg) # This gets the script movin if (__name__ == "__main__"): main() def scriptunload(userdata): rlsts_fct("save") print "\0034" + __module_name__, __module_version__,"has been unloaded\003" xchat.hook_command('doit', log_parse_starter, help="PLEASEWORK!") xchat.hook_unload(scriptunload) xchat.hook_print('Channel Message', on_text)