Пример #1
0
    async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
        async with data.session_acm() as session:
            author = await data.find_author(session=session, required=True)
            if "banker" not in author.roles:
                raise rc.UserError(
                    "Non hai permessi sufficienti per eseguire questo comando."
                )

            user_arg = args[0]
            qty_arg = args[1]
            reason_arg = " ".join(args[2:])

            if user_arg is None:
                raise rc.InvalidInputError(
                    "Non hai specificato un destinatario!")
            user = await rbt.User.find(self.alchemy, session, user_arg)
            if user is None:
                raise rc.InvalidInputError("L'utente specificato non esiste!")

            if qty_arg is None:
                raise rc.InvalidInputError("Non hai specificato una quantità!")
            try:
                qty = int(qty_arg)
            except ValueError:
                raise rc.InvalidInputError(
                    "La quantità specificata non è un numero!")

            if reason_arg == "":
                raise rc.InvalidInputError("Non hai specificato un motivo!")

            await FiorygiTransaction.spawn_fiorygi(user,
                                                   qty,
                                                   reason_arg,
                                                   data=data,
                                                   session=session)
Пример #2
0
    async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
        try:
            date_str, reminder_text = args.match(r"\[\s*([^]]+)\s*]\s*([^\n]+)\s*")
        except rc.InvalidInputError:
            date_str, reminder_text = args.match(r"\s*(.+?)\s*\n\s*([^\n]+)\s*")

        try:
            date: Optional[datetime.datetime] = dateparser.parse(date_str, settings={
                "PREFER_DATES_FROM": "future"
            })
        except OverflowError:
            date = None
        if date is None:
            await data.reply("⚠️ La data che hai inserito non è valida.")
            return
        if date <= datetime.datetime.now():
            await data.reply("⚠️ La data che hai specificato è nel passato.")
            return
        await data.reply(f"✅ Promemoria impostato per [b]{date.strftime('%Y-%m-%d %H:%M:%S')}[/b]")
        if isinstance(self.serf, rst.TelegramSerf):
            interface_data = pickle.dumps(data.message.chat.id)
        elif isinstance(self.serf, rsd.DiscordSerf):
            interface_data = pickle.dumps(data.message.channel.id)
        else:
            raise rc.UnsupportedError("This command does not support the current interface.")
        async with data.session_acm() as session:
            creator = await data.find_author(session=session)
            reminder = self.alchemy.get(Reminder)(creator=creator,
                                                  interface_name=self.serf.interface_name,
                                                  interface_data=interface_data,
                                                  datetime=date,
                                                  message=reminder_text)
            self.serf.tasks.add(self._remind(reminder))
            session.add(reminder)
            await ru.asyncify(session.commit)
Пример #3
0
    async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
        async with data.session_acm() as session:
            author = await data.find_author(session=session, required=True)
            if len(args) == 0:
                message = []
                for obj in await self.get_updatables_of_user(session=session,
                                                             user=author):

                    async def change(attribute: str, value: Any):
                        """A shortcut for self.__change."""
                        await self._change(session=session,
                                           obj=obj,
                                           attribute=attribute,
                                           new=value)

                    await self.update(session=session, obj=obj, change=change)
                    message.append(self.describe(obj))
                if len(message) == 0:
                    raise rc.UserError("Nessun account connesso.")
                await ru.asyncify(session.commit)
                await data.reply("\n".join(message))
            else:
                created = await self.create(session=session,
                                            user=author,
                                            args=args,
                                            data=data)
                await ru.asyncify(session.commit)
                if created is not None:
                    message = [
                        "🔗 Account collegato!", "",
                        self.describe(created)
                    ]
                    await data.reply("\n".join(message))
Пример #4
0
 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}")
Пример #5
0
 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}")
Пример #6
0
    async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
        async with data.session_acm() as session:
            author = await data.find_author(session=session, required=True)
        today = datetime.date.today()

        h = author.uid * hash(today)

        r = random.Random(x=h)

        message = r.sample(self._fortunes, 1)[0]
        await data.reply(message)
