def main(): current_games = [ f'{platform}_{category}_{name}' for platform, category, name in iter_parse_played_games(get_games()) ] changed_count = 0 for game in Game.select(): name = f'{game.platform}_{game.category}_{game.name}' last_ignored = game.ignored game.ignored = name not in current_games if last_ignored != game.ignored: log.info( f'#{game.id} {game.name} ({game.platform}, {game.category}): {last_ignored} -> {game.ignored}' ) game.save() changed_count += 1 if changed_count: text = f'Изменений: {changed_count}' log.debug(text) add_notify(log.name, text)
def test_check_global_timed_game_creates_new_game_upon_expiration(self): game_before_check = Game.get(Game.name == 'Global Timed') game_before_check.ends_at = datetime.utcnow() game_before_check.save() check_global_timed_game() self.assertEqual( 0, Game.select().where(Game.id == game_before_check.id).count()) Game.get(Game.name == 'Global Timed')
def active_games_at_page(profile_id, page_number, keyword, criteria): """ Returns - active games in the requested page that matches the keyword (sorted by criteria) - number of active games matching the keyword """ games_query = Game.select() \ .join(GameProfile) \ .where((GameProfile.profile == profile_id) & Game.name.contains(keyword) & (Game.ends_at > datetime.utcnow())) # Note: This line always filters out Global Indef. # LOOKATME: Depending on the keyword, the call above might return EVERY games from the database that belongs to # the player. If that is expensive, optimize this. games = [gm for gm in games_query] global_indef = Game.get_or_none(Game.id == 1) include_global_indef = False if keyword.lower() in global_indef.name.lower( ): # Cannot append global_indef to games yet, include_global_indef = True # else sorting by endTime will break total_games = len(games) + 1 if include_global_indef else len(games) max_page = int(ceil(total_games / PAGE_SIZE)) # Verify page is within range page_number = max(1, page_number) page_number = max_page if page_number > max_page else page_number from operator import attrgetter if criteria['titleAscending']: games.append(global_indef) games.sort(key=attrgetter("name")) elif criteria['titleDescending']: games.append(global_indef) games.sort(key=attrgetter("name"), reverse=True) elif criteria['endTimeAscending']: games.sort(key=attrgetter("ends_at")) games.append(global_indef) elif criteria['endTimeDescending']: games.sort(key=attrgetter("ends_at"), reverse=True) games.insert(0, global_indef) else: games.insert(0, global_indef) first_index_in_page = (page_number - 1) * PAGE_SIZE games = games[first_index_in_page:first_index_in_page + PAGE_SIZE] return games, total_games, PAGE_SIZE
'14': 'XIV', '15': 'XV', } # В какой-то момент поменял платформу с PS на PS1, нужно играм с PS1 указать # на те же игры с PS # В другой момент писал 'PS 2', после поменял название категории на PS2 old_by_new_platforms = { 'PS': 'PS1', 'PS 2': 'PS2', 'PS 3': 'PS3', 'PS 4': 'PS4', } for old_platform, new_platform in old_by_new_platforms.items(): # Ищем игры с указанной платформой и без заданного root_alias for game in Game.select().where(Game.platform == new_platform, Game.root_alias.is_null()): root_game = Game.get_or_none(Game.platform == old_platform, Game.name == game.name, Game.category == game.category) # Если не найдено или если у найденной id больше, чем у требуемой игры if not root_game or root_game.id > game.id: continue print(f'In game #{game.id} setted root_alias from #{root_game.id}') game.root_alias = root_game game.save() # У некоторых игр арабские цифры в названии были заменены на римские for root_game in Game.select(): m = re.search(r'\d+', root_game.name) if not m:
# 2021-01-06 14:20:35+00:00 -> 0 # 2021-01-08 05:23:31+05:00 -> 18000 def get_tz_secs(dt: DT.datetime) -> int: return int(dt.utcoffset().total_seconds()) for gist_file in GistFile.select(): if get_tz_secs(gist_file.committed_at_dt) > 0: continue gist_file.committed_at = utc_to_local(gist_file.committed_at_dt) gist_file.save() for game in Game.select(): append_datetime_dt = game.append_datetime_dt finish_datetime_dt = game.finish_datetime_dt changed = False if append_datetime_dt and get_tz_secs(append_datetime_dt) == 0: game.append_datetime = utc_to_local(append_datetime_dt) changed = True if finish_datetime_dt and get_tz_secs(finish_datetime_dt) == 0: game.finish_datetime = utc_to_local(finish_datetime_dt) changed = True if changed: game.save()
from collections import defaultdict from typing import List from db import Game def has_nearest_dates(games: List[Game], diff_secs=60) -> bool: dates = [game.finish_datetime_dt for game in games] return any( abs((dt1 - dt2).total_seconds()) <= diff_secs for dt1, dt2 in itertools.combinations(dates, 2) ) finish_by_games = defaultdict(list) for game in Game.select().where(Game.ignored == 0): if not game.finish_datetime_dt: continue date = game.finish_datetime_dt.date() finish_by_games[date].append(game) finish_by_games = {k: v for k, v in finish_by_games.items() if len(v) > 1 and has_nearest_dates(v)} print(len(finish_by_games)) for date, games in finish_by_games.items(): print(f'{date} ({len(games)}):') for x in games: print(f' {x}') print()
def index(): title = 'Games with RTX' URL = 'https://kanobu.ru/games/collections/igry-s-podderzhkoi-rtx/' headers = ['#', 'Игра', 'Дата добавления'] games = Game.select().order_by(Game.id.desc()) return render_template_string(""" <!DOCTYPE html> <html lang="ru"> <head> <meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/> <title>{{ title }}</title> <style type="text/css"> table { border-collapse: collapse; /* Убираем двойные линии между ячейками */ } /* Увеличим заголовок таблиц */ table > caption { font-size: 150%; } .frame th { font-size: 120%; } .frame td, .frame th { border: 1px double #333; /* Рамка таблицы */ padding: 5px; } .thumbnail { width: 64px; height: 64px; } </style> </head> <body> <table class="frame" style="width: 800px; margin:0 auto;"> <caption><a href="{{ URL }}">{{ title }} ({{ games.count() }})</a></caption> <colgroup> <col span="1"> </colgroup> <tbody> <tr> {% for header in headers %} <th>{{ header }}</th> {% endfor %} </tr> {% for game in games %} <tr> <td>{{ loop.index }}</td> <td valign="top"> <a target="_blank" href="{{ game.url }}"> <img class="thumbnail" src="{{ game.img_base64 }}" align="left"> </a> <div> {{ game.name }}</div> </td> <td valign="top">{{ game.append_date }}</td> </tr> {% endfor %} </tbody> </table> </body> </html> """, games=games, headers=headers, title=title, URL=URL)
# Чтобы можно было импортировать all_common.py, находящийся уровнем выше sys.path.append('..') # Для импортирования kanobu_ru__games__collections__igry_s_podderzhkoi_rtx.py sys.path.append('../../html_parsing') from all_common import get_logger, wait, simple_send_sms from kanobu_ru__games__collections__igry_s_podderzhkoi_rtx import get_games from db import db_create_backup, Game log = get_logger(__file__) while True: log.debug('Запуск') is_empty = not Game.select().count() if is_empty: log.debug('Обнаружен первый запуск') else: db_create_backup() try: has_new_game = False games = get_games() log.debug(f'Обработка {len(games)} игр') for game in games: game_db, created = Game.get_or_create(name=game.name, url=game.url) if game_db.img_base64 != game.img_base64: game_db.img_base64 = game.img_base64