""" ░██████╗░██████╗░██╗░░░░░███╗░░░███╗███████╗██████╗░██████╗░ ██╔════╝██╔═══██╗██║░░░░░████╗░████║██╔════╝██╔══██╗██╔══██╗ ╚█████╗░██║██╗██║██║░░░░░██╔████╔██║█████╗░░██████╔╝██████╔╝ ░╚═══██╗╚██████╔╝██║░░░░░██║╚██╔╝██║██╔══╝░░██╔══██╗██╔══██╗ ██████╔╝░╚═██╔═╝░███████╗██║░╚═╝░██║███████╗██║░░██║██║░░██║ ╚═════╝░░░░╚═╝░░░╚══════╝╚═╝░░░░░╚═╝╚══════╝╚═╝░░╚═╝╚═╝░░╚═╝ """ # meta developer: @sqlmerr_m # meta icon: https://github.com/sqlmerr/hikka_mods/blob/main/assets/icons/egsfreegames.png?raw=true # meta banner: https://github.com/sqlmerr/hikka_mods/blob/main/assets/banners/egsfreegames.png?raw=true import logging from typing import Dict, List, Optional import datetime import aiohttp from .. import utils, loader from hikkatl.tl.patched import Message @loader.tds class EGSFreeGames(loader.Module): """Module for checking free games in Epic Games Store. Inline bot will send them every day in special chat""" strings = { "name": "EGSFreeGames", "game": ( "- Game: {title}\n" " Status: {status}\n" " Promotion started at: {start}\n" " Promotion will end at: {end}\n" " Link: {url}\n" ), "header": "🎮 Free games in EGS:", "header_bot": "🎮 Today's free games in EGS:", "footer": "ℹ️ The active status means that the game can be picked up now.\nThe upcoming status means that the game can be picked up later", "_region_cfg": "Free games check region", "_schedule_checking_cfg": "Will the bot automatically send the current free games to a special chat room", } strings_ru = { "game": ( "- Игра: {title}\n" " Статус: {status}\n" " Акция началась: {start}\n" " Акция закончится: {end}\n" " Ссылка: {url}\n" ), "header": "🎮 Бесплатные игры в EGS:", "header_bot": "🎮 Сегодняшние бесплатные игры в EGS:", "footer": "ℹ️ Статус active означает, что игру можно забрать уже сейчас.\nСтатус upcoming означает, что игру можно будет забрать потом.", "_region_cfg": "Регион проверки бесплатных игр", "_schedule_checking_cfg": "Будет ли бот автоматически отправлять в специальный чат текущие бесплатные игры", "_cls_doc": "Модуль для проверки бесплатных игр в Epic Games Store. Инлайн бот будет отправлять их каждый день в специальном чате", } async def client_ready(self): self.chat, _ = await utils.asset_channel( self._client, "EGS Free Games", "There will be free games from epic games every day", avatar="https://github.com/sqlmerr/hikka_mods/blob/main/assets/icons/egsfreegames_chat.png?raw=true", invite_bot=True, _folder="hikka", ) def __init__(self): self.config = loader.ModuleConfig( loader.ConfigValue( "region", default="RU", doc=lambda: self.strings("_region_cfg"), validator=loader.validators.String(), ), loader.ConfigValue( "schedule_checking", default=True, doc=lambda: self.strings("_schedule_checking_cfg"), validator=loader.validators.Boolean(), ), ) def create_game_info(self, game, offer, status, available_in_russia=None): price_info = { "discount": 0, "RUB": {"original": -1, "current": -1}, "USD": {"original": -1, "current": -1}, } if game.get("price"): total_price = game["price"].get("totalPrice", {}) discount = offer["discountSetting"]["discountPercentage"] original_price = total_price.get("originalPrice", 0) / 100 current_price = total_price.get("discountPrice", original_price) / 100 currency = total_price.get("currencyCode", "USD") if currency in price_info: price_info[currency] = { "original": original_price, "current": current_price, } price_info["discount"] = discount slug = ( game["productSlug"] if game["productSlug"] else game["catalogNs"]["mappings"][0]["pageSlug"] ) url = "https://store.epicgames.com/ru/p/" + slug return { "title": game["title"], "publisher": game.get("seller", {}).get("name"), "status": status, "start_date": offer["startDate"], "end_date": offer["endDate"], "url": url, "image_url": game.get("keyImages", [{}])[0].get("url"), "price": price_info, "available_in_russia": available_in_russia, } def process_offers( self, game: Dict, offers: List, status: str, available_in_russia=None ): games_list = [] if offers: for offer in offers[0].get("promotionalOffers", []): if offer["discountSetting"]["discountPercentage"] == 0: games_list.append( self.create_game_info(game, offer, status, available_in_russia) ) return games_list def get_normal_timestamp(self, date: str) -> str: dt = datetime.datetime.fromisoformat(date.replace("Z", "+00:00")) dt = dt.astimezone(datetime.timezone.utc) formatted_date = dt.strftime("%d.%m.%Y %H:%M (UTC)") return formatted_date async def get_free_games(self, region: str = "RU") -> Optional[List]: url = "https://store-site-backend-static.ak.epicgames.com/freeGamesPromotions" params = {"locale": "en-US", "country": region, "allowCountries": region} try: async with aiohttp.ClientSession() as session: response = await session.get(url, params=params) response.raise_for_status() data = await response.json() games = [] for game in data["data"]["Catalog"]["searchStore"]["elements"]: if not game.get("promotions"): continue promotions = game["promotions"] promo = promotions.get("promotionalOffers", []) upcoming = promotions.get("upcomingPromotionalOffers", []) games.extend(self.process_offers(game, promo, "active", None)) games.extend(self.process_offers(game, upcoming, "upcoming", None)) return games except aiohttp.ClientResponseError as e: return def gen_text(self, games: List[Dict], bot: bool = False) -> str: header = self.strings("header") if not bot else self.strings("header_bot") text = "".join( [ self.strings("game").format( title=g["title"], status=g["status"], start=self.get_normal_timestamp(g["start_date"]), end=self.get_normal_timestamp(g["end_date"]), url=g["url"], ) + "\n" for g in games ] ) footer = self.strings("footer") if not bot else "" return f"{header}\n\n{text}{footer}" @loader.command(ru_doc="Получить бесплатные игры доступные в Epic Games Store") async def egsgames(self, message: Message): """Get free games links available in Epic Games Store""" games = await self.get_free_games(self.config["region"]) text = self.gen_text(games) await utils.answer(message, text) @loader.loop(interval=86400, autostart=True) async def loop(self, *args, **kwargs): if not self.config["schedule_checking"]: return games = await self.get_free_games(self.config["region"]) text = self.gen_text(games, bot=True) chat_id = utils.get_entity_id(self.chat) await self.inline.bot.send_message(chat_id=chat_id, text=text)