Пример #7
0
 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))
Пример #8
0
    async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
        BattleT = self.alchemy.get(DndBattle)

        line_args = args.joined(require_at_least=1).split("\n", 1)
        name = line_args[0]
        description = line_args[1] if len(line_args) > 1 else None

        async with data.session_acm() as session:
            battle = BattleT(name=name, description=description)

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

            await data.reply(
                f"✅ Battle [b]{battle.name}[/b] (ID: {battle.id}) created!")
Пример #9
0
    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}")
Пример #10
0
    async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
        async with data.session_acm() as session:
            author = await data.find_author(session=session, required=True)

            user_arg = args[0]
            qty_arg = args[1]

            if user_arg is None:
                raise rc.InvalidInputError(
                    "Non hai specificato un destinatario!")
            user = await rbt.User.find(alchemy=self.alchemy,
                                       session=session,
                                       identifier=user_arg)
            if user is None:
                raise rc.InvalidInputError("L'utente specificato non esiste!")
            if user.uid == author.uid:
                raise rc.InvalidInputError(
                    "Non puoi inviare fiorygi a te stesso!")

            if qty_arg is None:
                raise rc.InvalidInputError("Non hai specificato una quantità!")
            try:
                qty = int(qty_arg)
            except ValueError:
                raise rc.InvalidInputError(
                    "La quantità specificata non è un numero!")
            if qty <= 0:
                raise rc.InvalidInputError(
                    "La quantità specificata deve essere almeno 1!")

            if author.fiorygi.fiorygi < qty:
                raise rc.InvalidInputError(
                    "Non hai abbastanza fiorygi per effettuare la transazione!"
                )

            await FiorygiTransaction.spawn_fiorygi(
                author,
                -qty,
                f"aver ceduto fiorygi a {user}",
                data=data,
                session=session)
            await FiorygiTransaction.spawn_fiorygi(
                user,
                qty,
                f"aver ricevuto fiorygi da {author}",
                data=data,
                session=session)
Пример #11
0
        async def callback(data: rc.CommandData):
            async with data.session_acm() as session:
                # Find the user who clicked on the button
                user = await data.find_author(session=session, required=True)

                # Get the related MMEvent
                mmevent: MMEvent = await ru.asyncify(
                    session.query(self._EventT).get, self.mmid)

                # Check if the user had already responded
                mmresponse: MMResponse = await ru.asyncify(
                    session.query(self._ResponseT).filter_by(
                        user=user, mmevent=mmevent).one_or_none)

                if mmresponse is None:
                    # If they didn't respond, create a new MMResponse
                    # noinspection PyArgumentList
                    mmresponse = self._ResponseT(user=user,
                                                 mmevent=mmevent,
                                                 choice=choice)
                    session.add(mmresponse)

                    # Drop fiorygi
                    if random.randrange(100) < self.command.config[
                            "matchmaking"]["fiorygi_award_chance"]:
                        await FiorygiTransaction.spawn_fiorygi(
                            user,
                            1,
                            "aver risposto a un matchmaking",
                            data=data,
                            session=session)
                else:
                    # Change their response
                    mmresponse.choice = choice
                try:
                    await ru.asyncify(session.commit)
                except psycopg2.Error:
                    raise rc.UserError(
                        "Hai già risposto nello stesso modo a questo matchmaking."
                    )

                await self.telegram_channel_message_update()

                await data.reply(f"{choice.value} Hai risposto al matchmaking!"
                                 )
