コード例 #1
0
 async def call_herald_event(ci, destination: str, event_name: str, **kwargs) -> Dict:
     """Send a :class:`rh.Request` to a specific destination, and wait for a
     :class:`rh.Response`."""
     if self.herald is None:
         raise rc.UnsupportedError("`royalherald` is not enabled on this Constellation.")
     request: rh.Request = rh.Request(handler=event_name, data=kwargs)
     response: rh.Response = await self.herald.request(destination=destination, request=request)
     if isinstance(response, rh.ResponseFailure):
         if response.name == "no_event":
             raise rc.CommandError(f"There is no event named {event_name} in {destination}.")
         elif response.name == "exception_in_event":
             # TODO: pretty sure there's a better way to do this
             if response.extra_info["type"] == "CommandError":
                 raise rc.CommandError(response.extra_info["message"])
             elif response.extra_info["type"] == "UserError":
                 raise rc.UserError(response.extra_info["message"])
             elif response.extra_info["type"] == "InvalidInputError":
                 raise rc.InvalidInputError(response.extra_info["message"])
             elif response.extra_info["type"] == "UnsupportedError":
                 raise rc.UnsupportedError(response.extra_info["message"])
             elif response.extra_info["type"] == "ConfigurationError":
                 raise rc.ConfigurationError(response.extra_info["message"])
             elif response.extra_info["type"] == "ExternalError":
                 raise rc.ExternalError(response.extra_info["message"])
             else:
                 raise TypeError(f"Herald action call returned invalid error:\n"
                                 f"[p]{response}[/p]")
     elif isinstance(response, rh.ResponseSuccess):
         return response.data
     else:
         raise TypeError(f"Other Herald Link returned unknown response:\n"
                         f"[p]{response}[/p]")
コード例 #2
0
ファイル: diarioquote.py プロジェクト: RYGhub/royalpack-5
 async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
     try:
         entry_id = int(args[0].lstrip("#"))
     except ValueError:
         raise rc.CommandError("L'id che hai specificato non è valido.")
     async with data.session_acm() as session:
         entry: Diario = await ru.asyncify(
             session.query(self.alchemy.get(Diario)).get, entry_id)
         if entry is None:
             raise rc.CommandError("Nessuna riga con quell'id trovata.")
         await data.reply(f"ℹ️ {entry}")
コード例 #3
0
ファイル: eval.py プロジェクト: RYGhub/royalpack-5
 async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
     async with data.session_acm() as session:
         user: rbt.User = await data.find_author(session=session,
                                                 required=True)
         if "admin" not in user.roles:
             raise rc.CommandError(
                 "Non sei autorizzato a eseguire codice arbitrario!\n"
                 "(Sarebbe un po' pericoloso se te lo lasciassi eseguire, non trovi?)"
             )
     try:
         result = eval(args.joined(require_at_least=1))
     except Exception as e:
         raise rc.CommandError(f"Eval fallito: {e}")
     await data.reply(repr(result))
コード例 #4
0
ファイル: dndjoinbattle.py プロジェクト: Steffo99/rpgpack
    async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
        faction = Faction[args[0].upper()]
        initiative_mod = int(args.optional(1, default="0"))

        async with data.session_acm() as session:
            DndBattleUnitT = self.alchemy.get(DndBattleUnit)

            active_battle = await get_active_battle(data=data, session=session)
            if active_battle is None:
                raise rc.CommandError("No battle is active in this chat.")

            active_character = await get_active_character(data=data, session=session)
            if active_character is None:
                raise rc.CommandError("You don't have an active character.")

            char: DndCharacter = active_character.character

            units_with_same_name = await ru.asyncify(session.query(DndBattleUnitT).filter_by(
                name=char.name,
                battle=active_battle.battle
            ).all)

            if len(units_with_same_name) != 0:
                raise rc.InvalidInputError("A unit with the same name already exists.")

            roll = random.randrange(1, 21)
            modifier = char.initiative + initiative_mod
            modifier_str = f"{modifier:+d}" if modifier != 0 else ""
            initiative = roll + modifier

            dbu = DndBattleUnitT(
                linked_character=char,
                initiative=initiative,
                faction=faction,
                name=char.name,
                health_string=f"{char.current_hp}/{char.max_hp}",
                armor_class=char.armor_class,
                battle=active_battle.battle
            )

            session.add(dbu)
            await ru.asyncify(session.commit)

            await data.reply(f"{dbu}\n"
                             f"joins the battle!\n"
                             f"\n"
                             f"🎲 1d20{modifier_str} = {roll}{modifier_str} = {initiative}")
