#M i d g a 3
#meta developer: @midga3_modules
# scope: heroku_min 2.0.0
from google_play_scraper import app as gp_app, search as gp_search
import logging
from .. import loader, utils
from herokutl.tl.types import Message
__verison__ = (1, 1, 0)
logger = logging.getLogger(__name__)
@loader.tds
class playsearch(loader.Module):
"""
Search games!
"""
strings = {
"name": "PlaySearch",
"searching": "{}",
"update_notify": "🔄 Update available!\n\n{}\n Version: {}\nUpdated: {}\n\nOpen in Play Store",
"sub_usage": "Usage: .subscribe <app_id>\nExample: .subscribe com.nianticlabs.pokemongo",
"unsub_usage": "Usage: .unsubscribe <app_id>",
}
def __init__(self):
self.config = loader.ModuleConfig()
def _get_subs(self):
return self._db.get("playsearch", "subs", default={})
def _save_subs(self, subs):
self._db.set("playsearch", "subs", subs)
@loader.loop(interval=300, autostart=True)
async def poller(self):
subs = self._get_subs()
if not subs:
return
for app_id, info in list(subs.items()):
try:
data = gp_app(app_id, lang="en", country="us")
except Exception as e:
logger.error(f"Error fetching {app_id}: {e}")
continue
new_version = data.get('version', '')
new_updated = data.get('updated', 0)
old_version = info.get('version', '')
old_updated = info.get('updated', 0)
if new_version != old_version or new_updated != old_updated:
info['version'] = new_version
info['updated'] = new_updated
subs[app_id] = info
self._save_subs(subs)
if old_version:
for user_id in info.get('users', []):
try:
await self._client.send_message(
user_id,
self.strings['update_notify'].format(
data.get('title', app_id),
new_version,
new_updated,
app_id
),
disable_web_page_preview=True
)
except Exception as e:
logger.error(f"Error notifying {user_id}: {e}")
def _game_nav(self, pages, index):
if len(pages) <= 1:
return None
buttons = []
if index > 0:
buttons.append({"text": "◀️", "callback": self._game_page, "args": (pages, index - 1)})
buttons.append({"text": f"{index + 1}/{len(pages)}", "callback": self._game_page, "args": (pages, index)})
if index < len(pages) - 1:
buttons.append({"text": "▶️", "callback": self._game_page, "args": (pages, index + 1)})
return [buttons]
async def _game_page(self, call, pages, index):
await call.edit(pages[index], reply_markup=self._game_nav(pages, index))
@loader.command()
async def game(self, message: Message):
"""
Find games.
"""
args = utils.get_args_raw(message)
if not args:
await message.edit(self.strings['not_found'])
return
await message.edit(self.strings['searching'])
try:
results = gp_search(args, lang="en", country="us", n_hits=15)
except Exception as e:
logger.error(f"Error: {e}")
await message.edit(self.strings['not_found'])
return
if not results:
await message.edit(self.strings['not_found'])
return
pages = []
step = 15 if self.config.get("show_all_15", False) else 5
for page_start in range(0, len(results), step):
chunk = results[page_start:page_start + step]
lines = []
for index, app in enumerate(chunk, start=page_start + 1):
if not app:
continue
app_id = app.get('appId', '')
title = app.get('title', 'Unknown')
score = app.get('score', 0)
score = round(score, 2) if score else "N/A"
genre = app.get('genre', 'N/A')
installs = app.get('installs', 'N/A')
lines.append(self.strings['app_line'].format(index, app_id, title, score, genre, installs))
runs_text = "
" + "\n".join(lines) + "" pages.append(self.strings['game'].format(args, len(results), runs_text)) await self.inline.form( message=message, text=pages[0], reply_markup=self._game_nav(pages, 0) ) @loader.command() async def subscribe(self, message: Message): "Subscribe to updates of the game." args = utils.get_args_raw(message) if not args: await message.edit(self.strings['sub_usage']) return app_id = args.strip() try: data = gp_app(app_id, lang="en", country="us") except Exception as e: logger.error(f"Error: {e}") await message.edit(self.strings['not_found']) return subs = self._get_subs() user_id = message.sender_id if app_id in subs: if user_id in subs[app_id].get('users', []): await message.edit(self.strings['sub_exists'].format(data.get('title', app_id))) return subs[app_id].setdefault('users', []).append(user_id) else: subs[app_id] = { 'title': data.get('title', app_id), 'version': data.get('version', ''), 'updated': data.get('updated', 0), 'users': [user_id], } self._save_subs(subs) await message.edit(self.strings['sub_added'].format(data.get('title', app_id), app_id)) @loader.command() async def unsubscribe(self, message: Message): "Subcribe, but the other way." args = utils.get_args_raw(message) if not args: await message.edit(self.strings['unsub_usage']) return app_id = args.strip() subs = self._get_subs() user_id = message.sender_id if app_id not in subs or user_id not in subs[app_id].get('users', []): await message.edit(self.strings['sub_missing'].format(app_id)) return subs[app_id]['users'].remove(user_id) title = subs[app_id].get('title', app_id) if not subs[app_id]['users']: del subs[app_id] self._save_subs(subs) await message.edit(self.strings['sub_removed'].format(title)) @loader.command() async def mysubs(self, message: Message): "Your list..." subs = self._get_subs() user_id = message.sender_id user_subs = {aid: info for aid, info in subs.items() if user_id in info.get('users', [])} if not user_subs: await message.edit(self.strings['sub_list_empty']) return items = [] for aid, info in user_subs.items(): items.append(self.strings['sub_item'].format(info.get('title', aid), aid)) await message.edit(self.strings['sub_list'].format("\n".join(items)))