Пример #12
0
        async def callback(data: rc.CommandData):
            async with data.session_acm() as session:
                # Find the user who clicked on the button
                user = await data.find_author(session=session, required=True)

                # Get the related MMEvent
                mmevent: MMEvent = await ru.asyncify(
                    session.query(self._EventT).get, self.mmid)

                # Ensure the user has the required roles to start the matchmaking
                if user != mmevent.creator and "admin" not in user.roles:
                    raise rc.UserError(
                        "Non hai i permessi per eliminare questo matchmaking!")

                # Interrupt the matchmaking with the MANUAL_DELETE reason
                await self.queue.put(Interrupts.MANUAL_START)

                await data.reply(f"🚩 Evento avviato!")
Пример #13
0
    async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
        target = args[0]

        async with data.session_acm() as session:
            units = await get_targets(target, data=data, session=session)
            if len(units) == 0:
                raise rc.InvalidInputError(
                    f"No targets found matching [c]{target}[/c].")

            for unit in units:
                await self._change(unit, args[1:])

            await session.commit()

            message = []
            for unit in units:
                message.append(f"{unit}")

            await data.reply("\n\n".join(message))
Пример #14
0
    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()
Пример #15
0
    async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
        CvstatsT = self.alchemy.get(Cvstats)

        async with data.session_acm() as session:
            cvstats = 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))
Пример #16
0
    async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
        TreasureT = self.alchemy.get(Treasure)

        async with data.session_acm() as session:
            author = await data.find_author(session=session, required=True)
            code = args[0].lower()

            treasure = await ru.asyncify(session.query(TreasureT).get, code)
            if treasure is None:
                raise rc.UserError(
                    "Non esiste nessun Treasure con quel codice.")
            if treasure.redeemed_by is not None:
                raise rc.UserError(
                    f"Quel tesoro è già stato riscattato da {treasure.redeemed_by}."
                )

            treasure.redeemed_by = author
            await ru.asyncify(session.commit)
        await FiorygiTransaction.spawn_fiorygi(
            data, author, treasure.value,
            f'aver trovato il tesoro "{treasure.code}"')
        await data.reply("🤑 Tesoro riscattato!")
Пример #17
0
    async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
        """Handle a matchmaking command call."""

        # Parse the arguments, either with the standard syntax or with the Proto syntax
        dt, title, description = self._parse_args(args)

        # Add the MMEvent to the database
        async with data.session_acm() as session:
            author = await data.find_author(session=session, required=True)

            mmevent: MMEvent = self.alchemy.get(MMEvent)(
                creator=author,
                datetime=dt,
                title=title,
                description=description,
                interface=self.serf.interface_name)
            session.add(mmevent)
            await ru.asyncify(session.commit)

            # Create and run a task for the newly created MMEvent
            task = MMTask(mmevent.mmid, command=self)
            task.start()

        await data.reply(f"🚩 Matchmaking creato!")
