Exemplo n.º 1
0
    async def change_status(self, name):
        log.debug("Changing status to {}".format(name))
        log_to_file("Changing status to {}".format(name))

        shards = list(self.client.shards.keys())
        for shard_id in shards:
            customized = name + " | shard {}".format(shard_id + 1)
	await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name="you"))
Exemplo n.º 2
0
    async def change_status(self, name):
        log.debug("Changing status to {}".format(name))
        log_to_file("Changing status to {}".format(name))

        shards = list(self.client.shards.keys())
        for shard_id in shards:
            customized = name + " | shard {}".format(shard_id + 1)
            await self.client.change_presence(game=Game(name=customized, type=0), shard_id=shard_id)
Exemplo n.º 3
0
async def start():
    if not parser.has_option("Credentials", "token"):
        log.critical("Token not found. Check your settings.ini")
        log_to_file("Could not start: Token not specified")
        return

    token = parser.get("Credentials", "token")

    await client.login(token)
    await client.connect()
Exemplo n.º 4
0
    async def random_cat(self, type_="gif"):
        # structure:
        # response -> data -> images -> image -> url
        try:
            data = await self.req.get_html(self.url, api_key=self.key, format=self.format, size=self.size, type=type_)
            link = BeautifulSoup(data, "lxml").find("img").get("src")
        except (APIFailure, Exception):
            log_to_file("CatGenerator exception\n{}".format(traceback.format_exc()), "bug")
            return None

        return link
Exemplo n.º 5
0
    async def on_guild_join(self, guild, **kwargs):
        # Always 'en'
        lang = kwargs.get("lang")

        d_chan = await self.default_channel(guild)
        # Say hi to the server
        await self.send_message_failproof(
            d_chan, self.trans.get("EVENT_SERVER_JOIN", lang))

        # Create server settings
        self.handler.server_setup(guild)

        # Log
        log_to_file("Joined guild: {}".format(guild.name))
Exemplo n.º 6
0
async def on_ready():
    # Just prints "Resumed connection" if that's the way it is
    global IS_RESUME
    if IS_RESUME:
        print("Resumed connection...")
        log_to_file("Resumed connection as {}".format(client.user.name))
        return
    IS_RESUME = True

    print("connected!")
    print("BOT name: {} ({})".format(client.user.name, client.user.id))

    log_to_file("Connected as {} ({})".format(client.user.name, client.user.id))

    await nano.dispatch_event(ON_READY)
Exemplo n.º 7
0
    async def start(self):
        while self.enabled:
            # Run the backup every day or as specified
            await sleep(self.time)

            # Full backup counter
            self.temp_keep -= 1

            if self.temp_keep <= 0:
                dated_backup = True
                self.temp_keep = int(self.keep_every)
            else:
                dated_backup = False

            log_to_file("Creating a backup...")
            self.backup(dated_backup)
Exemplo n.º 8
0
    async def run(self):
        await self.client.wait_until_ready()

        # Shuffle the game list in place
        shuffle(game_list)

        for game in game_list:
            await self.change_status(game)
            await sleep(self.time)

            if self.client.is_closed:
                break

        # Shuffle when the whole list is used
        shuffle(game_list)

        log_to_file("Exited status changer")
Exemplo n.º 9
0
def main():
    try:
        print("Connecting to Discord...", end="")
        loop.run_until_complete(start())

    except Exception as e:
        loop.run_until_complete(client.logout())
        log.critical("Something went wrong, quitting (see log bugs.txt)")
        log_to_file("CRITICAL, shutting down: {}".format(e), "bug")

        # Attempts to save plugin state
        log.critical("Dispatching ON_SHUTDOW...")
        loop.run_until_complete(nano.dispatch_event(ON_SHUTDOWN))
        log.critical("Shutting down...")

    finally:
        loop.close()
