def do_body(self, args): """Render the HTMl for the goal scorer tally""" year = self.get_year(args) mem_key = ScorersPage.get_mem_key(year) scorer_page = memcache.get(mem_key) if scorer_page is None: if year == ALL_YEARS: players = Player.all() else: players = [ t.player for t in TeamList.gql('WHERE year = :1', year) ] scorers = [] for p in players: tally = 0 for g in p.goal_set: round = g.result.round if (year == ALL_YEARS or year == round.date.year) and round.num > 0: # Only count real goals - negative rounds are trials tally += g.count if tally > 0: scorers.append((p.get_short_name(), tally)) scorers.sort(self.sort_scores) data = { 'scorers': scorers, } tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, 'scorers.html') scorer_page = template.render(tpath, data) memcache.set(mem_key, scorer_page) self.response.out.write(scorer_page)
def do_player_list(self, args, manage_mode=False): """Render the HTML for a list of players""" year = self.get_year(args) if manage_mode: mem_key = PlayerPage.get_manage_list_mem_key(year) else: mem_key = PlayerPage.get_list_mem_key(year) player_div = memcache.get(mem_key) if player_div is None: data = { 'url_args': args, } if year == ALL_YEARS: data['players'] = Player.gql( 'ORDER BY last_name ASC, first_name ASC') else: data['players'] = [ p.player for p in TeamList.gql('WHERE year = :1', year) ] data['players'].sort(self.sort_players) tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, 'players.html') player_div = template.render(tpath, data) memcache.set(mem_key, player_div) self.response.out.write(player_div)
def do_body(self, args): year = self.get_year(args) if year == ALL_YEARS: players = Player.all() else: players = [t.player for t in TeamList.gql('WHERE year = :1', year)] players.sort(self.sort_players) data = { 'players': players, } tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, 'manage_protected.html') protected_page = template.render(tpath, data) self.response.out.write(protected_page)
def do_body(self, args): """Render the HTML for all the results, and provide enough information to edit an game""" data = { 'url_args': args, } year = self.get_year(args) if year == ALL_YEARS: data['rounds'] = Round.gql('ORDER BY date ASC') else: data['rounds'] = Round.gql('WHERE year = :1 ORDER BY date ASC', year) tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, 'rounds.html') self.response.out.write(template.render(tpath, data)) data = { 'url_args': args, } # Get the full data for the given round so they can edit it if args.has_key('round'): round_num = args['round'] round_key = Round.get_key(round_num, year) result_key = Result.get_key(round_num, year) if round_key != '': curr_round = Round.get_by_key_name(round_key) if curr_round: data['players'] = [ p.player for p in TeamList.gql('WHERE year = :1', curr_round.date.year) ] data['players'].sort(self.sort_players) data['round'] = curr_round curr_result = Result.get_by_key_name(result_key) if curr_result: data['result'] = curr_result if curr_result.other_goals == 0: curr_result.other_goals = None if curr_result.own_goals == 0: curr_result.own_goals = None #if curr_result.deewhy_forfeit: # curr_result.deewhy_goals = 0 # curr_result.opponent_goals = 5 #elif curr_result.opponent_forfeit: # curr_result.deewhy_goals = 5 # curr_result.opponent_goals = 0 tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, 'manage_results.html') self.response.out.write(template.render(tpath, data))
def do_body(self, args): """Render a given year's item summary. Makes no sense for multi-year.""" year = self.get_year(args) mem_key = CommonItemPage.get_mem_key(self.type, year) item_page = memcache.get(mem_key) if item_page is None: items = self.data_class.gql('WHERE year = :1', year) items = [i for i in items] items.sort(self.sort_tuple) remaining = [ t.player.get_short_name() for t in TeamList.gql('WHERE year = :1', year) ] rounds = [] for i in items: round = i.round # Only display entries that already have a result if round.result.get() is not None: caption = round.caption if not caption: caption = round.num if self.get_person(i) in self.data_class.OTHERS: person = self.data_class.OTHERS_FRIENDLY[ self.get_person(i)] else: person = i.player_ref.get_short_name() try: remaining.remove(person) except ValueError: # It was already removed before pass rounds.append((caption, person)) if len(remaining) > 0: remaining_str = ', '.join(remaining) else: remaining_str = 'Nobody' data = { 'rounds': rounds, 'remaining': remaining_str, 'url_args': args, } tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, self.template_file) item_page = template.render(tpath, data) memcache.set(mem_key, item_page) self.response.out.write(item_page)
def do_body(self, args): """Render the HTML for the page containing private details for everybody currently in the team.""" mem_key = ProtectedPage.get_mem_key() protected_page = None #memcache.get(mem_key) if protected_page is None: players = [ t.player for t in TeamList.gql('WHERE year = :1', datetime.now().year) ] # Always this year players.sort(self.sort_players) data = { 'players': players, } tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, 'protected.html') protected_page = template.render(tpath, data) memcache.set(mem_key, protected_page) self.response.out.write(protected_page)
def do_body(self, args): """Render the HTML for all the items, and provide enough information to edit one of them.""" updated_args = dict(args) year = self.get_year(args) updated_args['year'] = year data = { 'url_args': updated_args, } if year == ALL_YEARS: data['rounds'] = Round.gql('ORDER BY date ASC') data['players'] = Player.gql( 'ORDER BY last_name ASC, first_name ASC') else: data['rounds'] = Round.gql('WHERE year = :1 ORDER BY date ASC', int(year)) data['players'] = [ p.player for p in TeamList.gql('WHERE year = :1', int(year)) ] data['players'].sort(self.sort_players) tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, self.template_file) self.response.out.write(template.render(tpath, data))
def quick_stalk(url): """ Stalk all players in a match, requires a direct link to the match on challengermode :param url: Str, a link that shows a single match on challengermode :return: TeamList, containing both teams in the match """ logger.debug("Beginning challengermode quick stalk for " + url) driver = open_session() driver.get(url) time.sleep(3) challenger_soup = bs4.BeautifulSoup(driver.page_source, features="html.parser") quit_session(driver) team_containers = challenger_soup.find_all('div', class_="col-md-6") title = challenger_soup.select("#arena-wrap > div.pos--rel.flx--1-1-auto.w--100 > div.m-b--base > div:nth-child(3) > div.pos--rel.z--999 > div.cm-arena-wrap.arena-padding-horizontal > div.ta--center.m-v--medium.p-t--base--sm.cm-text-shadow > div.h1.lh--title.ellipsis > div > a")[0].text teams = [] for team_container in team_containers: team_name_block = team_container.find('div', class_="dis--none dis--blk--sm m-b--minimum") if team_name_block is None: team_name_block = team_container.find('div', class_="dis--none dis--blk--sm m-b--minimum m-t--medium") team_name_raw = team_name_block.text team_name_list = team_name_raw.split(" ") team_name = "".join(team_name_list[:len(team_name_list)-25]).strip() player_opggs_htmls = team_container.find_all('a', class_="link-white-dark") player_opggs = [] for player_opggs_html in player_opggs_htmls: player_opggs.append(player_opggs_html['href']) players = [] for player_opgg in player_opggs: rest, sum_name = player_opgg.split("=") players.append(Player(sum_name.replace("+", " "))) teams.append(Team(team_name, players)) return TeamList(title.strip(), teams)
def stalk_group(url): """ Returns a TeamList object for all teams in the group behind the given url. :param url: Str, a link to a group in a SINN League :return: TeamList, a TeamList object containing all teams of the group """ logger.debug("Beginning sinn league group stalk for " + url) # open web session page = requests.get(url) # Select Rangliste Container and find division name soup = bs4.BeautifulSoup(page.text, features="html.parser") list_container = soup.find( 'table', class_="table table-fixed-single table-responsive") # div_name = driver.find_element_by_xpath("//*[@id=\"container\"]/div/h1").text div_name = soup.select("#container > div > h1")[0].text # extract all team-links links = [link["href"] for link in list_container.find_all("a", href=True)] links = list(dict.fromkeys(links)) # create task Q over all team-links single_tasks = [] for link in links: single_task = task_queue.SingleTask(stalk_team, link) single_tasks.append(single_task) task_group = task_queue.TaskGroup(single_tasks, "stalk: " + div_name) teams = task_queue.submit_task_group(task_group) # return results for team in teams: if team is None: teams.remove(team) return TeamList(div_name, teams)
def do_body(self, args): """Generate the HTML email if there is an upcoming game""" day_skip = 2 if args.has_key('days'): try: day_skip = int(args['days']) except: pass admin_address = '*****@*****.**' curr_date = datetime.now() start_date = curr_date.replace(hour=0, minute=0, second=0) + timedelta(days=day_skip) end_date = curr_date.replace(hour=0, minute=0, second=0) + timedelta(days=day_skip + 1) # Find all the games that are within the given date range - really only expect one, behaviour # could end up a little strange if there's multiple... query = Round.gql('WHERE date >= :1 AND date <= :2', start_date, end_date) curr_round = query.get() logging.debug('WHERE date >= %s AND date <= %s' % (start_date, end_date)) logging.debug(curr_round) if curr_round: data = { 'current': curr_round, } tpath = os.path.join(DeeWhyPage.TEMPLATE_DIR, 'mailer.html') email_content = template.render(tpath, data) self.response.out.write( email_content) # Print the content as an added debug players = [ p.player for p in TeamList.gql('WHERE year = :1', curr_round.date.year) ] non_admins = [] admin = '' for p in players: details = '%s %s<%s>' % (p.first_name, p.last_name, p.email) if p.email == admin_address: admin = details else: non_admins.append(details) recipients = ','.join(non_admins) cc_recipients = admin # working around a server bug where cron emails fail when sent to me! #recipients = 'Test Guy<*****@*****.**>' % (curr_date.strftime('%A %d %B %I:%M')) # To make sure tests don't go out! logging.debug('Sending to ' + recipients) """ recipients = ','.join([ 'Adam1<*****@*****.**>', 'Adam2<*****@*****.**>', ]) logging.debug('Really sending to ' + recipients) """ caption = curr_round.caption if not caption: caption = 'Round ' + ` int(curr_round.num) ` kickoffStr = ` int(curr_round.time.strftime('%I')) ` if curr_round.time.minute > 0: kickoffStr += ':' + curr_round.time.strftime('%M') kickoffStr += curr_round.time.strftime('%p') subject = caption + ' - ' + curr_round.date.strftime( '%A %d %B') + ' at ' + kickoffStr message = mail.EmailMessage() message.subject = subject message.sender = 'Dee Why AL5 Team Page<*****@*****.**>' message.to = recipients message.cc = cc_recipients # Too lazy to add BCC recipients as a UI option so just add them here message.bcc = '*****@*****.**' message.html = email_content message.check_initialized() message.send()
def post(self, base_url, extra): """Save the data posted about the result from the HTML form""" try: curr_round = None round_num = int(self.request.get('round_num')) year = int(self.request.get('year')) round_key = Round.get_key(round_num, year) if round_key: curr_round = Round.get_by_key_name(round_key) if curr_round: # Quite a few cached pages depend upon this output, need to delete them all # - Removing this page from the summary memcache.delete(PlayerPage.get_draw_mem_key(year)) memcache.delete(PlayerPage.get_draw_mem_key(ALL_YEARS)) # - Disabling the options for this page for each player for t in TeamList.gql('WHERE year = :1', year): memcache.delete( PlayerPage.get_player_mem_key(t.player.db_key, year)) # - Changing the result and who scored memcache.delete(ResultsPage.get_mem_key(year)) memcache.delete(ResultsPage.get_mem_key(ALL_YEARS)) # - Changing the number of goals memcache.delete(ScorersPage.get_mem_key(year)) memcache.delete(ScorersPage.get_mem_key(ALL_YEARS)) # - Triggering previously suppressed rounds for the beer and shirts memcache.delete(BeerPage.get_mem_key('beer', year)) memcache.delete(BeerPage.get_mem_key('beer', ALL_YEARS)) memcache.delete(ShirtsPage.get_mem_key('shirts', year)) memcache.delete(ShirtsPage.get_mem_key('shirts', ALL_YEARS)) args = { 'year': year, 'key_name': Result.get_key(round_num, year), 'round': curr_round, } deewhy_forfeit = self.request.get('deewhy_forfeit') opponent_forfeit = self.request.get('opponent_forfeit') if not (deewhy_forfeit or opponent_forfeit): # Regular operation - read the goal counts args['deewhy_goals'] = self.get_goals('deewhy_goals') args['opponent_goals'] = self.get_goals('opponent_goals') args['other_goals'] = self.get_goals('other_goals') args['own_goals'] = self.get_goals('own_goals') elif deewhy_forfeit is not None and self.request.get( 'deewhy_forfeit') == 'on': # No goals in a forfeit args['deewhy_forfeit'] = True elif opponent_forfeit is not None and self.request.get( 'opponent_forfeit') == 'on': # No goals in a forfeit args['opponent_forfeit'] = True curr_result = Result(**args) curr_result.put() # Need to delete any existing scorers for this round - otherwise orphaned goals will stuff up the tallies for scorer in curr_result.scorer_set: scorer.delete() if not (deewhy_forfeit or opponent_forfeit): for post_key in self.request.POST.keys(): # Each goal scorer in the game needs a separate record if post_key.startswith('goals_'): player = Player.get_by_key_name( post_key[len('goals_'):]) goals = self.get_goals(post_key) if player is not None and goals > 0: GoalsScored( key_name=GoalsScored.get_key( player.db_key, round_num, year), year=int(year), player=player, result=curr_result, count=goals, ).put() self.get(base_url, extra) except Exception, e: self.get(base_url, extra, error=e)
def post(self, base_url, extra): """Save the data posted about the player from the HTML form""" #try: affected_years = set() old_key = self.request.get('key_name') if self.request.POST.has_key('do_delete') and self.request.POST.get( 'do_delete') == 'true': # Delete the selected player # Also need to delete anything else they were involved with e.g. teamlists, goals scored, etc... key = old_key player = Player.get_by_key_name(key) for x in player.year_list: x.delete() for x in player.beer_set: x.delete() for x in player.shirt_set: x.delete() for x in player.goal_set: x.delete() for x in player.availability_set: x.delete() self.delete_player(key) else: # Create/update the player first = self.request.get('first_name').strip() last = self.request.get('last_name').strip() key = Player.get_key(first, last) nick = self.request.get('nick_name').strip() email = self.request.get('email').strip() phone = self.request.get('phone').strip() registration = self.request.get('registration').strip() shirt = self.request.get('shirt').strip() if key != '': new_player = Player( key_name=key, db_key=key, first_name=first, last_name=last, nick_name=nick, email=email, phone=phone, registration=registration, shirt=shirt, ) new_player.put() for y in xrange(datetime.now().year, FIRST_YEAR - 1, -1): year_key = TeamList.get_key(key, y) if self.request.POST.has_key('played_' + str(y)): TeamList( key_name=year_key, player=new_player, year=y, ).put() else: self.delete_player_year(year_key) if old_key != key: # If changing the info changes the key, be sure to scrap the old entry too self.delete_player(old_key) # Quite a few pages are potentially affected when you change a player's details. But only do it if the # form says to do so, because it's so expensive to regenerate everything! nickname_update = (self.request.POST.has_key('do_flush') and self.request.get('do_flush') == 'on') # Update the side listings memcache.delete(PlayerPage.get_list_mem_key(ALL_YEARS)) memcache.delete(PlayerManagePage.get_list_mem_key(ALL_YEARS)) memcache.delete(PlayerPage.get_player_mem_key( key, ALL_YEARS)) # Their availability if nickname_update: memcache.delete(PlayerPage.get_draw_mem_key(ALL_YEARS)) memcache.delete(ResultsPage.get_mem_key(ALL_YEARS)) memcache.delete(ScorersPage.get_mem_key(ALL_YEARS)) memcache.delete(BeerPage.get_mem_key('beer', ALL_YEARS)) memcache.delete(ShirtsPage.get_mem_key('shirts', ALL_YEARS)) memcache.delete(ProtectedPage.get_mem_key()) for y in xrange(datetime.now().year, FIRST_YEAR - 1, -1): memcache.delete(PlayerPage.get_list_mem_key(y)) memcache.delete(PlayerManagePage.get_list_mem_key(y)) memcache.delete(PlayerPage.get_player_mem_key( key, y)) # Their availability if nickname_update: memcache.delete(PlayerPage.get_draw_mem_key(y)) memcache.delete(ResultsPage.get_mem_key(y)) memcache.delete(ScorersPage.get_mem_key(y)) memcache.delete(BeerPage.get_mem_key('beer', y)) memcache.delete(ShirtsPage.get_mem_key('shirts', y)) self.get(base_url, extra)
def delete_player_year(self, key): """Remove the association between the player and the year""" if key: t = TeamList.get_by_key_name(key) if t: t.delete()
def post(self, base_url, extra): """Save the details for the given round""" try: old_key = self.request.get('key_name') if self.request.POST.get('do_delete') == 'true': # Delete the selected round self.delete_round(old_key) year = old_key.split('-')[0] else: # Create/update the round num = int(self.request.get('num').strip()) caption = self.request.get('caption').strip() #if caption == '': # caption = 'Rd ' + `num` try: date = datetime.strptime( self.request.get('date').strip(), '%d/%m/%Y').date() except: date = datetime.strptime( self.request.get('date').strip(), '%d/%m/%y').date() time_value = self.request.get('time').strip() if time_value == '': time = None else: time = datetime.strptime(time_value, '%H:%M').time() opponent = self.request.get('opponent').strip() homeaway = self.request.get('homeaway').strip() location = Ground.get(self.request.get('location')) key = Round.get_key(num, date.year) if key != '' and num != '': new_round = Round( key_name=key, num=num, year=date.year, caption=caption, date=date, time=time, opponent=opponent, homeaway=homeaway, location=location, ) new_round.put() if old_key != key: # If changing the info changes the key, be sure to scrap the old entry too self.delete_round(old_key) year = date.year # Pages that are affected by this post: # - Draw, via a new item memcache.delete(PlayerPage.get_draw_mem_key(year)) memcache.delete(PlayerPage.get_draw_mem_key(ALL_YEARS)) # - All the individual player pages, via the items they can update for p in TeamList.gql('WHERE year = :1', year): memcache.delete( PlayerPage.get_player_mem_key(p.player.db_key, year)) memcache.delete( PlayerPage.get_player_mem_key(p.player.db_key, ALL_YEARS)) # NOT - results, beer or shirts (until results posted) self.get(base_url, extra) except Exception, e: self.get(base_url, extra, error=e)
def stalk(toornament_link): """ Stalks all teams signed up for the given toornament and returns an op.gg multi link for each team :param toornament_link: String, url to a tournament on toornament :return: List[(String, String)], containing a tuple with the team name and the op.gg multi links for each team """ logger.debug("Beginning toornament stalk for " + toornament_link) # open the websession driver = open_session() driver.get(toornament_link) # find the participants button and press it participants_button = driver.find_element_by_xpath( "//*[@id=\"tournament-nav\"]/div/section/div/ul/li[2]/a") participants_button.click() time.sleep(2) # find all teams and save the links participants_links = [] base_url = "https://www.toornament.com" toornament_soup = bs4.BeautifulSoup(driver.page_source, features="html.parser") team_container = toornament_soup.find_all('div', class_="size-1-of-4") # multiple team page test driver.get(str(driver.current_url) + "?page=1") count = 1 while True: count += 1 driver.get(str(driver.current_url)[:-1] + str(count)) toornament_soup2 = bs4.BeautifulSoup(driver.page_source, features="html.parser") if len(toornament_soup2.find_all('div', class_="size-1-of-4")) > 0: team_container.extend( toornament_soup2.find_all('div', class_="size-1-of-4")) else: break quit_session(driver) # extract toornament name tournament_name = toornament_soup.select( "#main-container > div.layout-section.header > div > section > div > div.information > div.name > h1" )[0].text for team in team_container: a = team.find('a', href=True) participants_links.append(base_url + a['href']) # open each link, switch to information and collect the Summoner Names single_tasks = [] for link in participants_links: single_tasks.append(SingleTask(stalk_team, link)) task_group = TaskGroup(single_tasks, "stalk: " + tournament_name) teams_players_tuples = submit_task_group(task_group) # build Player, Team and TeamList objects team_list = [] for team in teams_players_tuples: sum_names = team[0] team_name = team[1] players = [] for sum_name in sum_names: players.append(Player(sum_name)) team_list.append(Team(team_name, players)) return TeamList(tournament_name, team_list)