コード例 #5
0
ファイル: diarioshuffle.py プロジェクト: RYGhub/royalpack-5
 async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
     async with data.session_acm() as session:
         DiarioT = self.alchemy.get(Diario)
         entry: List[Diario] = await ru.asyncify(
             session.query(DiarioT).order_by(
                 func.random()).limit(1).one_or_none)
         if entry is None:
             raise rc.CommandError("Nessuna riga del diario trovata.")
         await data.reply(f"ℹ️ {entry}")
コード例 #6
0
 async def get_author(data, error_if_none=False):
     user: str = data.event.sender
     query = data.session.query(self.master_table)
     for link in self.identity_chain:
         query = query.join(link.mapper.class_)
     query = query.filter(self.identity_column == user)
     result = await ru.asyncify(query.one_or_none)
     if result is None and error_if_none:
         raise rc.CommandError(
             "You must be registered to use this command.")
     return result
コード例 #7
0
 async def find_author(data,
                       *,
                       session,
                       required: bool = False) -> Optional[rbt.User]:
     user: "******" = data.cbq.from_user
     TelegramT = data.alchemy.get(rbt.Telegram)
     result = await ru.asyncify(
         session.query(TelegramT).filter(TelegramT.tg_id == user.id).one_or_none
     )
     if result is None and required:
         raise rc.CommandError("You must be registered to use this command.")
     return result.user
コード例 #8
0
ファイル: discordserf.py プロジェクト: fakegit/royalnet
 async def find_author(data,
                       *,
                       session,
                       required: bool = False) -> Optional[rbt.User]:
     user: Union["discord.User", "discord.Member"] = data.message.author
     DiscordT = data.alchemy.get(rbt.Discord)
     result = await asyncify(
         session.query(DiscordT).filter(DiscordT.discord_id == user.id).one_or_none
     )
     if result is None and required:
         raise rc.CommandError("You must be registered to use this command.")
     return result
コード例 #9
0
ファイル: constellation.py プロジェクト: fakegit/royalnet
 async def call_herald_event(self, destination: str, event_name: str,
                             **kwargs) -> Dict:
     """Send a :class:`royalherald.Request` to a specific destination, and wait for a
     :class:`royalherald.Response`."""
     if self.herald is None:
         raise rc.UnsupportedError(
             "`royalherald` is not enabled on this serf.")
     request: rh.Request = rh.Request(handler=event_name, data=kwargs)
     response: rh.Response = await self.herald.request(
         destination=destination, request=request)
     if isinstance(response, rh.ResponseFailure):
         if response.name == "no_event":
             raise rc.ProgramError(
                 f"There is no event named {event_name} in {destination}.")
         elif response.name == "error_in_event":
             if response.extra_info["type"] == "CommandError":
                 raise rc.CommandError(response.extra_info["message"])
             elif response.extra_info["type"] == "UserError":
                 raise rc.UserError(response.extra_info["message"])
             elif response.extra_info["type"] == "InvalidInputError":
                 raise rc.InvalidInputError(response.extra_info["message"])
             elif response.extra_info["type"] == "UnsupportedError":
                 raise rc.UnsupportedError(response.extra_info["message"])
             elif response.extra_info["type"] == "ConfigurationError":
                 raise rc.ConfigurationError(response.extra_info["message"])
             elif response.extra_info["type"] == "ExternalError":
                 raise rc.ExternalError(response.extra_info["message"])
             else:
                 raise rc.ProgramError(
                     f"Invalid error in Herald event '{event_name}':\n"
                     f"[b]{response.extra_info['type']}[/b]\n"
                     f"{response.extra_info['message']}")
         elif response.name == "unhandled_exception_in_event":
             raise rc.ProgramError(
                 f"Unhandled exception in Herald event '{event_name}':\n"
                 f"[b]{response.extra_info['type']}[/b]\n"
                 f"{response.extra_info['message']}")
         else:
             raise rc.ProgramError(
                 f"Unknown response in Herald event '{event_name}':\n"
                 f"[b]{response.name}[/b]"
                 f"[p]{response}[/p]")
     elif isinstance(response, rh.ResponseSuccess):
         return response.data
     else:
         raise rc.ProgramError(
             f"Other Herald Link returned unknown response:\n"
             f"[p]{response}[/p]")