Exemplo n.º 10
0
    async def monitor(self):
        await self.client.wait_until_ready()

        last_time = time.time()

        while True:
            # Iterate through users and their reminders
            a = self.get_all_reminders()
            for user in a:

                for id_, reminder in user.items():
                    # If enough time has passed, send the reminder
                    if int(reminder["time_target"]) <= last_time:
                        try:
                            await self.dispatch(reminder)
                        except (DiscordException, KeyError):
                            log.warning("ERROR in reminders, see bugs.txt")
                            log_to_file(traceback.format_exc(), "bug")

                        self.remove_reminder(reminder["author"], id_)

            # And tick.
            last_time = await self.tick(last_time)
Exemplo n.º 11
0
    async def on_message(self, message, **kwargs):
        client = self.client

        prefix = kwargs.get("prefix")
        lang = kwargs.get("lang")

        # Check if this is a valid command
        if not is_valid_command(message.content, commands, prefix):
            return
        else:
            self.stats.add(MESSAGE)

        def startswith(*matches):
            for match in matches:
                if message.content.startswith(match):
                    return True

            return False

        # Global owner filter

        if not self.handler.is_bot_owner(message.author.id):
            await message.channel.send(self.trans.get("PERM_OWNER", lang))
            return

        # nano.dev.server_info [id]
        elif startswith("nano.dev.server_info"):
            s_id = message.content[len("nano.dev.server_info "):]

            srv = utils.find(lambda b: b.id == s_id, client.guilds)

            if not srv:
                await message.channel.send("No such guild. " + StandardEmoji.CROSS)
                return

            nano_data = self.handler.get_server_data(srv)
            to_send = "{}\n```css\nMember count: {}\nChannels: {}\nOwner: {}```\n" \
                      "*Settings*: ```{}```".format(srv.name, srv.member_count, ",".join([ch.name for ch in srv.channels]), srv.owner.name, nano_data)

            await message.channel.send(to_send)

        # nano.dev.test_exception
        elif startswith("nano.dev.test_exception"):
            int("abcdef")

        # nano.dev.embed_test
        elif startswith("nano.dev.embed_test"):
            emb = Embed(title="Stats", colour=Colour.darker_grey())
            emb.add_field(name="Messages Sent", value="sample messages")

            await message.channel.send("Stats", embed=emb)

        # nano.dev.backup
        elif startswith("nano.dev.backup"):
            self.backup.manual_backup()
            await message.channel.send("Backup completed " + StandardEmoji.PERFECT)

        # nano.dev.leave_server
        elif startswith("nano.dev.leave_server"):
            try:
                sid = int(message.content[len("nano.dev.leave_server "):])
            except ValueError:
                await message.channel.send("Not a number.")
                return

            srv = await self.client.get_guild(sid)
            await srv.leave()
            await message.channel.send("Left {}".format(srv.id))

        # nano.dev.tf.reload
        elif startswith("nano.dev.tf.clean"):
            self.nano.get_plugin("tf2").instance.tf.request()

            await message.channel.send("Re-downloaded data...")

        # nano.dev.plugin.reload
        elif startswith("nano.dev.plugin.reload"):
            name = message.content[len("nano.dev.plugin.reload "):]

            v_old = self.nano.get_plugin(name).plugin.NanoPlugin.version
            s = await self.nano.reload_plugin(name)
            v_new = self.nano.get_plugin(name).plugin.NanoPlugin.version

            if s:
                await message.channel.send("Successfully reloaded **{}**\nFrom version *{}* to *{}*.".format(name, v_old, v_new))
            else:
                await message.channel.send("Something went wrong, check the logs.")

        # nano.dev.servers.clean
        elif startswith("nano.dev.servers.tidy"):
            self.handler.delete_server_by_list([s.id for s in self.client.guilds])

        # nano.restart
        elif startswith("nano.restart"):
            await message.channel.send("**DED, but gonna come back**")

            await client.logout()

            self.shutdown_mode = "restart"
            return "shutdown"

        # nano.kill
        elif startswith("nano.kill"):
            await message.channel.send("**DED**")

            await client.logout()

            self.shutdown_mode = "exit"
            return "shutdown"

        # nano.playing
        elif startswith("nano.playing"):
            status = message.content[len("nano.playing "):]

            await client.change_presence(activity=Game(name=str(status)))
            await message.channel.send("Status changed " + StandardEmoji.THUMBS_UP)

        # nano.dev.translations.reload
        elif startswith("nano.dev.translations.reload"):
            self.trans.reload_translations()

            await message.channel.send(StandardEmoji.PERFECT)

        # nano.dev.test_default_channel
        elif startswith("nano.dev.test_default_channel"):
            df = await self.default_channel(message.guild)

            if not df:
                await message.channel.send("No default channel? w a t")
                return

            await message.channel.send("Default channel is {}, sending test message".format(df.mention))
            await df.send("This is a test message. Apparently everything is ok.")

        # nano.dev.announce
        elif startswith("nano.dev.announce"):
            await message.channel.send("Sending... ")
            ann = message.content[len("nano.dev.announce "):]

            s = []
            for g in self.client.guilds:
                try:
                    d_chan = await self.default_channel(g)
                    await d_chan.send(ann)
                    log_to_file("Sent announcement for {}".format(g.name))
                    s.append(g.name)
                except DiscordException:
                    log_to_file("Couldn't send announcement for {}".format(g.name))

            await message.channel.send("Sent to {} servers".format(len(s)))

        # nano.dev.userdetective

        elif startswith("nano.dev.userdetective"):
            param = str(message.content[len(prefix + "nano.dev.userdetective"):])

            # Number
            if param.isdigit():
                user = self.client.get_user(int(param))
                if not user:
                    await message.channel.send("No user with such ID.")
                    return
            elif len(message.mentions) > 0:
                user = message.mentions[0]
            else:
                members = [user for user in self.client.get_all_members()
                           if user.name == param]

                if not members:
                    await message.channel.send("No users with that name.")
                    return

                user = members[0]

            srv_in_common = 0
            server_table_temp = []
            # Loop though servers and find ones the user is in
            for srv in self.client.guilds:
                mem = srv.get_member(user.id)
                if mem:
                    srv_in_common += 1
                    server_table_temp.append("{}: {}".format(srv.name, mem.display_name))


            join_time_ago = int((datetime.now() - user.created_at).total_seconds())
            join_time_ago = resolve_time(join_time_ago, "en")

            embed = Embed(title="{}#{}{}".format(user.name, user.discriminator, ":robot:" if user.bot else ""), description="ID: {}".format(user.id))
            embed.add_field(name="Joined Discord", value="**{}** ago\nISO time: {}".format(join_time_ago, user.created_at))
            embed.add_field(name="Avatar url", value=user.avatar_url_as(format="png"))
            embed.add_field(name="Servers in common", value="**{}** on this shard:\n```http\n{}```".format(srv_in_common, "\n".join(server_table_temp)))

            await message.channel.send(embed=embed)
Exemplo n.º 12
0
    async def on_guild_remove(self, guild, **_):
        # Deletes server data
        self.handler.delete_server(guild.id)

        # Log
        log_to_file("Removed from guild: {}".format(guild.name))
Exemplo n.º 13
0
    async def on_message(self, message, **kwargs):
        trans = self.trans

        prefix = kwargs.get("prefix")
        lang = kwargs.get("lang")

        # Check if this is a valid command
        if not is_valid_command(message.content, commands, prefix):
            return
        else:
            self.stats.add(MESSAGE)

        def startswith(*matches):
            for match in matches:
                if message.content.startswith(match):
                    return True

            return False

        # !poll start
        # Arguments: "[title]" [option1]|(option2)|...
        # OR       : "[title]" [option1],(option2),...
        if startswith(prefix + "poll start"):
            if not self.handler.is_admin(message.author, message.guild):
                await message.channel.send(trans.get("PERM_ADMIN", lang))
                self.stats.add(WRONG_PERMS)
                return

            if self.vote.in_progress(message.guild.id):
                await message.channel.send(
                    trans.get("MSG_VOTING_IN_PROGRESS", lang))
                return

            arguments = message.content[len(prefix +
                                            "poll start "):].strip(" ")
            if not arguments:
                await message.channel.send(
                    trans.get("MSG_VOTING_I_USAGE", lang).format(prefix))
                return

            # TITLE
            # Handle short_title, "longer title", 'also like this'
            if arguments[0] == "\"":
                _, title, arguments = arguments.split("\"", maxsplit=3)
            elif arguments[0] == "'":
                _, title, arguments = arguments.split("'", maxsplit=3)
            else:
                title, arguments = arguments.split(" ", maxsplit=1)

            arguments = arguments.lstrip(" ")

            # CHOICES
            # | as separator
            if "|" in arguments:
                items = [a.strip(" ") for a in arguments.split("|") if a]
            # , used as separator
            else:
                items = [a.strip(" ") for a in arguments.split(",") if a]

            # Send an error if there's only a title
            if len(items) < 2:
                await message.channel.send(
                    trans.get("MSG_VOTING_NEED_OPTIONS", lang).format(prefix))
                return
            # END OF ARGUMENT PARSING

            # Check item amount
            if len(items) > VOTE_ITEM_LIMIT:
                await message.channel.send(
                    trans.get("MSG_VOTING_OPTIONS_TM",
                              lang).format(VOTE_ITEM_LIMIT, len(items)))
                return

            # Check total length
            if (len(title) + sum([len(a)
                                  for a in items])) > VOTE_ITEM_MAX_LENGTH:
                await message.channel.send(
                    trans.get("MSG_VOTING_OPTIONS_TL ",
                              lang).format(VOTE_ITEM_MAX_LENGTH,
                                           sum([len(a) for a in items])))
                return

            # Check if any option is empty
            if any(e == "" for e in items):
                await message.channel.send(
                    trans.get("MSG_VOTING_EMPTY_ITEM", lang))
                return

            self.vote.start_vote(message.author.id, message.guild.id, title,
                                 items)

            # Generates a list of options to show
            choices = "\n\n".join([
                "[{}]\n{}".format(en + 1, ch) for en, ch in enumerate(
                    self.vote.get_choices(message.guild.id))
            ])

            await message.channel.send(
                trans.get("MSG_VOTING_STARTED", lang).format(title, choices))

        # !poll end
        elif startswith(prefix + "poll end"):
            if not self.handler.is_admin(message.author, message.guild):
                await message.channel.send(trans.get("PERM_ADMIN", lang))
                self.stats.add(WRONG_PERMS)
                return

            if not self.vote.in_progress(message.guild.id):
                await message.channel.send(
                    trans.get("MSG_VOTING_NO_PROGRESS", lang))
                return

            # Wait for confirmation
            msg = await message.channel.send(
                trans.get("MSG_VOTING_END_CONFIRMATION",
                          lang).format(OK_EMOJI))
            await msg.add_reaction(OK_EMOJI)

            def check(reaction, user):
                return user == message.author and str(
                    reaction.emoji) == OK_EMOJI

            try:
                await self.client.wait_for('reaction_add',
                                           timeout=45,
                                           check=check)
            except asyncio.TimeoutError:
                await message.channel.send(
                    trans.get("MSG_VOTING_END_ABORT", lang))
                return

            await msg.delete()

            votes = self.vote.get_votes(message.guild.id)
            title = self.vote.get_title(message.guild.id)

            total_votes = sum(votes.values())

            embed = Embed(title="**{}**".format(title),
                          colour=Colour(0x303F9F),
                          description=trans.get("MSG_VOTING_AMOUNT",
                                                lang).format(total_votes))

            for name, val in votes.items():
                # Zero-width space
                dotted = add_dots(name, max_len=240) or "\u200B"
                embed.add_field(name=dotted,
                                value=trans.get("MSG_VOTING_AMOUNT2",
                                                lang).format(val))

            # Actually end the voting
            self.vote.end_voting(message.guild.id)

            try:
                await message.channel.send(
                    trans.get("MSG_VOTING_ENDED", lang) + "\n", embed=embed)
            except errors.HTTPException as e:
                await message.channel.send(trans.get("MSG_VOTING_ERROR", lang))
                log_to_file("VOTING ({}): {}".format(e, embed.to_dict()),
                            "bug")

        # !poll status
        elif startswith(prefix + "poll status"):
            if not self.vote.in_progress(message.guild.id):
                await message.channel.send(
                    trans.get("MSG_VOTING_NO_PROGRESS", lang))
                return

            header = self.vote.get_title(message.guild.id)
            votes = sum(self.vote.get_votes(message.guild.id).values())

            if votes == 0:
                vote_disp = trans.get("MSG_VOTING_S_NONE", lang)
            elif votes == 1:
                vote_disp = trans.get("MSG_VOTING_S_ONE", lang)
            else:
                vote_disp = trans.get("MSG_VOTING_S_MULTI", lang).format(votes)

            await message.channel.send(
                trans.get("MSG_VOTING_STATUS", lang).format(header, vote_disp))

        # !vote
        elif startswith(prefix + "vote"):
            # Ignore if there is no vote going on instead of getting an exception
            if not self.vote.in_progress(message.guild.id):
                await message.add_reaction(X_EMOJI)

                msg = await message.channel.send(
                    trans.get("MSG_VOTING_NO_PROGRESS", lang))
                await asyncio.sleep(2)
                await msg.delete()

                return

            # Get the choice, but tell the author if he/she didn't supply a number
            try:
                choice = int(message.content[len(prefix + "vote "):]) - 1
            # Cannot convert to int
            except ValueError:
                await message.add_reaction(BLOCK_EMOJI)

                m = await message.channel.send(
                    trans.get("MSG_VOTING_NOT_NUMBER", lang))
                await asyncio.sleep(2)
                await m.delete()
                return

            res = self.vote.plus_one(choice, message.author.id,
                                     message.guild.id)

            # User already voted
            if res == -1:
                await message.add_reaction(BLOCK_EMOJI)

                msg = await message.channel.send(
                    trans.get("MSG_VOTING_CHEATER", lang))
                await asyncio.sleep(2)
                await msg.delete()

            # No such option
            elif not res:
                await message.add_reaction(X_EMOJI)

                msg = await message.channel.send(
                    trans.get("MSG_VOTING_INVALID_NUMBER", lang))
                await asyncio.sleep(2)
                await msg.delete()

            # Everything ok, was added
            else:
                await message.add_reaction(OK_EMOJI)

            self.stats.add(VOTE)
