# Author: Dennis Lutter <lad1337@gmail.com> # URL: http://code.google.com/p/sickbeard/ # # This file is part of Sick Beard. # # Sick Beard is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Sick Beard is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Sick Beard. If not, see <http://www.gnu.org/licenses/>. from sickbeard import db, logger class BlackAndWhiteList(object): _tableBlack = "blacklist" _tableWhite = "whitelist" blackList = [] whiteList = [] blackDict = {} whiteDict = {} last_black_valid_result = None last_white_valid_result = None def __init__(self, show_id): if not show_id: raise BlackWhitelistNoShowIDException() self.show_id = show_id self.refresh() def __del__(self): pass def refresh(self): logger.log(u"Building black and white list for " + str(self.show_id), logger.DEBUG) (self.blackList, self.blackDict) = self.load_blacklist() (self.whiteList, self.whiteDict) = self.load_whitelist() def load_blacklist(self): return self._load_list(self._tableBlack) def load_whitelist(self): return self._load_list(self._tableWhite) def get_black_keywords_for(self, range): if range in self.blackDict: return self.blackDict[range] else: return [] def get_white_keywords_for(self, range): if range in self.whiteDict: return self.whiteDict[range] else: return [] def set_black_keywords(self, range, values): self._del_all_black_keywords() self._add_keywords(self._tableBlack, range, values) def set_white_keywords(self, range, values): self._del_all_white_keywords() self._add_keywords(self._tableWhite, range, values) def set_black_keywords_for(self, range, values): self._del_all_black_keywords_for(range) self._add_keywords(self._tableBlack, range, values) def set_white_keywords_for(self, range, values): self._del_all_white_keywords_for(range) self._add_keywords(self._tableWhite, range, values) def add_black_keyword(self, range, value): self._add_keywords(self._tableBlack, range, [value]) def add_white_keyword(self, range, value): self._add_keywords(self._tableWhite, range, [value]) def get_last_result_msg(self): blackResult = whiteResult = "Untested" if self.last_black_valid_result == True: blackResult = "Valid" elif self.last_black_valid_result == False: blackResult = "Invalid" if self.last_white_valid_result == True: whiteResult = "Valid" elif self.last_white_valid_result == False: whiteResult = "Invalid" return "Blacklist: " + blackResult + ", Whitelist: " + whiteResult def _add_keywords(self, table, range, values): myDB = db.DBConnection() for value in values: myDB.action("INSERT INTO " + table + " (show_id, range , keyword) VALUES (?,?,?)", [self.show_id, range, value]) self.refresh() def _del_all_black_keywords(self): self._del_all_keywords(self._tableBlack) def _del_all_white_keywords(self): self._del_all_keywords(self._tableWhite) def _del_all_black_keywords_for(self, range): self._del_all_keywords_for(self._tableBlack, range) def _del_all_white_keywords_for(self, range): self._del_all_keywords_for(self._tableWhite, range) def _del_all_keywords(self, table): logger.log(u"Deleting all " + table + " keywords for " + str(self.show_id), logger.DEBUG) myDB = db.DBConnection() myDB.action("DELETE FROM " + table + " WHERE show_id = ?", [self.show_id]) self.refresh() def _del_all_keywords_for(self, table, range): logger.log(u"Deleting all " + range + " " + table + " keywords for " + str(self.show_id), logger.DEBUG) myDB = db.DBConnection() myDB.action("DELETE FROM " + table + " WHERE show_id = ? and range = ?", [self.show_id, range]) self.refresh() def _load_list(self, table): myDB = db.DBConnection() sqlResults = myDB.select("SELECT range,keyword FROM " + table + " WHERE show_id = ? ", [self.show_id]) if not sqlResults or not len(sqlResults): return ([], {}) list, dict = self._build_keyword_dict(sqlResults) logger.log("BWL: " + str(self.show_id) + " loaded keywords from " + table + ": " + str(dict), logger.DEBUG) return list, dict def _build_keyword_dict(self, sql_result): list = [] dict = {} for row in sql_result: list.append(row["keyword"]) if row["range"] in dict: dict[row["range"]].append(row["keyword"]) else: dict[row["range"]] = [row["keyword"]] return (list, dict) def is_valid_for_black(self, haystack): logger.log(u"BWL: " + str(self.show_id) + " is valid black", logger.DEBUG) result = self._is_valid_for(self.blackDict, False, haystack) self.last_black_valid_result = result return result def is_valid_for_white(self, haystack): logger.log(u"BWL: " + str(self.show_id) + " is valid white", logger.DEBUG) result = self._is_valid_for(self.whiteDict, True, haystack) self.last_white_valid_result = result return result def is_valid(self, haystack): return self.is_valid_for_black(haystack) and self.is_valid_for_white(haystack) def _is_valid_for(self, list, mood, haystack): if not len(list): return True results = [] for range in list: for keyword in list[range]: string = None if range == "global": string = haystack.name elif range in haystack.__dict__: string = haystack.__dict__[range] elif not range in haystack.__dict__: results.append((not mood)) else: results.append(False) if string: results.append(self._is_keyword_in_string(string, keyword) == mood) # black: mood = False # white: mood = True if mood in results: return mood else: return (not mood) def _is_keyword_in_string(self, fromPost, fromBWList): """ will return true if fromBWList is found in fromPost for now a basic find is used """ fromPost = fromPost.lower() fromBWList = fromBWList.lower() logger.log(u"BWL: " + str(self.show_id) + " comparing fromPost: " + fromPost + " vs fromBWlist: " + fromBWList, logger.DEBUG) return (fromPost.find(fromBWList) >= 0) class BlackWhiteKeyword(object): range = "" value = [] def __init__(self, range, values): self.range = range # "global" or a parser group self.value = values # a list of values may contain only one item (still a list) class BlackWhitelistNoShowIDException(Exception): "No show_id was given"