コード例 #10
0
ファイル: dndaddunit.py プロジェクト: Steffo99/rpgpack
    async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
        faction = Faction[args[0].upper()]
        name = args[1]
        initiative = int(args[2])
        health = args[3]
        armor_class = int(args[4])

        DndBattleUnitT = self.alchemy.get(DndBattleUnit)

        async with data.session_acm() as session:
            active_battle = await get_active_battle(session=session, data=data)
            if active_battle is None:
                raise rc.CommandError("No battle is active in this chat.")

            units_with_same_name = await ru.asyncify(
                session.query(DndBattleUnitT).filter_by(
                    name=name, battle=active_battle.battle).all)

            if len(units_with_same_name) != 0:
                raise rc.InvalidInputError(
                    "A unit with the same name already exists.")

            try:
                health = Health.from_text(health)
            except ValueError:
                raise rc.InvalidInputError("Invalid health string.")

            dbu = DndBattleUnitT(linked_character_id=None,
                                 initiative=initiative,
                                 faction=faction,
                                 name=name,
                                 health_string=health,
                                 armor_class=armor_class,
                                 battle=active_battle.battle)

            session.add(dbu)
            await ru.asyncify(session.commit)

            await data.reply(f"{dbu}\n" f"joins the battle!")

            if dbu.health.hidden:
                await data.delete_invoking()
コード例 #11
0
ファイル: gettargets.py プロジェクト: Steffo99/rpgpack
async def get_targets(target: Optional[str], *, data: rc.CommandData,
                      session) -> List[DndBattleUnit]:
    DndBattleUnitT = data.alchemy.get(DndBattleUnit)

    active_battle = await get_active_battle(data)
    if active_battle is None:
        raise rc.CommandError("No battle is active in this chat.")
    battle = active_battle.battle

    # Get the active character
    if not target or target.upper() == "SELF":
        active_character = await get_active_character(data)
        if active_character is None:
            return []
        char = active_character.character

        return await ru.asyncify(
            session.query(DndBattleUnitT).filter_by(linked_character=char,
                                                    battle=battle).all)

    # Get all
    if target.upper() == "ALL":
        return await ru.asyncify(
            session.query(DndBattleUnitT).filter_by(battle=battle).all)

    # Get by faction
    try:
        faction = Faction.get(target)
    except ValueError:
        pass
    else:
        return await ru.asyncify(
            session.query(DndBattleUnitT).filter_by(faction=faction,
                                                    battle=battle).all)

    # Get by ilike
    return await ru.asyncify(
        session.query(DndBattleUnitT).filter(
            and_(DndBattleUnitT.name.ilike(target),
                 DndBattleUnitT.battle == battle)).all)
コード例 #12
0
async def to_imgur(imgur_api_key,
                   photosizes: List[telegram.PhotoSize],
                   caption="") -> str:
    # Select the largest photo
    largest_photo = sorted(photosizes, key=lambda p: p.width * p.height)[-1]
    # Get the photo url
    photo_file: telegram.File = await ru.asyncify(largest_photo.get_file)
    # Forward the url to imgur, as an upload
    async with aiohttp.request(
        "post",
        "https://api.imgur.com/3/upload",
        data={
            "image": photo_file.file_path,
            "type": "URL",
            "title": "Diario image",
            "description": caption
        },
        headers={"Authorization": f"Client-ID {imgur_api_key}"}) as request:
        response = await request.json()
        if not response["success"]:
            raise rc.CommandError(
                f"Imgur returned an error in the image upload: {response}")
        return response["data"]["link"]
