mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 19:44:20 +00:00
Add brawlhalla command
This commit is contained in:
parent
e1cd6bffd6
commit
f9ec812790
20 changed files with 285 additions and 27 deletions
|
@ -35,6 +35,7 @@ from .steampowered import SteampoweredCommand
|
|||
from .steammatch import SteammatchCommand
|
||||
from .dota import DotaCommand
|
||||
from .magickfiorygi import MagickfiorygiCommand
|
||||
from .brawlhalla import BrawlhallaCommand
|
||||
|
||||
# Enter the commands of your Pack here!
|
||||
available_commands = [
|
||||
|
@ -74,6 +75,7 @@ available_commands = [
|
|||
SteammatchCommand,
|
||||
DotaCommand,
|
||||
MagickfiorygiCommand,
|
||||
BrawlhallaCommand,
|
||||
]
|
||||
|
||||
# Don't change this, it should automatically generate __all__
|
||||
|
|
143
royalpack/commands/brawlhalla.py
Normal file
143
royalpack/commands/brawlhalla.py
Normal file
|
@ -0,0 +1,143 @@
|
|||
import asyncio
|
||||
import logging
|
||||
import sentry_sdk
|
||||
import aiohttp
|
||||
from typing import *
|
||||
from royalnet.commands import *
|
||||
from royalnet.utils import *
|
||||
from royalnet.serf.telegram.escape import escape as tg_escape
|
||||
from ..tables import Steam, Brawlhalla
|
||||
from ..types import BrawlhallaRank, BrawlhallaMetal, BrawlhallaTier
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BrawlhallaCommand(Command):
|
||||
name: str = "brawlhalla"
|
||||
|
||||
aliases = ["bh", "bruhalla", "bruhlalla"]
|
||||
|
||||
description: str = "Visualizza le tue statistiche di Dota!"
|
||||
|
||||
syntax: str = ""
|
||||
|
||||
def __init__(self, interface: CommandInterface):
|
||||
super().__init__(interface)
|
||||
if self.interface.name == "telegram":
|
||||
self.loop.create_task(self._updater(900))
|
||||
|
||||
async def _send(self, message):
|
||||
client = self.serf.client
|
||||
await self.serf.api_call(client.send_message,
|
||||
chat_id=self.config["Telegram"]["main_group_id"],
|
||||
text=tg_escape(message),
|
||||
parse_mode="HTML",
|
||||
disable_webpage_preview=True)
|
||||
|
||||
@staticmethod
|
||||
def _display(bh: Brawlhalla) -> str:
|
||||
string = f"ℹ️ [b]{bh.name}[/b]\n\n"
|
||||
|
||||
if bh.rank_1v1:
|
||||
string += f"1v1: [b]{bh.rank_1v1}[/b]\n"
|
||||
|
||||
return string
|
||||
|
||||
async def _notify(self,
|
||||
obj: Brawlhalla,
|
||||
attribute_name: str,
|
||||
old_value: Any,
|
||||
new_value: Any):
|
||||
if attribute_name == "rank_1v1":
|
||||
old_rank: Optional[BrawlhallaRank] = old_value
|
||||
new_rank: Optional[BrawlhallaRank] = new_value
|
||||
if new_rank > old_rank:
|
||||
message = f"📈 [b]{obj.steam.user}[/b] è salito a [b]{new_value}[/b] ({obj.rating_1v1} MMR) in 1v1 su Brawlhalla! Congratulazioni!"
|
||||
elif new_rank < old_rank:
|
||||
message = f"📉 [b]{obj.steam.user}[/b] è sceso a [b]{new_value}[/b] ({obj.rating_1v1} MMR) in 1v1 su Brawlhalla."
|
||||
else:
|
||||
return
|
||||
await self._send(message)
|
||||
|
||||
@staticmethod
|
||||
async def _change(obj: Brawlhalla,
|
||||
attribute_name: str,
|
||||
new_value: Any,
|
||||
callback: Callable[[Brawlhalla, str, Any, Any], Awaitable[None]]):
|
||||
old_value = obj.__getattribute__(attribute_name)
|
||||
if old_value != new_value:
|
||||
await callback(obj, attribute_name, old_value, new_value)
|
||||
obj.__setattr__(attribute_name, new_value)
|
||||
|
||||
async def _update(self, steam: Steam, db_session):
|
||||
BrawlhallaT = self.alchemy.get(Brawlhalla)
|
||||
log.info(f"Updating: {steam}")
|
||||
async with aiohttp.ClientSession() as session:
|
||||
bh: Brawlhalla = steam.brawlhalla
|
||||
if bh is None:
|
||||
log.debug(f"Checking if player has an account...")
|
||||
async with session.get(f"https://api.brawlhalla.com/search?steamid={steam.steamid.as_64}&api_key={self.config['Brawlhalla']['api_key']}") as response:
|
||||
if response.status != 200:
|
||||
raise ExternalError(f"Brawlhalla API /search returned {response.status}!")
|
||||
j = await response.json()
|
||||
if j == {} or j == []:
|
||||
log.debug("No account found.")
|
||||
return
|
||||
bh = BrawlhallaT(
|
||||
steam=steam,
|
||||
brawlhalla_id=j["brawlhalla_id"],
|
||||
name=j["name"]
|
||||
)
|
||||
db_session.add(bh)
|
||||
message = f"↔️ Account {bh} connesso a {bh.steam.user}!"
|
||||
await self._send(message)
|
||||
async with session.get(f"https://api.brawlhalla.com/player/{bh.brawlhalla_id}/ranked?api_key={self.config['Brawlhalla']['api_key']}") as response:
|
||||
if response.status != 200:
|
||||
raise ExternalError(f"Brawlhalla API /ranked returned {response.status}!")
|
||||
j = await response.json()
|
||||
if j == {} or j == []:
|
||||
log.debug("No ranked info found.")
|
||||
else:
|
||||
await self._change(bh, "rating_1v1", j["rating"], self._notify)
|
||||
metal_name, tier_name = j["tier"].split(" ", 1)
|
||||
metal = BrawlhallaMetal[metal_name.upper()]
|
||||
tier = BrawlhallaTier(int(tier_name))
|
||||
rank = BrawlhallaRank(metal=metal, tier=tier)
|
||||
await self._change(bh, "rank_1v1", rank, self._notify)
|
||||
await asyncify(db_session.commit)
|
||||
|
||||
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()
|
||||
log.info("")
|
||||
steams = session.query(self.alchemy.get(Steam)).all()
|
||||
for steam in steams:
|
||||
try:
|
||||
await self._update(steam, session)
|
||||
except Exception as e:
|
||||
sentry_sdk.capture_exception(e)
|
||||
log.error(f"Error while updating {steam.user.username}: {e}")
|
||||
await asyncio.sleep(1)
|
||||
await asyncify(session.commit)
|
||||
session.close()
|
||||
log.info(f"Sleeping for {period}s")
|
||||
await asyncio.sleep(period)
|
||||
|
||||
async def run(self, args: CommandArgs, data: CommandData) -> None:
|
||||
author = await data.get_author(error_if_none=True)
|
||||
|
||||
found_something = False
|
||||
|
||||
message = ""
|
||||
for steam in author.steam:
|
||||
await self._update(steam, data.session)
|
||||
if steam.brawlhalla is None:
|
||||
continue
|
||||
found_something = True
|
||||
message += self._display(steam.brawlhalla)
|
||||
message += "\n"
|
||||
if not found_something:
|
||||
raise UserError("Nessun account di Brawlhalla trovato.")
|
||||
await data.reply(message)
|
|
@ -7,7 +7,7 @@ from royalnet.commands import *
|
|||
from royalnet.utils import *
|
||||
from royalnet.serf.telegram.escape import escape as tg_escape
|
||||
from ..tables import Steam, Dota
|
||||
from ..utils import DotaRank
|
||||
from ..types import DotaRank
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -15,7 +15,7 @@ log = logging.getLogger(__name__)
|
|||
class DotaCommand(Command):
|
||||
name: str = "dota"
|
||||
|
||||
aliases = ["dota2", "doto", "doto2"]
|
||||
aliases = ["dota2", "doto", "doto2", "dotka", "dotka2"]
|
||||
|
||||
description: str = "Visualizza le tue statistiche di Dota!"
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ from royalnet.commands import *
|
|||
from royalnet.utils import *
|
||||
from royalnet.serf.telegram import *
|
||||
from ..tables import LeagueOfLegends
|
||||
from ..utils import LeagueLeague
|
||||
from ..types import LeagueLeague
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -2,8 +2,10 @@ from sqlalchemy import *
|
|||
from sqlalchemy.orm import *
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
import steam
|
||||
from ..types import BrawlhallaRank, BrawlhallaTier, BrawlhallaMetal
|
||||
|
||||
|
||||
# noinspection PyAttributeOutsideInit
|
||||
class Brawlhalla:
|
||||
__tablename__ = "brawlhalla"
|
||||
|
||||
|
@ -25,12 +27,33 @@ class Brawlhalla:
|
|||
|
||||
@declared_attr
|
||||
def name(self):
|
||||
return Column(String)
|
||||
return Column(String, nullable=False)
|
||||
|
||||
@declared_attr
|
||||
def rating_1v1(self):
|
||||
return Column(Integer)
|
||||
|
||||
@property
|
||||
@declared_attr
|
||||
def tier_1v1(self):
|
||||
return Column(String)
|
||||
return Column(Enum(BrawlhallaTier))
|
||||
|
||||
@declared_attr
|
||||
def metal_1v1(self):
|
||||
return Column(Enum(BrawlhallaMetal))
|
||||
|
||||
@property
|
||||
def rank_1v1(self):
|
||||
return BrawlhallaRank(metal=self.metal_1v1, tier=self.tier_1v1)
|
||||
|
||||
@rank_1v1.setter
|
||||
def rank_1v1(self, value):
|
||||
if not isinstance(value, BrawlhallaRank):
|
||||
raise TypeError("rank_1v1 can only be set to BrawlhallaRank values.")
|
||||
self.metal_1v1 = value.metal
|
||||
self.tier_1v1 = value.tier
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Brawlhalla account {self._steamid}>"
|
||||
|
||||
def __str__(self):
|
||||
return f"[c]brawlhalla:{self.brawlhalla_id}[/c]"
|
|
@ -2,9 +2,7 @@ from typing import *
|
|||
from sqlalchemy import *
|
||||
from sqlalchemy.orm import relationship, backref
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
from ..utils.dotamedal import DotaMedal
|
||||
from ..utils.dotastars import DotaStars
|
||||
from ..utils.dotarank import DotaRank
|
||||
from ..types import DotaMedal, DotaStars, DotaRank
|
||||
import steam
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from sqlalchemy import *
|
||||
from sqlalchemy.orm import relationship, composite
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
from ..utils import LeagueRank, LeagueTier, LeagueLeague
|
||||
from ..types import LeagueRank, LeagueTier, LeagueLeague
|
||||
|
||||
|
||||
class LeagueOfLegends:
|
||||
|
|
27
royalpack/types/__init__.py
Normal file
27
royalpack/types/__init__.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
from .mmchoice import MMChoice
|
||||
from .mminterfacedata import MMInterfaceData, MMInterfaceDataTelegram
|
||||
from .leaguetier import LeagueTier
|
||||
from .leaguerank import LeagueRank
|
||||
from .leagueleague import LeagueLeague
|
||||
from .dotamedal import DotaMedal
|
||||
from .dotastars import DotaStars
|
||||
from .dotarank import DotaRank
|
||||
from .brawlhallatier import BrawlhallaTier
|
||||
from .brawlhallametal import BrawlhallaMetal
|
||||
from .brawlhallarank import BrawlhallaRank
|
||||
|
||||
|
||||
__all__ = [
|
||||
"MMChoice",
|
||||
"MMInterfaceData",
|
||||
"MMInterfaceDataTelegram",
|
||||
"LeagueTier",
|
||||
"LeagueRank",
|
||||
"LeagueLeague",
|
||||
"DotaMedal",
|
||||
"DotaStars",
|
||||
"DotaRank",
|
||||
"BrawlhallaMetal",
|
||||
"BrawlhallaRank",
|
||||
"BrawlhallaTier",
|
||||
]
|
23
royalpack/types/brawlhallametal.py
Normal file
23
royalpack/types/brawlhallametal.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
import enum
|
||||
|
||||
|
||||
class BrawlhallaMetal(enum.Enum):
|
||||
TIN = 0
|
||||
BRONZE = 1
|
||||
SILVER = 2
|
||||
GOLD = 3
|
||||
PLATINUM = 4
|
||||
DIAMOND = 5
|
||||
|
||||
def __str__(self):
|
||||
return self.name.capitalize()
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.__class__.__qualname__}.{self.name}"
|
||||
|
||||
def __gt__(self, other):
|
||||
if other is None:
|
||||
return True
|
||||
if not isinstance(other, self.__class__):
|
||||
raise TypeError(f"Can't compare {self.__class__.__qualname__} with {other.__class__.__qualname__}")
|
||||
return self.value > other.value
|
36
royalpack/types/brawlhallarank.py
Normal file
36
royalpack/types/brawlhallarank.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
from .brawlhallametal import BrawlhallaMetal
|
||||
from .brawlhallatier import BrawlhallaTier
|
||||
|
||||
|
||||
class BrawlhallaRank:
|
||||
__slots__ = "metal", "tier"
|
||||
|
||||
def __init__(self, metal: BrawlhallaMetal, tier: BrawlhallaTier):
|
||||
self.metal: BrawlhallaMetal = metal
|
||||
self.tier: BrawlhallaTier = tier
|
||||
|
||||
def __gt__(self, other):
|
||||
if other is None:
|
||||
return True
|
||||
if not isinstance(other, self.__class__):
|
||||
raise TypeError(f"Can't compare {self.__class__.__qualname__} with {other.__class__.__qualname__}")
|
||||
if self.metal > other.metal:
|
||||
return True
|
||||
elif self.metal < other.metal:
|
||||
return False
|
||||
elif self.tier > other.tier:
|
||||
return True
|
||||
return False
|
||||
|
||||
def __eq__(self, other):
|
||||
if other is None:
|
||||
return False
|
||||
if not isinstance(other, self.__class__):
|
||||
raise TypeError(f"Can't compare {self.__class__.__qualname__} with {other.__class__.__qualname__}")
|
||||
return self.metal == other.metal and self.tier == other.tier
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__qualname__}: {self.metal} {self.tier}>"
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.metal} {self.tier}"
|
23
royalpack/types/brawlhallatier.py
Normal file
23
royalpack/types/brawlhallatier.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
import enum
|
||||
|
||||
|
||||
class BrawlhallaTier(enum.Enum):
|
||||
ZERO = 0
|
||||
I = 1
|
||||
II = 2
|
||||
III = 3
|
||||
IV = 4
|
||||
V = 5
|
||||
|
||||
def __str__(self):
|
||||
return str(self.value)
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.__class__.__qualname__}.{self.name}"
|
||||
|
||||
def __gt__(self, other):
|
||||
if other is None:
|
||||
return True
|
||||
if not isinstance(other, self.__class__):
|
||||
raise TypeError(f"Can't compare {self.__class__.__qualname__} with {other.__class__.__qualname__}")
|
||||
return self.value > other.value
|
|
@ -1,24 +1,7 @@
|
|||
from .mmchoice import MMChoice
|
||||
from .mminterfacedata import MMInterfaceData, MMInterfaceDataTelegram
|
||||
from .leaguetier import LeagueTier
|
||||
from .leaguerank import LeagueRank
|
||||
from .leagueleague import LeagueLeague
|
||||
from .royalqueue import RoyalQueue
|
||||
from .dotamedal import DotaMedal
|
||||
from .dotastars import DotaStars
|
||||
from .dotarank import DotaRank
|
||||
from .finduser import find_user_api
|
||||
|
||||
__all__ = [
|
||||
"MMChoice",
|
||||
"MMInterfaceData",
|
||||
"MMInterfaceDataTelegram",
|
||||
"LeagueTier",
|
||||
"LeagueRank",
|
||||
"LeagueLeague",
|
||||
"RoyalQueue",
|
||||
"DotaMedal",
|
||||
"DotaStars",
|
||||
"DotaRank",
|
||||
"find_user_api",
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue