diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index bb69797b..ca50ac4b 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -51,6 +51,7 @@ from .lazyyoutube import LazyyoutubeCommand from .funkwhalealbum import FunkwhalealbumCommand from .lazyfunkwhalealbum import LazyfunkwhalealbumCommand from .matchmaking import MatchmakingCommand +from .cvstats import CvstatsCommand # Enter the commands of your Pack here! available_commands = [ @@ -106,6 +107,7 @@ available_commands = [ FunkwhalealbumCommand, LazyfunkwhalealbumCommand, MatchmakingCommand, + CvstatsCommand ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/cvstats.py b/royalpack/commands/cvstats.py new file mode 100644 index 00000000..b590b7b9 --- /dev/null +++ b/royalpack/commands/cvstats.py @@ -0,0 +1,129 @@ +from typing import * +import logging +import asyncio +import datetime +import royalnet.commands as rc +from royalnet.utils import asyncify +from ..tables import Cvstats + + +log = logging.getLogger(__name__) + + +class CvstatsCommand(rc.Command): + name: str = "cvstats" + + description: str = "" + + syntax: str = "" + + def __init__(self, interface: rc.CommandInterface): + super().__init__(interface) + if self.interface.name == "discord": + self.loop.create_task(self._updater(1800)) + + def _is_ryg_member(self, member: dict): + for role in member["roles"]: + if role["id"] == self.interface.config["Cv"]["displayed_role_id"]: + return True + return False + + async def _update(self, db_session): + log.info(f"Gathering Cvstats...") + while True: + try: + response: Dict[str, Any] = await self.interface.call_herald_event("discord", "discord_cv") + except rc.ConfigurationError: + await asyncio.sleep(10) + continue + else: + break + + users_total = 0 + members_total = 0 + users_online = 0 + members_online = 0 + users_connected = 0 + members_connected = 0 + users_playing = 0 + members_playing = 0 + + # noinspection PyUnboundLocalVariable + for m in response["guild"]["members"]: + users_total += 1 + if self._is_ryg_member(m): + members_total += 1 + + if m["status"]["main"] != "offline" and m["status"]["main"] != "idle": + users_online += 1 + if self._is_ryg_member(m): + members_online += 1 + + if m["voice"] is not None and not m["voice"]["afk"]: + users_connected += 1 + if self._is_ryg_member(m): + members_connected += 1 + + for mact in m["activities"]: + if mact.get("type") == 0: + users_playing += 1 + if self._is_ryg_member(m): + members_playing += 1 + + log.debug(f"Total users: {users_total}") + log.debug(f"Total members: {members_total}") + log.debug(f"Online users: {users_online}") + log.debug(f"Online members: {members_online}") + log.debug(f"Connected users: {users_connected}") + log.debug(f"Connected members: {members_connected}") + log.debug(f"Playing users: {users_playing}") + log.debug(f"Playing members: {members_playing}") + + CvstatsT = self.alchemy.get(Cvstats) + + cvstats = CvstatsT( + timestamp=datetime.datetime.now(), + users_total=users_total, + members_total=members_total, + users_online=users_online, + members_online=members_online, + users_connected=users_connected, + members_connected=members_connected, + users_playing=users_playing, + members_playing=members_playing + ) + + log.debug("Saving to database...") + db_session.add(cvstats) + await asyncify(db_session.commit) + log.debug("Done!") + + async def _updater(self, period: int): + log.info(f"Started updater with {period}s period") + while True: + log.info(f"Updating...") + session = self.alchemy.Session() + await self._update(session) + session.close() + log.info(f"Sleeping for {period}s") + await asyncio.sleep(period) + + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + CvstatsT = self.alchemy.get(Cvstats) + + cvstats = data.session.query(CvstatsT).order_by(CvstatsT.timestamp.desc()).first() + + message = [ + f"ℹ️ [b]Statistiche[/b]", + f"Ultimo aggiornamento: [b]{cvstats.timestamp.strftime('%Y-%m-%d %H:%M')}[/b]", + f"Utenti totali: [b]{cvstats.users_total}[/b]", + f"Membri totali: [b]{cvstats.members_total}[/b]", + f"Utenti online: [b]{cvstats.users_online}[/b]", + f"Membri online: [b]{cvstats.members_online}[/b]", + f"Utenti connessi: [b]{cvstats.users_connected}[/b]", + f"Membri connessi: [b]{cvstats.members_connected}[/b]", + f"Utenti in gioco: [b]{cvstats.users_playing}[/b]", + f"Membri in gioco: [b]{cvstats.members_playing}[/b]" + ] + + await data.reply("\n".join(message)) diff --git a/royalpack/tables/__init__.py b/royalpack/tables/__init__.py index 1359d360..6e8a6937 100644 --- a/royalpack/tables/__init__.py +++ b/royalpack/tables/__init__.py @@ -16,6 +16,7 @@ from .pollvotes import PollVote from .brawlhalladuos import BrawlhallaDuo from .mmevents import MMEvent from .mmresponse import MMResponse +from .cvstats import Cvstats # Enter the tables of your Pack here! available_tables = [ @@ -36,6 +37,7 @@ available_tables = [ BrawlhallaDuo, MMEvent, MMResponse, + Cvstats, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/tables/cvstats.py b/royalpack/tables/cvstats.py new file mode 100644 index 00000000..f669347b --- /dev/null +++ b/royalpack/tables/cvstats.py @@ -0,0 +1,47 @@ +from sqlalchemy import * +from sqlalchemy.orm import * +from sqlalchemy.ext.declarative import declared_attr + + +class Cvstats: + __tablename__ = "cvstats" + + @declared_attr + def id(self): + return Column(Integer, primary_key=True) + + @declared_attr + def timestamp(self): + return Column(DateTime) + + @declared_attr + def members_connected(self): + return Column(Integer) + + @declared_attr + def users_connected(self): + return Column(Integer) + + @declared_attr + def members_online(self): + return Column(Integer) + + @declared_attr + def users_online(self): + return Column(Integer) + + @declared_attr + def members_playing(self): + return Column(Integer) + + @declared_attr + def users_playing(self): + return Column(Integer) + + @declared_attr + def members_total(self): + return Column(Integer) + + @declared_attr + def users_total(self): + return Column(Integer)