コード例 #13
0
    async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
        arg = args.optional(0)
        async with data.session_acm() as session:
            if arg == "credits":
                await data.reply(f"ℹ️ [c]{self.serf.prefix}{self.name}[/c] di [i]Steffo[/i]\n"
                                 f"\n"
                                 f"Tutte le domande vengono dall'[b]Open Trivia Database[/b] di [i]Pixeltail Games[/i],"
                                 f" creatori di Tower Unite, e sono rilasciate sotto la licenza [b]CC BY-SA 4.0[/b].")
                return
            elif arg == "scores":
                trivia_scores = await ru.asyncify(session.query(self.alchemy.get(TriviaScore)).all)
                strings = ["🏆 [b]Trivia Leaderboards[/b]\n"]
                for index, ts in enumerate(sorted(trivia_scores, key=lambda ts: -ts.score)):
                    if index > 3:
                        index = 3
                    strings.append(f"{self._medal_emojis[index]} {ts.user.username}: [b]{ts.score:.0f}p[/b]"
                                   f" ({ts.correct_answers}/{ts.total_answers})")
                await data.reply("\n".join(strings))
                return
            # if self._question_lock:
            #     raise rc.CommandError("C'è già un'altra domanda attiva!")
            # self._question_lock = True
            # Fetch the question
            async with aiohttp.ClientSession() as ws:
                async with ws.get("https://opentdb.com/api.php?amount=1") as response:
                    j = await response.json()
            # Parse the question
            if j["response_code"] != 0:
                raise rc.CommandError(f"OpenTDB returned an error response_code ({j['response_code']}).")
            question = j["results"][0]
            text = f'❓ [b]{question["category"]}[/b]\n' \
                   f'{html.unescape(question["question"])}'
            # Prepare answers
            correct_answer: str = question["correct_answer"]
            wrong_answers: List[str] = question["incorrect_answers"]
            answers: List[str] = [correct_answer, *wrong_answers]
            if question["type"] == "multiple":
                random.shuffle(answers)
            elif question["type"] == "boolean":
                answers.sort(key=lambda a: a)
                answers.reverse()
            else:
                raise NotImplementedError("Unknown question type")
            # Find the correct index
            for index, answer in enumerate(answers):
                if answer == correct_answer:
                    correct_index = index
                    break
            else:
                raise ValueError("correct_index not found")
            # Add emojis
            for index, answer in enumerate(answers):
                answers[index] = f"{self._letter_emojis[index]} {html.unescape(answers[index])}"
            # Create the question id
            question_id = uuid.uuid4()
            self._answerers[question_id] = {}

            # Create the correct and wrong functions
            async def correct(data: rc.CommandData):
                answerer_ = await data.find_author(session=session, required=True)
                try:
                    self._answerers[question_id][answerer_.uid] = True
                except KeyError:
                    raise rc.UserError("Tempo scaduto!")
                await data.reply("🆗 Hai risposto alla domanda. Ora aspetta un attimo per i risultati!")

            async def wrong(data: rc.CommandData):
                answerer_ = await data.find_author(session=session, required=True)
                try:
                    self._answerers[question_id][answerer_.uid] = False
                except KeyError:
                    raise rc.UserError("Tempo scaduto!")
                await data.reply("🆗 Hai risposto alla domanda. Ora aspetta un attimo per i risultati!")

            # Add question
            keyboard: List[rc.KeyboardKey] = []
            for index, answer in enumerate(answers):
                if index == correct_index:
                    keyboard.append(rc.KeyboardKey(short=self._letter_emojis[index],
                                                   text=answers[index],
                                                   callback=correct))
                else:
                    keyboard.append(rc.KeyboardKey(short=self._letter_emojis[index],
                                                   text=answers[index],
                                                   callback=wrong))
            async with data.keyboard(text=text, keys=keyboard):
                await asyncio.sleep(self._answer_time)
            results = f"❗️ Tempo scaduto!\n" \
                      f"La risposta corretta era [b]{answers[correct_index]}[/b]!\n\n"
            for answerer_id in self._answerers[question_id]:
                answerer = session.query(self.alchemy.get(rbt.users.User)).get(answerer_id)
                if answerer.trivia_score is None:
                    ts = self.alchemy.get(TriviaScore)(user=answerer)
                    session.add(ts)
                    await ru.asyncify(session.commit)
                previous_score = answerer.trivia_score.score
                if self._answerers[question_id][answerer_id]:
                    results += self._correct_emoji
                    answerer.trivia_score.correct_answers += 1
                else:
                    results += self._wrong_emoji
                    answerer.trivia_score.wrong_answers += 1
                current_score = answerer.trivia_score.score
                score_difference = current_score - previous_score
                results += f" {answerer}: [b]{current_score:.0f}p[/b] ({score_difference:+.0f}p)\n"
            await data.reply(results)
            del self._answerers[question_id]
            await ru.asyncify(session.commit)