Exemplo n.º 14
0
    async def on_error(event, *args, **kwargs):
        e_type, value, _ = sys.exc_info()

        # Ignore Forbidden errors (but log them anyways)
        if e_type == errors.Forbidden:
            log.warning("Forbidden 403")

            if isinstance(args[0], Message):
                log_to_file("Forbidden 403. Server: {}, channel: {}".format(args[0].guild, args[0].channel))

            elif isinstance(args[0], Member):
                log_to_file("Forbidden 403. Server: {}, member: {}:{}".format(args[0].guild, args[0].name, args[0].id))

            else:
                try:
                    items = args[0].__dict__
                except AttributeError:
                    items = args[0].__slots__

                log_to_file("Forbidden 403. Unknown instance: {}:{}".format(type(args[0]), items))

        elif e_type == errors.HTTPException and str(value).startswith("BAD REQUEST"):
            log.warning("Bad Request 400")
            log_to_file("Bad Request 400: \nTraceback: {}".format(kwargs), "bug")

        elif e_type == errors.NotFound:
            log.warning("Not Found 404")
            log_to_file("Not Found 404: {}".format(value))

        # Ignore this, used for flow control
        elif e_type == IgnoredException:
            return

        else:
            if isinstance(args[0], (User, Member)):
                readable = "{}:{} (guild:{})".format(args[0].name, args[0].id, args[0].guild.id)
            elif isinstance(args[0], Message):
                readable = "'{}' by {} (guild:{})".format(args[0].content, args[0].author.name, args[0].guild.id)
            elif isinstance(args[0], Guild):
                readable = "{} (guild)({})".format(args[0].name, args[0].id)
            else:
                try:
                    readable = "__dict__ of {}: ".format(type(args[0]), args[0].__dict__)
                except AttributeError:
                    readable = "__slots__ of {}: ".format(type(args[0]), args[0].__slots__)

            log_to_file("EXCEPTION in {}: {}".format(event, readable), "bug")

            exc = traceback.format_exc()
            traceback.print_exc()
            log_to_file(exc, "bug")

            log.warning("Something went wrong, see bugs.txt")