Пример #18
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)
Пример #19
0
    async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
        async with data.session_acm() as session:
            author = await data.find_author(session=session, required=False)
            if author is not None:
                raise rc.UserError(f"This account is already connected to {author}!")

            username = args[0]
            password = "******".join(args[1:])

            user = await data.find_user(session=session, identifier=username)
            if user is None:
                raise rc.UserError("No such user.")
            try:
                successful = user.test_password(password)
            except ValueError:
                raise rc.UserError(f"User {user} has no password set!")
            if not successful:
                raise rc.InvalidInputError(f"Invalid password!")

            if rst is not None and isinstance(self.serf, rst.TelegramSerf):
                import telegram
                message: telegram.Message = data.message
                from_user: telegram.User = message.from_user
                TelegramT = self.alchemy.get(Telegram)
                tg_user: Telegram = await ru.asyncify(
                    session.query(TelegramT).filter_by(tg_id=from_user.id).one_or_none
                )
                if tg_user is None:
                    # Create
                    tg_user = TelegramT(
                        user=user,
                        tg_id=from_user.id,
                        first_name=from_user.first_name,
                        last_name=from_user.last_name,
                        username=from_user.username
                    )
                    session.add(tg_user)
                else:
                    # Edit
                    tg_user.first_name = from_user.first_name
                    tg_user.last_name = from_user.last_name
                    tg_user.username = from_user.username
                await ru.asyncify(session.commit)
                await data.reply(f"↔️ Account {tg_user} synced to {user}!")

            elif rsd is not None and isinstance(self.serf, rsd.DiscordSerf):
                import discord
                message: discord.Message = data.message
                ds_author: discord.User = message.author
                DiscordT = self.alchemy.get(Discord)
                ds_user: Discord = await ru.asyncify(
                    session.query(DiscordT).filter_by(discord_id=ds_author.id).one_or_none
                )
                if ds_user is None:
                    # Create
                    # noinspection PyProtectedMember
                    ds_user = DiscordT(
                        user=user,
                        discord_id=ds_author.id,
                        username=ds_author.name,
                        discriminator=ds_author.discriminator,
                        avatar_url=ds_author.avatar_url._url
                    )
                    session.add(ds_user)
                else:
                    # Edit
                    ds_user.username = ds_author.name
                    ds_user.discriminator = ds_author.discriminator
                    ds_user.avatar_url = ds_author.avatar_url
                await ru.asyncify(session.commit)
                await data.reply(f"↔️ Account {ds_user} synced to {ds_author}!")

            else:
                raise rc.UnsupportedError(f"Unknown interface: {self.serf.__class__.__qualname__}")