コード例 #14
0
    async def create(
            self,
            session,
            user: rbt.User,
            args: rc.CommandArgs,
            data: Optional[rc.CommandData] = None
    ) -> Optional[LeagueOfLegends]:
        name = args.joined()

        # Connect a new League of Legends account to Royalnet
        log.debug(f"Searching for: {name}")
        summoner = self._lolwatcher.summoner.by_name(region=self.region(),
                                                     summoner_name=name)
        # Ensure the account isn't already connected to something else
        leagueoflegends = await ru.asyncify(
            session.query(self.alchemy.get(LeagueOfLegends)).filter_by(
                summoner_id=summoner["id"]).one_or_none)
        if leagueoflegends:
            raise rc.CommandError(
                f"L'account {leagueoflegends} è già registrato su Royalnet.")
        # Get rank information
        log.debug(f"Getting leagues data: {name}")
        leagues = self._lolwatcher.league.by_summoner(
            region=self.region(), encrypted_summoner_id=summoner["id"])
        soloq = LeagueLeague()
        flexq = LeagueLeague()
        twtrq = LeagueLeague()
        tftq = LeagueLeague()
        for league in leagues:
            if league["queueType"] == "RANKED_SOLO_5x5":
                soloq = LeagueLeague.from_dict(league)
            if league["queueType"] == "RANKED_FLEX_SR":
                flexq = LeagueLeague.from_dict(league)
            if league["queueType"] == "RANKED_FLEX_TT":
                twtrq = LeagueLeague.from_dict(league)
            if league["queueType"] == "RANKED_TFT":
                tftq = LeagueLeague.from_dict(league)
        # Get mastery score
        log.debug(f"Getting mastery data: {name}")
        mastery = self._lolwatcher.champion_mastery.scores_by_summoner(
            region=self.region(), encrypted_summoner_id=summoner["id"])
        # Create database row
        leagueoflegends = self.alchemy.get(LeagueOfLegends)(
            region=self.region(),
            user=user,
            profile_icon_id=summoner["profileIconId"],
            summoner_name=summoner["name"],
            puuid=summoner["puuid"],
            summoner_level=summoner["summonerLevel"],
            summoner_id=summoner["id"],
            account_id=summoner["accountId"],
            rank_soloq=soloq,
            rank_flexq=flexq,
            rank_twtrq=twtrq,
            rank_tftq=tftq,
            mastery_score=mastery)

        await FiorygiTransaction.spawn_fiorygi(
            data=data,
            session=session,
            user=user,
            qty=1,
            reason=
            "aver collegato a Royalnet il proprio account di League of Legends"
        )

        session.add(leagueoflegends)
        return leagueoflegends