def reseeders_update(self): """ Get the pre-reseed list from database. And sent those un-reseed torrents to each reseeder depend on it's download status. """ pre_reseeder_list = self.get_online_reseeders() pre_cond = " OR ".join(["`{}`=0".format(i.db_column) for i in pre_reseeder_list]) result = db.exec("SELECT * FROM `seed_list` WHERE `download_id` != 0 AND ({})".format(pre_cond), r_dict=True, fetch_all=True) for t in result: # Traversal all un-reseed list try: dl_torrent = tc.get_torrent(t["download_id"]) except KeyError: # Un-exist pre-reseed torrent Logger.error("The pre-reseed Torrent: \"{0}\" isn't found in result, " "It's db-record will be deleted soon.".format(t["title"])) self._del_torrent_with_db(rid=t["id"]) if t["id"] in self.downloading_torrent_id_queue: self.downloading_torrent_id_queue.remove(t["id"]) else: tname = dl_torrent.name if int(dl_torrent.progress) is 100: # Get the download progress in percent. Logger.info("New completed torrent: \"{name}\" , Judge reseed or not.".format(name=tname)) for reseeder in pre_reseeder_list: Thread(target=reseeder.torrent_feed, args=(dl_torrent,), name="Thread-{}".format(reseeder.model_name()), daemon=True).start() # reseeder.torrent_feed(torrent=dl_torrent) if dl_torrent.id in self.downloading_torrent_id_queue: self.downloading_torrent_id_queue.remove(dl_torrent.id) elif dl_torrent.id in self.downloading_torrent_id_queue: pass # Wait until this torrent download completely. else: Logger.warning("Torrent:\"{name}\" is still downloading, Wait......".format(name=tname)) self.downloading_torrent_id_queue.append(dl_torrent.id)
def update_torrent_info_from_rpc_to_db(self, last_id_db=None, force_check=False): """ Sync torrent's id from transmission to database, List Start on last check id,and will return the max id as the last check id. """ torrent_list = tc.get_torrents() # Cache the torrent list new_torrent_list = [ t for t in torrent_list if t.id > self.last_id_check ] if new_torrent_list: last_id_now = max([t.id for t in new_torrent_list]) if last_id_db is None: last_id_db = db.get_max_in_seed_list( column_list=db.col_seed_list[2:]) Logger.debug("Max tid, transmission: {tr}, database: {db}".format( tr=last_id_now, db=last_id_db)) if not force_check: # Normal Update Logger.info( "Some new torrents were add to transmission, Sync to db~") for i in new_torrent_list: # Upsert the new torrent db.upsert_seed_list(self._get_torrent_info(i)) elif int(last_id_now) != int( last_id_db ): # Check the torrent 's record between tr and db total_num_in_tr = len(set([t.name for t in torrent_list])) total_num_in_db = db.exec( sql="SELECT COUNT(*) FROM `seed_list`")[0] if int(total_num_in_tr) >= int(total_num_in_db): Logger.info("Upsert the whole torrent id to database.") for t in torrent_list: # Upsert the whole torrent db.upsert_seed_list(self._get_torrent_info(t)) else: Logger.error( "The torrent list didn't match with db-records, Clean the whole \"seed_list\" for safety." ) db.exec(sql="DELETE FROM `seed_list` WHERE 1" ) # Delete all line from seed_list self.update_torrent_info_from_rpc_to_db(last_id_db=0) self.last_id_check = last_id_now else: Logger.debug("No new torrent(s), Return with nothing to do.") return self.last_id_check
def reseeders_update(self): """Get the pre-reseed list from database.""" pre_cond = " OR ".join([ "`{}`=0".format(i.db_column) for i in self.get_pre_reseeder_list() ]) result = db.exec( "SELECT * FROM `seed_list` WHERE `download_id` != 0 AND ({})". format(pre_cond), r_dict=True, fetch_all=True) for t in result: # Traversal all un-reseed list try: dl_torrent = tc.get_torrent(t["download_id"]) except KeyError: # Un-exist pre-reseed torrent logging.error( "The pre-reseed Torrent: \"{0}\" isn't found in result," " It's db-record will be deleted soon".format(t["title"])) Thread(target=self._del_torrent_with_db, args={ "rid": t["id"] }, daemon=True).start() else: tname = dl_torrent.name if int(dl_torrent.progress ) is 100: # Get the download progress in percent. logging.info( "New completed torrent: \"{name}\" ,Judge reseed or not." .format(name=tname)) self.reseeder_feed(dl_torrent=dl_torrent) if dl_torrent.id in self.downloading_torrent_id_queue: self.downloading_torrent_id_queue.remove(dl_torrent.id) elif dl_torrent.id in self.downloading_torrent_id_queue: pass # Wait until this torrent download completely. else: logging.warning( "Torrent:\"{name}\" is still downloading,Wait......". format(name=tname)) self.downloading_torrent_id_queue.append(dl_torrent.id)
def reseeder_feed(self, dl_torrent): pre_reseeder_list = self.get_pre_reseeder_list() tname = dl_torrent.name cow = db.exec( "SELECT * FROM `seed_list` WHERE `download_id`='{did}'".format( did=dl_torrent.id), r_dict=True) reseed_status = False for pat in pattern_group: search = re.search(pat, tname) if search: logging.debug("The search group dict: {gr}".format( gr=search.groupdict())) for reseeder in [ r for r in pre_reseeder_list if int(cow[r.db_column]) == 0 ]: # Site feed try: tag = reseeder.torrent_feed(torrent=dl_torrent, name_pattern=search) except Exception as e: logging.critical( "{}, Will start A reseeder online check soon.". format(e.args[0])) Thread(target=self._online_check, daemon=True).start() pass else: db.upsert_seed_list((tag, tname, reseeder.db_column)) reseed_status = True break if not reseed_status: # Update seed_id == -1 if no matched pattern logging.warning( "No match pattern,Mark \"{}\" As Un-reseed torrent,Stop watching." .format(tname)) for reseeder in pre_reseeder_list: db.upsert_seed_list((-1, tname, reseeder.db_column))
def torrent_feed(self, torrent): torrent = self._get_torrent(torrent) reseed_tag, = db.exec( "SELECT `{}` FROM `seed_list` WHERE `download_id` = {}".format(self.db_column, torrent.id) ) if reseed_tag in [None, 0, "0"] and reseed_tag not in [-1, "-1"]: # It means that the pre-reseed torrent in this site is not reseed before, # And this torrent not marked as an un-reseed torrent. self._assist_delay() Logger.info("Autoseed-{mo} Get A feed torrent: {na}".format(mo=self.name, na=torrent.name)) reseed_tag = -1 try: reseed_tag = self.torrent_reseed(torrent) except Exception as e: # TODO 针对不同的Error情况做不同的更新(e.g. 因为网络问题则置0,其他情况置1) err_name = type(e).__name__ Logger.error( "Reseed not success in Site: {} for torrent: {}, " "With Exception: {}, {}".format(self.name, torrent.name, err_name, e) ) finally: db.upsert_seed_list((reseed_tag, torrent.name, self.db_column))
def _del_torrent_with_db(self, rid=None): """Delete torrent(both download and reseed) with data from transmission and database""" Logger.debug( "Begin torrent's status check. If reach condition you set, You will get a warning." ) if rid: sql = "SELECT * FROM `seed_list` WHERE `id`={}".format(rid) else: sql = "SELECT * FROM `seed_list`" time_now = time.time() for cow in db.exec(sql=sql, r_dict=True, fetch_all=True): sid = cow.pop("id") s_title = cow.pop("title") err = 0 reseed_list = [] torrent_id_list = [tid for tracker, tid in cow.items() if tid > 0] for tid in torrent_id_list: try: # Ensure torrent exist reseed_list.append(tc.get_torrent(torrent_id=tid)) except KeyError: # Mark err when the torrent is not exist. err += 1 delete = False if rid: delete = True Logger.warning( "Force Delete. Which name: {}, Affect torrents: {}".format( s_title, torrent_id_list)) elif err is 0: # It means all torrents in this cow are exist,then check these torrent's status. reseed_stop_list = [] for t in reseed_list: if int(time_now - t.addedDate ) > TIME_TORRENT_KEEP_MIN: # At least seed time if t.status == "stopped": # Mark the stopped torrent reseed_stop_list.append(t) elif setting.pre_delete_judge(torrent=t): _tid, _tname, _tracker = self._get_torrent_info(t) tc.stop_torrent(t.id) Logger.warning( "Reach Target you set, Torrent({tid}) \"{name}\" in Tracker \"{tracker}\" now stop, " "With Uploaded {si:.2f} MiB, Ratio {ro:.2f} , Keep time {ho:.2f} h." "".format(tid=_tid, name=_tname, tracker=_tracker, si=t.uploadedEver / 1024 / 1024, ro=t.uploadRatio, ho=(time.time() - t.startDate) / 60 / 60)) if len(reseed_list) == len(reseed_stop_list): delete = True Logger.info( "All torrents of \"{0}\" reach target, Will DELETE them soon." .format(s_title)) else: delete = True Logger.error( "Some Torrents (\"{name}\", {er} of {co}) may not found, " "Delete all it's records from db".format( name=s_title, er=err, co=len(torrent_id_list))) if delete: # Delete torrents with it's data and db-records for tid in torrent_id_list: tc.remove_torrent(tid, delete_data=True) db.exec( sql="DELETE FROM `seed_list` WHERE `id` = {0}".format(sid))
def _shut_unreseeder_db(): Logger.debug("Set un-reseeder's column into -1.") for tracker in unactive_tracker_list: # Set un_reseed column into -1 db.exec( sql="UPDATE `seed_list` SET `{cow}` = -1 WHERE `{cow}` = 0 " .format(cow=tracker))
def _shut_unreseeder_db(self): for tracker in self.unactive_tracker_list: # Set un_reseed column into -1 db.exec( sql="UPDATE `seed_list` SET `{cow}` = -1 WHERE `{cow}` = 0 ". format(cow=tracker))
def _del_torrent_with_db(self): """Delete torrent(both download and reseed) with data from transmission and database""" Logger.debug( "Begin torrent's status check. If reach condition you set, You will get a warning." ) time_now = time.time() t_all_list = tc.get_torrents() t_name_list = set(map(lambda x: x.name, t_all_list)) for t_name in t_name_list: t_list = list(filter(lambda x: x.name == t_name, t_all_list)) t_list_len = len(t_list) t_list_stop = 0 for t in t_list: if t.status == "stopped": t_list_stop += 1 continue _tid, _tname, _tracker = self._get_torrent_info(t) # 0 means OK, 1 means tracker warning, 2 means tracker error, 3 means local error. if t.error > 1: tc.stop_torrent(t.id) Logger.warning( "Torrent Error, Torrent({tid}) \"{name}\" in Tracker \"{tracker}\" now stop, " "Error code : {code} {msg}." "With Uploaded {si:.2f} MiB, Ratio {ro:.2f} , Keep time {ho:.2f} h." "".format(tid=_tid, name=_tname, tracker=_tracker, si=t.uploadedEver / 1024 / 1024, ro=t.uploadRatio, ho=(time.time() - t.startDate) / 60 / 60, code=t.error, msg=t.errorString)) if int(time_now - t.addedDate ) > TIME_TORRENT_KEEP_MIN: # At least seed time if setting.pre_delete_judge(torrent=t): tc.stop_torrent(t.id) Logger.warning( "Reach Target you set, Torrent({tid}) \"{name}\" in Tracker \"{tracker}\" now stop, " "With Uploaded {si:.2f} MiB, Ratio {ro:.2f} , Keep time {ho:.2f} h." "".format(tid=_tid, name=_tname, tracker=_tracker, si=t.uploadedEver / 1024 / 1024, ro=t.uploadRatio, ho=(time.time() - t.startDate) / 60 / 60)) if t_list_stop == t_list_len: # Delete torrents with it's data and db-records Logger.info( "All torrents of \"{0}\" reach target, Will DELETE them soon." .format(t_name)) tid_list = map(lambda x: x.id, t_list) for tid in tid_list: tc.remove_torrent(tid, delete_data=True) db.exec("DELETE FROM `seed_list` WHERE `title` = %s", (t_name, ))