Пример #20
0
 async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
     async with data.session_acm() as session:
         if isinstance(self.serf, rst.TelegramSerf):
             message: telegram.Message = data.message
             reply: telegram.Message = message.reply_to_message
             creator = await data.find_author(session=session,
                                              required=True)
             # noinspection PyUnusedLocal
             quoted: Optional[str]
             # noinspection PyUnusedLocal
             text: Optional[str]
             # noinspection PyUnusedLocal
             context: Optional[str]
             # noinspection PyUnusedLocal
             timestamp: datetime.datetime
             # noinspection PyUnusedLocal
             media_url: Optional[str]
             # noinspection PyUnusedLocal
             spoiler: bool
             if creator is None:
                 await data.reply(
                     "⚠️ Devi essere registrato a Royalnet per usare questo comando!"
                 )
                 return
             if reply is not None:
                 # Get the message text
                 text = reply.text
                 # Check if there's an image associated with the reply
                 photosizes: Optional[List[
                     telegram.PhotoSize]] = reply.photo
                 if photosizes:
                     # Text is a caption
                     text = reply.caption
                     media_url = await to_imgur(
                         self.config["Imgur"]["token"], photosizes,
                         text if text is not None else "")
                 else:
                     media_url = None
                 # Ensure there is a text or an image
                 if not (text or media_url):
                     raise rc.InvalidInputError(
                         "Il messaggio a cui hai risposto non contiene testo o immagini."
                     )
                 # Find the Royalnet account associated with the sender
                 quoted_tg = await ru.asyncify(
                     session.query(self.alchemy.get(
                         rbt.Telegram)).filter_by(
                             tg_id=reply.from_user.id).one_or_none)
                 quoted_account = quoted_tg.user if quoted_tg is not None else None
                 # Find the quoted name to assign
                 quoted_user: telegram.User = reply.from_user
                 quoted = quoted_user.full_name
                 # Get the timestamp
                 timestamp = reply.date
                 # Set the other properties
                 spoiler = False
                 context = None
             else:
                 # Get the current timestamp
                 timestamp = datetime.datetime.now()
                 # Get the message text
                 raw_text = " ".join(args)
                 # Check if there's an image associated with the reply
                 photosizes: Optional[List[
                     telegram.PhotoSize]] = message.photo
                 if photosizes:
                     media_url = await to_imgur(
                         self.config["Imgur"]["token"], photosizes,
                         raw_text if raw_text is not None else "")
                 else:
                     media_url = None
                 # Parse the text, if it exists
                 if raw_text:
                     # Pass the sentence through the diario regex
                     match = re.match(
                         r'(!)? *["«‘“‛‟❛❝〝"`]([^"]+)["»’”❜❞〞"`] *(?:(?:-{1,2}|—) *([^,]+))?(?:, *([^ ].*))?',
                         raw_text)
                     # Find the corresponding matches
                     if match is not None:
                         spoiler = bool(match.group(1))
                         text = match.group(2)
                         quoted = match.group(3)
                         context = match.group(4)
                     # Otherwise, consider everything part of the text
                     else:
                         spoiler = False
                         text = raw_text
                         quoted = None
                         context = None
                     # Ensure there's a quoted
                     if not quoted:
                         quoted = None
                     if not context:
                         context = None
                     # Find if there's a Royalnet account associated with the quoted name
                     if quoted is not None:
                         quoted_alias = await ru.asyncify(
                             session.query(self.alchemy.get(
                                 rbt.Alias)).filter_by(
                                     alias=quoted.lower()).one_or_none)
                     else:
                         quoted_alias = None
                     quoted_account = quoted_alias.user if quoted_alias is not None else None
                 else:
                     text = None
                     quoted = None
                     quoted_account = None
                     spoiler = False
                     context = None
                 # Ensure there is a text or an image
                 if not (text or media_url):
                     raise rc.InvalidInputError(
                         "Manca il testo o l'immagine da inserire nel diario."
                     )
             # Create the diario quote
             diario = self.alchemy.get(Diario)(
                 creator=creator,
                 quoted_account=quoted_account,
                 quoted=quoted,
                 text=text,
                 context=context,
                 timestamp=timestamp,
                 media_url=media_url,
                 spoiler=spoiler)
             session.add(diario)
             await ru.asyncify(session.commit)
             await data.reply(f"✅ {str(diario)}")
         else:
             # Find the creator of the quotes
             creator = await data.find_author(session=session,
                                              required=True)
             # Recreate the full sentence
             raw_text = " ".join(args)
             # Pass the sentence through the diario regex
             match = re.match(
                 r'(!)? *["«‘“‛‟❛❝〝"`]([^"]+)["»’”❜❞〞"`] *(?:(?:-{1,2}|—) *([^,]+))?(?:, *([^ ].*))?',
                 raw_text)
             # Find the corresponding matches
             if match is not None:
                 spoiler = bool(match.group(1))
                 text = match.group(2)
                 quoted = match.group(3)
                 context = match.group(4)
             # Otherwise, consider everything part of the text
             else:
                 spoiler = False
                 text = raw_text
                 quoted = None
                 context = None
             timestamp = datetime.datetime.now()
             # Ensure there is some text
             if not text:
                 raise rc.InvalidInputError(
                     "Manca il testo o l'immagine da inserire nel diario.")
             # Or a quoted
             if not quoted:
                 quoted = None
             if not context:
                 context = None
             # Find if there's a Royalnet account associated with the quoted name
             if quoted is not None:
                 quoted_account = await rbt.User.find(
                     self.alchemy, session, quoted)
             else:
                 quoted_account = None
             if quoted_account is None:
                 raise rc.UserError(
                     "Il nome dell'autore è ambiguo, quindi la riga non è stata aggiunta.\n"
                     "Per piacere, ripeti il comando con un nome più specifico!"
                 )
             # Create the diario quote
             DiarioT = self.alchemy.get(Diario)
             diario = DiarioT(creator=creator,
                              quoted_account=quoted_account,
                              quoted=quoted,
                              text=text,
                              context=context,
                              timestamp=timestamp,
                              media_url=None,
                              spoiler=spoiler)
             session.add(diario)
             await ru.asyncify(session.commit)
             await data.reply(f"✅ {str(diario)}")
Пример #21
0
 async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
     if name := args.optional(0) is not None:
         async with data.session_acm() as session:
             user = await User.find(alchemy=self.alchemy,
                                    session=session,
                                    identifier=name)