1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-27 13:34:28 +00:00

Add brawlhalla command

This commit is contained in:
Steffo 2020-03-19 16:26:11 +01:00
parent e1cd6bffd6
commit f9ec812790
20 changed files with 285 additions and 27 deletions

View file

@ -35,6 +35,7 @@ from .steampowered import SteampoweredCommand
from .steammatch import SteammatchCommand from .steammatch import SteammatchCommand
from .dota import DotaCommand from .dota import DotaCommand
from .magickfiorygi import MagickfiorygiCommand from .magickfiorygi import MagickfiorygiCommand
from .brawlhalla import BrawlhallaCommand
# Enter the commands of your Pack here! # Enter the commands of your Pack here!
available_commands = [ available_commands = [
@ -74,6 +75,7 @@ available_commands = [
SteammatchCommand, SteammatchCommand,
DotaCommand, DotaCommand,
MagickfiorygiCommand, MagickfiorygiCommand,
BrawlhallaCommand,
] ]
# Don't change this, it should automatically generate __all__ # Don't change this, it should automatically generate __all__

View 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)

View file

@ -7,7 +7,7 @@ from royalnet.commands import *
from royalnet.utils import * from royalnet.utils import *
from royalnet.serf.telegram.escape import escape as tg_escape from royalnet.serf.telegram.escape import escape as tg_escape
from ..tables import Steam, Dota from ..tables import Steam, Dota
from ..utils import DotaRank from ..types import DotaRank
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -15,7 +15,7 @@ log = logging.getLogger(__name__)
class DotaCommand(Command): class DotaCommand(Command):
name: str = "dota" name: str = "dota"
aliases = ["dota2", "doto", "doto2"] aliases = ["dota2", "doto", "doto2", "dotka", "dotka2"]
description: str = "Visualizza le tue statistiche di Dota!" description: str = "Visualizza le tue statistiche di Dota!"

View file

@ -7,7 +7,7 @@ from royalnet.commands import *
from royalnet.utils import * from royalnet.utils import *
from royalnet.serf.telegram import * from royalnet.serf.telegram import *
from ..tables import LeagueOfLegends from ..tables import LeagueOfLegends
from ..utils import LeagueLeague from ..types import LeagueLeague
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View file

@ -2,8 +2,10 @@ from sqlalchemy import *
from sqlalchemy.orm import * from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.ext.declarative import declared_attr
import steam import steam
from ..types import BrawlhallaRank, BrawlhallaTier, BrawlhallaMetal
# noinspection PyAttributeOutsideInit
class Brawlhalla: class Brawlhalla:
__tablename__ = "brawlhalla" __tablename__ = "brawlhalla"
@ -25,12 +27,33 @@ class Brawlhalla:
@declared_attr @declared_attr
def name(self): def name(self):
return Column(String) return Column(String, nullable=False)
@declared_attr @declared_attr
def rating_1v1(self): def rating_1v1(self):
return Column(Integer) return Column(Integer)
@property @declared_attr
def tier_1v1(self): 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]"

View file

@ -2,9 +2,7 @@ from typing import *
from sqlalchemy import * from sqlalchemy import *
from sqlalchemy.orm import relationship, backref from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.ext.declarative import declared_attr
from ..utils.dotamedal import DotaMedal from ..types import DotaMedal, DotaStars, DotaRank
from ..utils.dotastars import DotaStars
from ..utils.dotarank import DotaRank
import steam import steam

View file

@ -1,7 +1,7 @@
from sqlalchemy import * from sqlalchemy import *
from sqlalchemy.orm import relationship, composite from sqlalchemy.orm import relationship, composite
from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.ext.declarative import declared_attr
from ..utils import LeagueRank, LeagueTier, LeagueLeague from ..types import LeagueRank, LeagueTier, LeagueLeague
class LeagueOfLegends: class LeagueOfLegends:

View 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",
]

View 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

View 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}"

View 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

View file

@ -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 .royalqueue import RoyalQueue
from .dotamedal import DotaMedal
from .dotastars import DotaStars
from .dotarank import DotaRank
from .finduser import find_user_api from .finduser import find_user_api
__all__ = [ __all__ = [
"MMChoice",
"MMInterfaceData",
"MMInterfaceDataTelegram",
"LeagueTier",
"LeagueRank",
"LeagueLeague",
"RoyalQueue", "RoyalQueue",
"DotaMedal",
"DotaStars",
"DotaRank",
"find_user_api", "find_user_api",
] ]