Exemplo n.º 1
0
Arquivo: cho.py Projeto: Mxnuuel/gulag
class SendPrivateMessage(BanchoPacket, type=Packets.OSU_SEND_PRIVATE_MESSAGE):
    msg: osuTypes.message

    async def handle(self, p: Player) -> None:
        if p.silenced:
            log(f'{p} tried to send a dm while silenced.', Ansi.YELLOW)
            return

        msg = self.msg.msg
        target = self.msg.target

        # allow this to get from sql - players can receive
        # messages offline, due to the mail system. B)
        if not (t := await glob.players.get(name=target, sql=True)):
            log(f'{p} tried to write to non-existent user {target}.',
                Ansi.YELLOW)
            return

        if t.pm_private and p.id not in t.friends:
            p.enqueue(packets.userDMBlocked(target))
            log(f'{p} tried to message {t}, but they are blocking dms.')
            return

        if t.silenced:
            # if target is silenced, inform player.
            p.enqueue(packets.targetSilenced(target))
            log(f'{p} tried to message {t}, but they are silenced.')
            return

        msg = f'{msg[:2045]}...' if msg[2048:] else msg

        if t.status.action == Action.Afk and t.away_msg:
            # send away message if target is afk and has one set.
            await p.send(t, t.away_msg)

        if t is glob.bot:
            # may have a command in the message.
            cmd = (msg.startswith(glob.config.command_prefix)
                   and await commands.process_commands(p, t, msg))

            if cmd:
                # command triggered, send response if any.
                if 'resp' in cmd:
                    await p.send(t, cmd['resp'])
            else:
                # no commands triggered.
                if match := regexes.now_playing.match(msg):
                    # user is /np'ing a map.
                    # save it to their player instance
                    # so we can use this elsewhere owo..
                    p.last_np = await Beatmap.from_bid(int(match['bid']))

                    if p.last_np:
                        if match['mods']:
                            # [1:] to remove leading whitespace
                            mods = Mods.from_np(match['mods'][1:])
                        else:
                            mods = Mods.NOMOD

                        if mods not in p.last_np.pp_cache:
                            await p.last_np.cache_pp(mods)

                        # since this is a DM to the bot, we should
                        # send back a list of general PP values.
                        # TODO: !acc and !mods in commands to
                        #       modify these values :P
                        _msg = [p.last_np.embed]
                        if mods:
                            _msg.append(f'+{mods!r}')

                        msg = f"{' '.join(_msg)}: " + ' | '.join([
                            f'{acc}%: {pp:.2f}pp'
                            for acc, pp in zip((90, 95, 98, 99,
                                                100), p.last_np.pp_cache[mods])
                        ])

                    else:
                        msg = 'Could not find map.'

                    await p.send(t, msg)
Exemplo n.º 2
0
class SendPrivateMessage(BanchoPacket, type=Packets.OSU_SEND_PRIVATE_MESSAGE):
    msg: osuTypes.message

    async def handle(self, p: Player) -> None:
        if p.silenced:
            log(f'{p} tried to send a dm while silenced.', Ansi.LYELLOW)
            return

        # remove leading/trailing whitespace
        msg = self.msg.msg.strip()
        t_name = self.msg.target

        # allow this to get from sql - players can receive
        # messages offline, due to the mail system. B)
        if not (t := await glob.players.get_ensure(name=t_name)):
            log(f'{p} tried to write to non-existent user {t_name}.',
                Ansi.LYELLOW)
            return

        if t.pm_private and p.id not in t.friends:
            p.enqueue(packets.userDMBlocked(t_name))
            log(f'{p} tried to message {t}, but they are blocking dms.')
            return

        if t.silenced:
            # if target is silenced, inform player.
            p.enqueue(packets.targetSilenced(t_name))
            log(f'{p} tried to message {t}, but they are silenced.')
            return

        # limit message length to 2k chars
        # perhaps this could be dangerous with !py..?
        if len(msg) > 2000:
            msg = f'{msg[:2000]}... (truncated)'
            p.enqueue(
                packets.notification('Your message was truncated\n'
                                     '(exceeded 2000 characters).'))

        if t.status.action == Action.Afk and t.away_msg:
            # send away message if target is afk and has one set.
            p.send(t.away_msg, sender=t)

        if t is glob.bot:
            # may have a command in the message.
            cmd = (msg.startswith(glob.config.command_prefix)
                   and await commands.process_commands(p, t, msg))

            if cmd:
                # command triggered, send response if any.
                if 'resp' in cmd:
                    p.send(cmd['resp'], sender=t)
            else:
                # no commands triggered.
                if match := regexes.now_playing.match(msg):
                    # user is /np'ing a map.
                    # save it to their player instance
                    # so we can use this elsewhere owo..
                    bmap = await Beatmap.from_bid(int(match['bid']))

                    if bmap:
                        # parse mode_vn int from regex
                        if match['mode_vn'] is not None:
                            mode_vn = {
                                'Taiko': 1,
                                'CatchTheBeat': 2,
                                'osu!mania': 3
                            }[match['mode_vn']]
                        else:
                            # use beatmap mode if not specified
                            mode_vn = bmap.mode.as_vanilla

                        p.last_np = {
                            'bmap': bmap,
                            'mode_vn': mode_vn,
                            'timeout': time.time() + 300  # 5mins
                        }

                        # calc pp if possible
                        if not glob.oppai_built:
                            msg = 'No oppai-ng binary was found at startup.'
                        elif mode_vn not in (0, 1):
                            msg = 'PP not yet supported for that mode.'
                        else:
                            if match['mods'] is not None:
                                # [1:] to remove leading whitespace
                                mods = Mods.from_np(match['mods'][1:], mode_vn)
                            else:
                                mods = Mods.NOMOD

                            if mods not in bmap.pp_cache:
                                await bmap.cache_pp(mods)

                            # since this is a DM to the bot, we should
                            # send back a list of general PP values.
                            _msg = [bmap.embed]
                            if mods:
                                _msg.append(f'+{mods!r}')

                            msg = f"{' '.join(_msg)}: " + ' | '.join([
                                f'{acc}%: {pp:.2f}pp'
                                for acc, pp in zip((90, 95, 98, 99,
                                                    100), bmap.pp_cache[mods])
                            ])

                    else:
                        msg = 'Could not find map.'

                        # time out their previous /np
                        p.last_np['timeout'] = 0

                    p.send(msg, sender=t)