Exemplo n.º 15
0
Arquivo: jokes.py Projeto: RossKM/Nano
    async def on_message(self, message, **kwargs):
        trans = self.trans

        prefix = kwargs.get("prefix")
        lang = kwargs.get("lang")

        # Check if this is a valid command
        if not is_valid_command(message.content, commands, prefix):
            return
        else:
            self.stats.add(MESSAGE)

        def startswith(*matches):
            for match in matches:
                if message.content.startswith(match):
                    return True

            return False

        # !cat gif/jpg/png
        if startswith(prefix + "cat"):
            fmt = str(message.content[len(prefix + "cat"):]).strip(" ")

            # GIF is the default type!
            if fmt == "jpg":
                type_ = "jpg"
            elif fmt == "png":
                type_ = "png"
            else:
                type_ = "gif"

            pic = await self.cats.random_cat(type_)

            if pic:
                # Teal (blue-ish)
                embed = Embed(colour=Colour(0x00796b))
                embed.set_image(url=pic)
                embed.set_footer(text=trans.get("MSG_CAT_FOOTER", lang))

                await message.channel.send(embed=embed)
            else:
                await message.channel.send(trans.get("MSG_CAT_FAILED", lang))

            self.stats.add(IMAGE_SENT)

        # !xkcd random/number/latest
        elif startswith(prefix + "xkcd"):
            fmt = str(message.content[len(prefix + "xkcd"):]).strip(" ")

            # Decides mode
            fetch = "random"
            if fmt:
                if is_number(fmt):
                    # Check if number is valid
                    if int(fmt) > self.xkcd.last_num:
                        await message.channel.send(
                            trans.get("MSG_XKCD_NO_SUCH", lang))
                        return
                    else:
                        fetch = "number"
                elif fmt == trans.get("INFO_RANDOM", lang) or fmt == "random":
                    fetch = "random"
                # Any other argument means latest
                else:
                    fetch = "latest"
            # Default: random
            else:
                fetch == "random"

            if fetch == "random":
                xkcd = await self.xkcd.get_random_xkcd()
            elif fetch == "number":
                xkcd = await self.xkcd.get_xkcd_by_number(fmt)
            # Can only mean latest
            else:
                xkcd = await self.xkcd.get_latest_xkcd()

            # In case something went wrong
            if not xkcd:
                await message.channel.send(trans.get("MSG_XKCD_FAILED", lang))
                log_to_file("XKCD: string {}, fetch: {}, got None".format(
                    fmt, fetch))

            xkcd_link = self.xkcd.make_link(xkcd["num"])

            embed = Embed(title=trans.get("MSG_XKCD",
                                          lang).format(xkcd["num"]),
                          description=filter_text(xkcd["safe_title"]))
            embed.set_image(url=xkcd["img"])
            embed.set_footer(
                text=trans.get("MSG_XKCD_SOURCE", lang).format(xkcd_link))

            await message.channel.send(embed=embed)

        # !joke (yo mama/chuck norris)
        elif startswith(prefix + "joke"):
            content = filter_text(self.joke.random_joke())

            embed = Embed(description=content)
            await message.channel.send(embed=embed)