def check_crash(self): self['crashed'] = os.path.exists(CRASH_FILE) if self['crashed']: with open(CRASH_FILE, 'rb') as f: self['crash_reason'] = f.read().strip() log_error('Atarashii crashed')
def load(self): try: for line in open(CONFIG_FILE, 'rb'): line = line.strip() name = line[:line.find(' ')] line = line[len(name) + 1:] vtype = line[:line.find(' ')] value = line[len(vtype) + 1:] try: if vtype == 'long': if value == UNSET_SETTING: value = long(UNSET_ID_NUM) else: value = long(value) elif vtype == 'bool': value = True if value == 'True' else False if name != UNSET_SETTING: self.values[urllib.unquote(name)] = value except ValueError, error: log_error('%s' % error) except IOError: self.values = {} # Check crash self.check_crash() crash_file(False)
def async_set_ids(self, username): self.pending = True if self.get_key(): try: self.request('set', { 'token': self.key, 'user': username, 'first_tweet': self.settings['firsttweet_' + username], 'last_tweet': self.settings['lasttweet_' + username], 'first_message': self.settings['firstmessage_' + username], 'last_message': self.settings['lastmessage_' + username] }) # Set stuff self.first_tweet = self.settings['firsttweet_' + username] self.last_tweet = self.settings['lasttweet_' + username] self.first_message = self.settings['firstmessage_' + username] self.last_message = self.settings['lastmessage_' + username] self.pending = False return True except IOError: if self.settings['syncing']: self.main.on_sync_up_fail() log_error('Syncing up failed') self.pending = False return False else: self.pending = False return False
def retrieve_new_key(self): try: key = self.request('new', {'coding': 'kittens'}) return key except IOError: log_error('Key retrieve failed') return None
def delete_userlist(self, name): userfile = os.path.join(ATARASHII_DIR, 'usernames_%s.list' % name) if os.path.exists(userfile): try: os.unlink(userfile) except OSError: log_error('Could not delete userlist for %s' % name)
def new_key(self): try: self.key = self.request('new', {'coding': 'kittens'}) self.settings['synckey'] = self.key return True except IOError: log_error('Key request failed') return False
def close(self): if self.last_id == -1: return False try: self.notify.CloseNotification(self.last_id) except dbus.exceptions.DBusException: log_error('DBUS error while closing')
def check_cache(self): for i in os.listdir(CACHE_DIR): cache_file = os.path.join(CACHE_DIR, i) if cache_file[-4:].lower() in ('jpeg', '.jpg', '.png', '.gif'): if time.time() - os.stat(cache_file).st_mtime > CACHE_TIMEOUT: try: os.unlink(cache_file) except (OSError, IOError): log_error('Could not delete file %s' % cache_file)
def save_userlist(self, name): if self.users_changed and name != UNSET_USERNAME: userfile = os.path.join(ATARASHII_DIR, 'usernames_%s.list' % name) try: with open(userfile, 'wb') as f: f.write(','.join(self.user_list)) except IOError: log_error('Could not save userlist for %s' % name) self.users_changed = False
def post_results(self): print ("Posting results...") while True: try: PTFinter.enter_results(self.league, self.matches, self.driver) break except errors.UnexpectedAlertPresentException: self.driver.switch_to_alert().accept() league_name = self.league.get_league_name() print("Alert Error for {}".format(league_name)) errors.log_error("Alert Error for {}".format(league_name))
def read_theme(self, name, theme_file): with open(theme_file, 'rb') as f: lines = [e.strip() for e in f if not e.strip().startswith('#')] try: theme_data = UNSET_STRING.join(lines).replace('\'', '"') self.color_themes[name] = json.loads(theme_data) if not 'title_en' in self.color_themes[name]: del self.color_themes[name] except (TypeError, ValueError): log_error('Invalid theme description for "%s"' % name)
def get_ids(self): if self.settings['syncing'] is not True: return False if self.main.username == UNSET_USERNAME: return False if self.get_key(): try: username = self.main.username data = self.request('get', {'token': self.key, 'user': username}) # no userdata was found, sync up! if data == 'Result: Empty': self.set_ids() return False tweet, message = data.split(';') first_tweet, last_tweet = tweet.split(',') first_message, last_message = message.split(',') # Set the IDs first_tweet = long(first_tweet) if first_tweet > self.settings['firsttweet_' + username]: self.settings['firsttweet_' + username] = first_tweet last_tweet = long(last_tweet) if last_tweet > self.settings['lasttweet_' + username]: self.settings['lasttweet_' + username] = last_tweet first_message = long(first_message) if first_message > self.settings['firstmessage_' + username]: self.settings['firstmessage_' + username] = first_message last_message = long(last_message) if last_message > self.settings['lastmessage_' + username]: self.settings['lastmessage_' + username] = last_message return True except IOError: if self.settings['syncing']: self.main.on_sync_down_fail() log_error('Syncing down failed') return False else: return False
def show(self, item_id, *args): if (item_id == -1 or item_id == self.last_id) and len(self.items) > 0: item = self.items.pop(0) try: self.last_id = self.send(item) # In very strange cases the dbus might go aways while we're running # so lets try to grab it again except dbus.exceptions.DBusException: log_error('DBUS error') self.init_dbus() self.last_id = self.send(item) # Play the sound play_sound(self.main, item[3])
def check_autostart(self): if os.path.exists(DESKTOP_FILE): try: with open(DESKTOP_FILE, 'rb') as f: text = f.read() if text.find('X-GNOME-Autostart-enabled=false') != -1: self['autostart'] = False else: self['autostart'] = True except (OSError, IOError): log_error('Could not check autostart') self['autostart'] = False else: self['autostart'] = False
def get_best_prediction(self): """Return prediction with highest expected value.""" try: highest_value = max(self.expected_values.values()) except ValueError: # If errors elsewhere cause a prediction not to be made, default # prediction to 0-0 and expected value to 0.0 print ("No best score found in predictions, defaulting to {}-{}"\ .format(self.prediction[0], self.prediction[1])) errors.log_error("No prediction made for {}".format(self.name)) return (self.prediction, 0.0) for key in self.expected_values.keys(): # better safe than sorry with floats if abs(self.expected_values[key] - highest_value) < 0.0001: best_score = key break return (best_score, highest_value)
def request(self, method, data): tries = 1 while True: conn = httplib.HTTPSConnection(SYNC_SERVER_HOST, SYNC_SERVER_PORT, timeout = 4) try: conn.request('POST', '/' + method, urllib.urlencode(data)) response = conn.getresponse() if response.status == 200: break raise IOError except IOError, error: log_error('Syncing request #%d failed %s' % (tries, error)) tries += 1 if tries > SYNC_MAX_TRIES: raise IOError
def get_no_bonus(league, ptfID, max_result_change, max_score_change, current_pred): """Return lists for results and scores which don't give bonus points. Args: league (League): League object for the match in question. ptfID (str): The identifying number of the match for predictthefootball.com max_result_change (float): Expected maximum fluctuation of prediction rates for results, as a percentage value. max_score_change (float): Expected maximum fluctuation of prediction rates for scores, as a percentage value. current_pred (tuple): Current predicted value for the match. Returns: no_bonus_results (list): Results which don't give bonus points no_bonus_scores (list): Scores which don't give bonus points """ # Retrieve bonus points information url = 'https://{}.predictthefootball.com/site/stats?fixtureid={}'.format( league.get_identifier("PTF url"), ptfID) for i in range(5): try: response = requests.get(url) break except requests.exceptions.ConnectionError: errors.log_error( "ConnectionError for {}. Retries: {}".\ format(url, i+1)) sleep(3) ptfSoup = bs4.BeautifulSoup(response.text, "html.parser") # Find the number of players, used to calculate how much the user's own # predictions will affect the prediction rates. players = get_player_count(ptfSoup) no_bonus_results = get_no_bonus_results( ptfSoup, players, max_result_change, current_pred) no_bonus_scores = get_no_bonus_scores( ptfSoup, players, max_score_change, current_pred) return no_bonus_results, no_bonus_scores
def calculate_predictions(self): # Iterate through matches, calculate the best prediction for each counter = 0 for match in self.matches: for attempt in range(3): try: match.update_all() except errors.OddscheckerUrlError: if attempt == 2: name = match.get_name() print ("OddcheckerUrlError for {}".format(name)) print ("Skipping...") errors.log_error( "OddscheckerUrlError for {}".format(name)) else: continue break counter += 1 print ("Finished {} out of {}".format(counter, len(self.matches)))
def run(self): tries = 0 code = -1 # Wacka! This thing is a mess, sometimes it goes zombie and on other # ocasions it just fails. So the kittens just threw some try/except # on it! player = None while code != 0 and tries < 3: try: # Check for Zombieeeeeees! try: if player is not None: player.kill() log_error('Sound zombie') except OSError: pass player = subprocess.Popen(['play', '-q', self.sound]) code = player.wait() if code != 0: log_error('Sound failed with %d' % code) except OSError, error: log_error('Failed to play sound %s' % error) tries += 1
def get_upcoming(self, within_days=2): try: ptf_matches_info = PTFinter.upcoming_games(self.driver, self.league) except errors.UnexpectedAlertPresentException: self.driver.switch_to_alert().accept() league_name = self.league.get_league_name() print("Alert Error for {}".format(league_name)) errors.log_error("Alert Error for {}".format(league_name)) ptf_matches_info = PTFinter.upcoming_games(self.driver, self.league) league_teams = self.league.get_teams() matches = [] time_now = dt.datetime.now() for info in ptf_matches_info: # Window of time to make predictions # Default is between 2 days before match to 2 minutes before predict_within = [ info[3] - dt.timedelta(days=within_days), info[3] - dt.timedelta(minutes=2)] if not predict_within[0] < time_now < predict_within[1]: continue # set home and away to the home and away teams home = None away = None for team in league_teams: if team.get_identifier("PTF") == info[0]: home = team elif team.get_identifier("PTF") == info[1]: away = team if home is None: raise ValueError("{} not found in teams".format(info[0])) elif away is None: raise ValueError("{} not found in teams".format(info[1])) # Create a Match object and add it to the list of matches newmatch = match.Match( self.league, home, away, info[2], info[3], info[4]) matches.append(newmatch) self.matches = matches
def load_userlist(self, name): try: self.userlist_name = name userfile = os.path.join(ATARASHII_DIR, 'usernames_%s.list' % name) with open(userfile, 'rb') as f: users = f.read().split(',') usrs = [i.strip() for i in users if i.strip() != UNSET_USERNAME] self.user_list = usrs if not name.lower() in [i.lower() for i in self.user_list]: self.user_list.append(name) self.users_changed = True else: self.users_changed = False self.user_list_lower = [] self.users_unsorted = True self.sort_users() except IOError: log_error('Could not load userlist for %s' % name) self.user_list = []
def set_autostart(self, mode): # Create/Delete .desktop file try: # Try to create the folder if it doesn't exists if not os.path.exists(AUTOSTART_DIR): os.mkdir(AUTOSTART_DIR) # Get contents of the desktop file with open(COPY_DESKTOP_FILE, 'rb') as f: text = f.read() # Tweak the file bit bmode = 'true' if mode else 'false' text = text.replace('Exec=atarashii', 'Exec=atarashii auto') text = text.replace('StartupNotify=true', 'StartupNotify=false') with open(DESKTOP_FILE, 'wb') as f: f.write(text + '\nX-GNOME-Autostart-enabled=%s' % bmode) # Only save if we succeeded self['autostart'] = mode except IOError: log_error('Could not set autostart')
def find_correct_url(league, home, away): """Find the correct url for the given home and away teams. Sometimes Oddschecker will have multiple ways to refer to the same team. Instead of having to change the team database every time this happens, just store the additional urls as "Oddschecker2", etc. If this is rewritten, team ids for Oddschecker should be stored as a list of all possible names, but for backwards compatibility this function just checks for all possible keys. Args: league (League): League object home (Team): Team object for home team away (Team): Team object for away team Return: bets (List): List of bs4 tags of all possible bets. home_name (str): The name of the home team which is used. away_name (str): The name of the away team which is used. """ home_urls = [home.get_identifier("Oddschecker", url=True)] away_urls = [away.get_identifier("Oddschecker", url=True)] home_names = [home.get_identifier("Oddschecker")] away_names = [away.get_identifier("Oddschecker")] match_name = home.get_team_name() + " vs " + away.get_team_name() # If a team has more than 2 identifiers, the following loops will be # executed. At the time of writing, the only case where there might be # extra identifiers is for this usecase of multiple Oddschecker IDs, but # in case that changes the loops will check for all but 2 identifiers. # # By storing the non-url names in a parellel list, we can later retrieve # them by using the index where the correct url was found. for i in range(home.count_identifiers() - 2): new_id = "Oddschecker" + str(i) try: home_urls.append(home.get_identifier(new_id, url=True)) home_names.append(home.get_identifier(new_id)) except KeyError: break for i in range(away.count_identifiers() - 2): new_id = "Oddschecker" + str(i) try: away_urls.append(away.get_identifier(new_id, url=True)) away_names.append(away.get_identifier(new_id)) except KeyError: break correct = False # For breaking out of nested for loop. for home_index in range(len(home_urls)): if correct: break for away_index in range(len(away_urls)): # Loop through the possible combinations of urls. # Keeping track of the index allows for looking up the non-url # team names which we have stored in the same order. home_url = home_urls[home_index] away_url = away_urls[away_index] base_url = "http://www.oddschecker.com/football/{}".format(league.get_identifier("OC url")) odds_url = base_url + "/{}-v-{}/correct-score".format(home_url, away_url) for i in range(5): try: response = requests.get(odds_url) break except requests.exceptions.ConnectionError: errors.log_error("ConnectionError for odds of {}. Retries: {}".format(match_name, i + 1)) sleep(3) soup = bs4.BeautifulSoup(response.text, "html.parser") bets = soup.select(".eventTableRow") if len(bets) > 0: # Once a correct page is found, use that one correct = True break if len(bets) == 0: # If after trying all combinations, still no bets are found, # raise an exception raise errors.OddscheckerUrlError home_name = home_names[home_index] away_name = away_names[away_index] return bets, home_name, away_name
def random_error(orderid, storecode): throw_error = random.random() > 0.8 if (throw_error): e.log_error(orderid, storecode) return throw_error
def handle_error(self, error): # Do we need to give focus back to the textbox? self.gui.text.check_refocus() # Determine the kind of the error rate_error = UNSET_ERROR # Timeout errors if isinstance(error, socket.timeout): msg = UNSET_ERROR error_code = 0 error_errno = ERR_URLLIB_TIMEOUT # HTTP Errors elif isinstance(error, HTTPError): msg = UNSET_ERROR error_code = error.code error_errno = None # GAI errors elif isinstance(error, socket.gaierror) or isinstance(error, URLError): msg = UNSET_ERROR if hasattr(error, 'errno'): error_errno = error.errno else: error_errno = ERR_URLLIB_FAILED error_code = 0 # IO errors elif isinstance(error, IOError): if hasattr(error, 'read'): msg = error.read() elif hasattr(error, 'msg'): msg = error.msg else: msg = UNSET_ERROR error_errno = error.errno error_code = error.code if hasattr(error, 'code') else 0 # Tweepy errors else: msg = error.reason error_code = error.response.status error_errno = None # Catch errors due to missing network if error_errno in (ERR_URLLIB_FAILED, ERR_URLLIB_TIMEOUT): code = ERR_NETWORK_FAILED if self.status(ST_LOGIN_SUCCESSFUL) \ or error_errno == ERR_URLLIB_TIMEOUT: code = ERR_NETWORK_TWITTER_FAILED self.gui.set_multi_button(True) self.gui.tray.refresh_menu.set_sensitive(False) # Refresh Views gobject.idle_add(self.gui.tweet.render) gobject.idle_add(self.gui.message.render) # Catch common Twitter errors elif error_code in (HT_400_BAD_REQUEST, HT_401_UNAUTHORIZED, HT_403_FORBIDDEN, HT_404_NOT_FOUND, HT_500_INTERNAL_SERVER_ERROR, HT_502_BAD_GATEWAY, HT_503_SERVICE_UNAVAILABLE): if msg.lower().startswith('no status'): code = ERR_TWEET_NOT_FOUND elif msg.lower().startswith('no direct message'): code = ERR_MESSAGE_NOT_FOUND elif msg.lower().startswith('share sharing'): code = ERR_ALREADY_RETWEETED elif msg.lower().startswith('status is a duplicate'): code = ERR_TWEET_DUPLICATED elif msg.lower().startswith('you cannot send messages'): code = ERR_USER_NOT_FOLLOW else: code = error_code # Ratelimit errors if code == HT_400_BAD_REQUEST and not self.status(ST_WAS_SEND) \ or code == HT_403_FORBIDDEN and self.status(ST_WAS_SEND): self.gui.set_multi_button(False) self.gui.tray.refresh_menu.set_sensitive(False) code, rate_error = self.reconnect() # Just normal HT_400_BAD_REQUEST's and HT_403_FORBIDDEN' elif code == HT_400_BAD_REQUEST and self.status(ST_WAS_SEND) \ or code == HT_403_FORBIDDEN \ and not self.status(ST_WAS_SEND): code = HT_500_INTERNAL_SERVER_ERROR # A real 404. This may be raised if a user wasn't found elif self.status(ST_WAS_SEND) and code == HT_404_NOT_FOUND: code = ERR_USER_NOT_FOUND else: log_error('Unkown error code %s' % error_code) code = ERR_NETWORK_FAILED # Reset stuff self.unset_status(ST_WAS_SEND | ST_WAS_RETWEET | \ ST_WAS_RETWEET_NEW | ST_WAS_DELETE) # Leave it to the GUI! self.gui.show_error(code, rate_error) # Log the error if error_errno is None: error_errno = 0 log_error('%s %d' % (ERR_MAPPING[code], error_errno))