예제 #1
0
def detect_text(url: str) -> str:
    """Uses Google Cloud VisionAI"""

    try:
        # Download image from url
        # Vision library can take an URL, but this saves an invocation in case of an invalid link
        response = requests.get(url)

        # Convert data to image
        image_bytes = io.BytesIO(response.content)
        image = vision.types.Image(content=image_bytes.read())

    # Invalid URL provided
    except requests.exceptions.MissingSchema:
        raise ContentError("That's not an image? {0}{1}\n{2}".format(
            basic_emoji.get("Pepega"), basic_emoji.get("Clap"),
            basic_emoji.get("forsenSmug")))

    # Let VisionAI do its thing
    cloud_response = google_vision.text_detection(image=image)
    texts = cloud_response.text_annotations

    # Couldn't read anything
    if not texts:
        raise ContentError("Can't see shit! {0}".format(
            basic_emoji.get("forsenT")))

    # Return raw detected text
    return texts[0].description
예제 #2
0
    async def set_icon(self, ctx, emote: str = ""):
        """Change user's icon to emoji"""

        if len(emote) == 0:
            await ctx.send("No emote specified")
            await ctx.message.add_reaction(basic_emoji.get("Si"))

        # Find every Discord emote
        discord_emotes = re.findall(r"<:\w*:\d*>", ctx.message.content)

        # Unicode emojis compatible by default
        compatible = extract_emoji(ctx.message.content)

        # Filter foreign emotes
        for e in discord_emotes:
            for known in self.bot.emojis:
                if e == str(known):
                    compatible.append(e)

        # Remove duplicates
        compatible = list(set(compatible))

        # If user specified compatible custom emoji
        if len(compatible) == 1:
            self.user_icon[ctx.author.id] = str(compatible[0])
            await ctx.message.add_reaction("✅")

        elif len(compatible) == 0:
            await ctx.send("I can't use that emote " +
                           basic_emoji.get("Sadge"))

        else:
            await ctx.send("Too many emotes specified " +
                           basic_emoji.get("Pepega"))
예제 #3
0
    async def decide(self, ctx, *args):
        """Choose one option from a list"""

        # No arguments -> exit
        if not args:
            await ctx.send(
                "Decide between what? " + basic_emoji.get("Pepega") +
                basic_emoji.get("Clap") +
                "\nUse `;`, `:`, `,` or ` or `, to separate options.")
            await ctx.message.add_reaction(basic_emoji.get("Si"))
            return

        # Join arguments to one string
        raw = " ".join(str(i) for i in args)

        # Attempt to split it by any separator
        options = raw.split(";")
        if len(options) < 2:
            options = raw.split(":")
            if len(options) < 2:
                options = raw.split(",")
                if len(options) < 2:
                    options = raw.split(" or ")

        # Splitting failed
        if len(options) < 2:
            await ctx.send(
                "Separator not recognized, use `;`, `:`, `,` or ` or `, to separate options."
            )

        # Else send a result
        else:
            await ctx.send(random.choice(options))
예제 #4
0
    async def read(self, ctx, url: str = ""):
        """Detect text in image"""

        # Check whether user provided url or embedded image
        if not url and not ctx.message.attachments:
            await ctx.send("Read what? " + basic_emoji.get("Pepega") +
                           basic_emoji.get("Clap") + "\n" +
                           basic_emoji.get("forsenSmug"))
            await ctx.message.add_reaction(basic_emoji.get("Si"))
            return

        # Get url to the image
        if not url:
            url = ctx.message.attachments[0].url

        # Display status
        status = await ctx.send("Processing... " + basic_emoji.get("docSpin"))

        # Attempt to detect text
        try:
            text = detect_text(url)
        except ContentError as e:
            await status.delete()
            await ctx.send(e)
            return

        await status.delete()
        # Split into short enough segments (Discord's max message length is 2000)
        for segment in wrap(text, 1990):
            await ctx.send("```" + segment + "```")
예제 #5
0
    async def joke(self, ctx):
        """Display a random 'joke'"""

        url = "http://stupidstuff.org/jokes/joke.htm?jokeid={0}".format(random.randint(1, 3773))

        # Attempt to download webpage
        try:
            response = requests.get(url, headers)
            response.raise_for_status()
        except requests.HTTPError:
            fail = await ctx.send("Bad response (status code {0}) from {1})".format(response.status_code, url))
            await fail.add_reaction(basic_emoji.get("Si"))
            return

        # Look for a joke
        soup = BeautifulSoup(response.content, "html.parser")
        table = soup.find("table", attrs={"class": "scroll"})

        # If element not found
        if not table:
            fail = await ctx.send("Joke not found on {0}".format(url))
            await fail.add_reaction(basic_emoji.get("Si"))
            return

        for row in table.findAll("tr"):
            # Send string with empty lines removed (split into smaller parts in case it is >2000 characters long)
            for segment in wrap(str(row.text).replace("\n\n", "\n"), 1990):
                await ctx.send(segment)
예제 #6
0
async def select_video(bot: discord.ext.commands.Bot, ctx: discord.ext.commands.Context, query: str) -> str:
    """Extract Youtube URL, returns empty string if failed"""

    # If URL contained in argument
    if "youtube.com/watch?v=" in query or "youtu.be/" in query:
        # Assuming it's the first 'word' of argument
        return query.partition(" ")[0]

    # Else search youtube for video title
    else:
        try:
            videos = youtube_search(query)
        except ConnectionError:
            msg = await ctx.send(basic_emoji.get("hackerCD") + "HTTP error. " + basic_emoji.get("Sadge"))
            await msg.add_reaction(basic_emoji.get("Si"))
            return ""

        # 0 videos -> exit
        if len(videos) == 0:
            msg = await ctx.send("0 videos found. " + basic_emoji.get("Sadge"))
            await msg.add_reaction(basic_emoji.get("Si"))
            return ""

        # 1 video -> we have a winner
        elif len(videos) == 1:
            return "https://www.youtube.com/watch?v=" + videos[0][1]

        # Else let user to choose which one they meant
        else:
            # Only giving 5 choices max
            number_emojis = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣"]
            valid_numbers = []

            poll = ""
            i = 0

            # Iterate over all (5 at most) found videos, pair = ('title - channel' : 'video_id')
            for pair in videos:
                # Add title to message
                poll += number_emojis[i] + ". " + pair[0] + "\n"
                # Add valid option
                valid_numbers.append(number_emojis[i])
                i += 1

            # Display message with available videos
            msg = await ctx.send(poll)
            await add_choices_message(msg, len(valid_numbers), cancellable=True)

            # Wait for user to choose
            choice = await wait_for_choice(bot, ctx.author, msg, valid_numbers, cancellable=True)

            await msg.delete()

            # Cancelled or timed out
            if choice <= 0:
                return ""

            return "https://www.youtube.com/watch?v=" + videos[choice - 1][1]
예제 #7
0
    async def pause(self, ctx):
        """Pause current song"""

        session = self.sessions[ctx.guild.id]

        if session.vc.pause():
            msg = await ctx.send("Nothing is playing.")
            await msg.add_reaction(basic_emoji.get("Si"))

        else:
            await ctx.send(
                basic_emoji.get("residentCD") + " Paused " +
                basic_emoji.get("Okayga"))
예제 #8
0
    async def roll(self, ctx, num: str = "100"):
        """Roll a dice"""

        # Default string for invalid input
        result = "No, I don't think so. " + basic_emoji.get("forsenSmug")

        # Parse input
        if num.isnumeric():
            # Roll dice
            result = str(random.randint(1, int(num)))
        else:
            await ctx.message.add_reaction(basic_emoji.get("Si"))

        # Display result
        await ctx.send(result)
예제 #9
0
    async def markov(self, ctx, *, string: str = ""):
        """Generate a Markov chain sequence"""

        # Load model if not loaded
        if self.markov_model is None:
            # Decrypt JSON file
            key = os.getenv("MARKOV_MODEL_KEY")
            pyAesCrypt.decryptFile("markov_model.json.aes",
                                   "markov_model.json", key)
            # Load model from JSON (expects str, not dict)
            with open("markov_model.json") as f:
                self.markov_model = markovify.Text.from_json(
                    json.dumps(json.load(f)))

        # Generate sentence
        try:
            sentence = self.markov_model.make_sentence_with_start(
                beginning=random.choice(string.split(" ")),
                tries=1000,
                min_words=20)
        except (markovify.text.ParamError, KeyError):
            sentence = self.markov_model.make_short_sentence(max_chars=2000,
                                                             min_chars=150,
                                                             tries=1000)

        # Return sentence
        if sentence:
            await ctx.send(sentence)
        else:
            msg = await ctx.send("Failed generating sentence.")
            await msg.add_reaction(basic_emoji.get("Si"))
예제 #10
0
    async def chan(self, ctx, board: str = "", arg: str = ""):
        """Display random post (image in spoiler)"""

        # If no board specified, or random one -> choose random board
        if not board or board.lower() == "random":
            board_list = [
                'a', 'b', 'c', 'd', 'e', 'f', 'g', 'gif', 'd', 'h', 'hr', 'k',
                'm', 'o', 'p', 'r', 's', 't', 'u', 'v', 'vg', 'w', 'wg', 'i',
                'ic', 'r9k', 'cm', 'hm', 'y', '3', 'adv', 'an', 'cgl', 'ck',
                'co', 'diy', 'fa', 'fit', 'hc', 'int', 'jp', 'lit', 'mlp',
                'mu', 'n', 'po', 'pol', 'sci', 'soc', 'sp', 'tg', 'toy', 'trv',
                'tv', 'vp', 'wsg', 'x'
            ]
            board = random.choice(board_list)

        # Attempt to download board
        try:
            b = basc_py4chan.Board(board)
            threads = b.get_all_threads()

        # Invalid board specified (library uses requests)
        except requests.exceptions.HTTPError:
            msg = await ctx.send("`/{0}/` doesn't exist.".format(board))
            await msg.add_reaction(basic_emoji.get("Si"))
            return

        result = ""
        post = None

        # Finding a post with text
        if arg.lower() == "text" or arg.lower() == "txt":
            # Try a random one until successful
            while not post or not post.text_comment:
                thread = random.choice(threads)
                post = random.choice(thread.posts)
                result = post.text_comment

        # Finding a post with image
        elif arg.lower() == "image" or arg.lower() == "img":
            while not post or not post.has_file:
                thread = random.choice(threads)
                post = random.choice(thread.posts)
                # Put image in a spoiler
                result = "|| {0} ||\n{1}".format(post.file_url,
                                                 post.text_comment)

        # If no option specified -> find a post with text, image optional
        else:
            while not post or not post.text_comment:
                thread = random.choice(threads)
                post = random.choice(thread.posts)
                if post.has_file:
                    result = "|| {0} ||\n{1}".format(post.file_url,
                                                     post.text_comment)
                else:
                    result = post.text_comment

        # Split into smaller parts if a post is too long (>2000 characters)
        for segment in wrap(result, 1990):
            await ctx.send(segment)
예제 #11
0
async def verbose_garfield(ctx, date) -> None:
    """Send a Garfield strip, with status notification"""

    status = await ctx.send(
        basic_emoji.get("hackerCD") + " Searching for Garfield strip " +
        basic_emoji.get("docSpin"))

    try:
        comic = garfield_strip(date)
    except GarfieldError as e:
        await status.delete()
        await ctx.send(e)
        return

    await status.delete()
    await ctx.send(comic)
예제 #12
0
    async def rand_date(self, ctx):
        """Display random Garfield strip + interesting fact about that day"""
        date = random_date(datetime.datetime(1978, 6, 19),
                           datetime.datetime.utcnow())

        await verbose_garfield(ctx, date)

        status = await ctx.send("Looking up an interesting fact... " +
                                basic_emoji.get("docSpin"))
        msg = "This comic came out in " + custom_strftime("%B {S}, %Y",
                                                          date) + "."

        # Try to find an interesting fact
        try:
            fact = get_day_fact(date)

        # Error -> stop
        except WikipediaError as e:
            await status.delete()
            await ctx.send(msg + e.message)
            return

        await status.delete()
        response = await ctx.send(msg + " Also on this day in " + fact)
        await response.add_reaction(random.choice(scoots_emoji))
예제 #13
0
    async def ping(self, ctx):
        """Displays time delta between Discord message and command invocation"""

        ms = (datetime.utcnow() - ctx.message.created_at.replace(tzinfo=None)
              ).total_seconds() * 1000
        await ctx.send(
            basic_emoji.get("Pepega") + " 🏓 Pong! `{0}ms`".format(int(ms)))
예제 #14
0
    async def weather(self, ctx, *args):
        """Get weather information"""

        # Default location
        location = "Prague"

        if args:
            location = " ".join(str(i) for i in args)

        url = ("http://api.openweathermap.org/data/2.5/weather?q=" + location +
               "&units=metric&lang=en&appid=" + WEATHER_TOKEN)
        res = requests.get(url).json()
        if str(res["cod"]) == "200":
            description = "Weather in " + res["name"] + " , " + res["sys"][
                "country"]
            embed = discord.Embed(title="Weather", description=description)
            image = "http://openweathermap.org/img/w/" + res["weather"][0][
                "icon"] + ".png"
            embed.set_thumbnail(url=image)
            weather = res["weather"][0]["main"] + " (" + res["weather"][0][
                "description"] + ") "
            temp = str(res["main"]["temp"]) + "°C"
            feels_temp = str(res["main"]["feels_like"]) + "°C"
            humidity = str(res["main"]["humidity"]) + "%"
            wind = str(res["wind"]["speed"]) + "m/s"
            clouds = str(res["clouds"]["all"]) + "%"
            visibility = str(
                res["visibility"] /
                1000) + " km" if "visibility" in res else "no data"
            embed.add_field(name="Weather", value=weather, inline=False)
            embed.add_field(name="Temperature", value=temp, inline=True)
            embed.add_field(name="Feels like", value=feels_temp, inline=True)
            embed.add_field(name="Humidity", value=humidity, inline=True)
            embed.add_field(name="Wind", value=wind, inline=True)
            embed.add_field(name="Clouds", value=clouds, inline=True)
            embed.add_field(name="Visibility", value=visibility, inline=True)
            await ctx.send(embed=embed)
        elif str(res["cod"]) == "404":
            msg = await ctx.send("Location not found.")
            await msg.add_reaction(basic_emoji.get("Sadge"))
        elif str(res["cod"]) == "401":
            msg = await ctx.send("API key broke, have a nice day.")
            await msg.add_reaction(basic_emoji.get("Si"))
        else:
            await ctx.send("Location not found! " + basic_emoji.get("Sadge") +
                           " (" + res["message"] + ")")
예제 #15
0
    async def skip(self, ctx):
        """Play next song in queue"""

        session = self.sessions[ctx.guild.id]

        if not session.next_song():
            msg = await ctx.send("Nothing is playing.")
            await msg.add_reaction(basic_emoji.get("Si"))
예제 #16
0
    async def stop(self, ctx):
        """Stop playback"""

        session = self.sessions[ctx.guild.id]

        if not session.stop():
            msg = await ctx.send("Nothing is playing.")
            await msg.add_reaction(basic_emoji.get("Si"))
예제 #17
0
파일: main.py 프로젝트: c0rexx/pepek-bot
async def on_command_error(ctx, error):
    """Executed when an exception is raised"""

    # Unknown command
    if isinstance(error, commands.CommandNotFound):
        await ctx.message.add_reaction(basic_emoji.get("Si"))
        await ctx.send("{0}📣 COMMAND NOT FOUND".format(
            basic_emoji.get("Pepega")))

    # Limited command in DMs
    elif isinstance(error, commands.errors.NoPrivateMessage):
        await ctx.message.add_reaction(basic_emoji.get("Si"))
        await ctx.send("Not available in DMs.")

    # Unescaped quotes
    elif isinstance(error, commands.errors.UnexpectedQuoteError):
        await ctx.message.add_reaction(basic_emoji.get("Si"))
        await ctx.send(
            "{0}📣 UNEXPECTED QUOTE ERROR\nUse `\\` to escape your quote(s) {1}"
            .format(basic_emoji.get("Pepega"),
                    basic_emoji.get("forsenScoots")))

    # Command cooldown
    elif isinstance(error, commands.CommandOnCooldown):
        await ctx.message.add_reaction(basic_emoji.get("Si"))
        await ctx.send("That command is on cooldown.")

    else:
        raise error
예제 #18
0
    async def forceplay(self, ctx, *args):
        """Put song in front of queue"""

        session = self.sessions[ctx.guild.id]

        # No arguments -> exit
        if not args:
            await ctx.send("Play what? " + basic_emoji.get("Pepega") +
                           basic_emoji.get("Clap") + "\n" +
                           basic_emoji.get("forsenSmug"))
            await ctx.message.add_reaction(basic_emoji.get("Si"))
            return

        if session.vc is None:
            await ctx.send("Nothing is queued to skip in front of " +
                           basic_emoji.get("Pepega") +
                           basic_emoji.get("Clap") + "\nUse `p.play`")
            await ctx.message.add_reaction(basic_emoji.get("Si"))
            return

        # Extract youtube video url
        arg = " ".join(str(i) for i in args)
        url = await select_video(self.bot, ctx, arg)

        # No video selected by user
        if not url:
            return

        session.forceplay(url)
        await ctx.send("Song inserted to the front of the queue.")
예제 #19
0
def detect_text(url: str) -> str:
    """Uses Google Cloud VisionAI"""

    # Check if link is an image
    mimetype, encoding = mimetypes.guess_type(url)
    if not mimetype or not mimetype.startswith("image"):
        raise ContentError("That's not an image? {0}{1}\n{2}".format(
            basic_emoji.get("Pepega"), basic_emoji.get("Clap"),
            basic_emoji.get("forsenSmug")))

    # Download image
    try:
        response = requests.get(url)
        image_bytes = io.BytesIO(response.content)
        image = vision_v1.types.Image(content=image_bytes.read())

    except requests.exceptions.MissingSchema:
        raise ContentError("That's not an image? {0}{1}\n{2}".format(
            basic_emoji.get("Pepega"), basic_emoji.get("Clap"),
            basic_emoji.get("forsenSmug")))

    # Read image
    cloud_response = google_vision.text_detection(image=image)
    texts = cloud_response.text_annotations

    # Couldn't read anything
    if not texts:
        raise ContentError("Can't see shit! {0}".format(
            basic_emoji.get("forsenT")))

    # Return raw detected text
    return texts[0].description
예제 #20
0
    async def fact(self, ctx, arg1: str = "", arg2: str = ""):
        """Displays a random interesting fact"""

        # No date provided -> use today's date
        if not arg1 or not arg2:
            date = datetime.datetime.today()
            msg = "On this day in the year "

        # Invalid date input -> stop
        elif not arg1.isnumeric() or not arg2.isnumeric():
            await ctx.send(
                "That's not even a numeric date. Try something like '9 11'.")
            await ctx.message.add_reaction(basic_emoji.get("Si"))
            return

        # Attempt to parse date input
        else:
            try:
                date = datetime.date(2000, int(arg1), int(arg2))
                msg = "On " + custom_strftime("%B {S}", date) + " in the year "
            except ValueError:
                await ctx.send(
                    "No..? You must be using the wrong calendar. Try 'Month Day'."
                )
                await ctx.message.add_reaction(basic_emoji.get("Si"))
                return

        status = await ctx.send("Looking up an interesting fact... " +
                                basic_emoji.get("docSpin"))

        # Try to find an interesting fact
        try:
            fact = get_day_fact(date)

        # Error -> stop
        except WikipediaError as e:
            await status.delete()
            await ctx.send(e)
            return

        await status.delete()
        response = await ctx.send(msg + fact)
        await response.add_reaction(random.choice(scoots_emoji))
예제 #21
0
    async def repeat(self, ctx):
        """Toggle repeat"""

        session = self.sessions[ctx.guild.id]

        if not session.song:
            msg = await ctx.send("Nothing is playing.")
            await msg.add_reaction(basic_emoji.get("Si"))
            return

        session.repeat = not session.repeat
        await ctx.send("Repeat set to `{0}`".format(session.repeat))
예제 #22
0
    async def clear(self, ctx):
        """Clear song queue"""

        session = self.sessions[ctx.guild.id]

        if not session.song_queue:
            await ctx.send("Queue already empty " +
                           basic_emoji.get("forsenScoots"))
            return

        session.song_queue = []
        await ctx.send("Queue emptied.")
예제 #23
0
    async def garf(self, ctx, arg1: str = "", arg2: str = "", arg3: str = ""):
        """Get specific Garfield comic"""

        # Parsing input
        if not arg1 or not arg2 or not arg3:
            await ctx.send(
                basic_emoji.get("forsenT") +
                " Date looks like 'Year Month Day', ie. '2001 9 11'.")
            await ctx.message.add_reaction(basic_emoji.get("Si"))
            return

        if not arg1.isnumeric() or not arg2.isnumeric() or not arg3.isnumeric(
        ):
            await ctx.send(
                basic_emoji.get("forsenT") +
                " That's not even a numeric date.")
            await ctx.message.add_reaction(basic_emoji.get("Si"))
            return

        # Construct date
        try:
            date = datetime.datetime(int(arg1), int(arg2), int(arg3))
        except ValueError:
            await ctx.send(
                basic_emoji.get("forsenSmug") +
                " No..? You must be using the wrong calendar.")
            await ctx.message.add_reaction(basic_emoji.get("Si"))
            return

        # Send comic strip
        await verbose_garfield(ctx, date)
예제 #24
0
    async def decide(self, ctx, *args):
        """Choose one option from a list"""

        separators = [';', ':', ',', ' or ', ' ']

        hint = ""
        # Add separators in reverse priority
        for sep in reversed(separators[1:]):
            hint += f"`{sep}`, "
        # Add "or" in front of last separator
        hint += f"or `{separators[0]}`"

        # No arguments -> exit
        if not args:
            await ctx.send("Decide between what? " +
                           basic_emoji.get("Pepega") +
                           basic_emoji.get("Clap") + "\nUse " + hint +
                           " to separate options.")
            await ctx.message.add_reaction(basic_emoji.get("Si"))
            return

        # Join arguments to one string
        raw = " ".join(str(i) for i in args)

        # Attempt to split it by any separator
        options = []
        for separator in separators:
            options = raw.split(separator)
            if len(options) > 1:
                break

        # Splitting failed, show hint
        if len(options) < 2:
            await ctx.send(
                f"Separator not recognized, use one of {hint} to separate options."
            )

        # Else send a result
        else:
            await ctx.send(random.choice(options))
예제 #25
0
    async def translate(self, ctx, *, arg: str = ""):
        """Translate text"""

        # No text entered -> nothing to translate
        if not arg:
            await ctx.send("Translate what? " + basic_emoji.get("Pepega") +
                           basic_emoji.get("Clap") + "\n" +
                           basic_emoji.get("forsenSmug"))
            await ctx.message.add_reaction(basic_emoji.get("Si"))
            return

        # Split into ["first_word", "the_rest of the query"]
        query = arg.split(" ", 1)

        # If first word is an ISO639-1 language code, translate to that language
        if query[0] in googletrans.LANGUAGES:
            result = translator.translate(query[1], dest=query[0])

        # Otherwise translate to english by default
        else:
            result = translator.translate(arg, dest="en")

        # Using .lower() because for example chinese-simplified is 'zh-cn', but result.src returns 'zh-CN' (so dumb)
        header = "Translated from `{0}` {1} to `{2}` {3}".format(
            googletrans.LANGUAGES.get(result.src.lower()),
            code_to_country(result.src.lower()),
            googletrans.LANGUAGES.get(result.dest.lower()),
            code_to_country(result.dest.lower()))

        # Split into parts in case of very long translation
        first_iter = True
        for segment in wrap(result.text, 1950):
            # Send header together with the first part
            if first_iter:
                await ctx.send("{0}\n```{1}```".format(header, segment))
                first_iter = False
            # Send the rest parts standalone
            else:
                await ctx.send("```" + segment + "```")
예제 #26
0
    async def wolfram(self, ctx, *args):
        """Ask WolframAlpha a question"""

        # No arguments -> exit
        if not args:
            await ctx.send("What? " + basic_emoji.get('Pepega') +
                           basic_emoji.get('Clap'))
            await ctx.message.add_reaction(basic_emoji.get('Si'))
            return

        # Parse query into url-friendly format (for example replaces spaces with '%2')
        query = urllib.parse.quote_plus(" ".join(str(i) for i in args))

        # Send query (with some extra arguments regarding result formatting)
        url = "http://api.wolframalpha.com/v1/simple?appid={0}&i={1}&background=36393f&foreground=white&timeout=30".format(
            WOLFRAM_APPID, query)

        async with ctx.typing():
            # Attempt to download result
            try:
                response = requests.get(url)
                response.raise_for_status()

            # Invalid query / timeout / something else
            except requests.HTTPError:
                fail = await ctx.send("Bad response (status code: {0})".format(
                    response.status_code))
                await fail.add_reaction(basic_emoji.get("Si"))
                return

            # I want to send an image (generated by WolframAlpha), not embed a link (image would be regenerated if user clicked it + it would contain app_id)
            # And because discord.File has to open the file, I first save the file, then embed it, then delete it...
            # And to avoid overwriting during simultaneous calls, use the query's hash as the filename
            filename = "tmp" + str(hash(query))
            open(filename, "wb").write(response.content)

            await ctx.send(file=discord.File(filename, filename="result.png"))

            os.remove(filename)
예제 #27
0
    async def playing(self, ctx):
        """Display currently playing song"""

        session = self.sessions[ctx.guild.id]

        if not session.song:
            msg = await ctx.send("Nothing is playing.")
            await msg.add_reaction(basic_emoji.get("Si"))

        else:
            title = await ctx.send(
                random.choice(dance_emoji) + " 🎶 Now playing 🎶: " +
                session.song)
            await title.add_reaction(random.choice(dance_react))
예제 #28
0
def get_day_fact(date: datetime.datetime) -> str:
    # Try to find an interesting fact
    try:
        raw = wikipedia.page(date.strftime("%B") + " " +
                             str(date.day)).section("Events")
        # Library returns long string or None
        facts = raw.splitlines()

    # Returned None -> error -> stop
    except AttributeError:
        raise WikipediaError("No facts found on wikipedia.com/wiki/" +
                             date.strftime("%B") + "_" + str(date.day) + " " +
                             basic_emoji.get("Pepega"))

    # Returned empty string
    if not facts:
        raise WikipediaError("No facts found on wikipedia.com/wiki/" +
                             date.strftime("%B") + "_" + str(date.day) + " " +
                             basic_emoji.get("Pepega"))

    # Choose a random line (each line is 1 fact)
    else:
        return random.choice(facts)
예제 #29
0
    async def tomorrow(self, ctx):
        """Display when tomorrow's Garfield comic comes out"""

        # Calculate timedelta
        delta = next_garfield()
        hours = delta.seconds // 3600 % 24
        minutes = delta.seconds // 60 % 60
        seconds = delta.seconds - hours * 3600 - minutes * 60

        # If next garfield actually comes out today, simply add 24 hours for tomorrow's
        now = datetime.datetime.utcnow()
        # TODO: Add summer/wintertime offset
        if now.hour < 6 or (now.hour == 6 and now.minute < 7):
            hours += 24

        await ctx.message.add_reaction(basic_emoji.get("Si"))
        await ctx.send(
            "You will have to be patient, tomorrow's comic comes out in {0}:{1}:{2}."
            .format(
                str(hours).zfill(2),
                str(minutes).zfill(2),
                str(seconds).zfill(2)))
예제 #30
0
    async def created(self, ctx, user: Union[nextcord.Member, nextcord.User,
                                             nextcord.ClientUser, str, None]):
        """Display account creation date"""

        if isinstance(user, str):
            await ctx.send("Try a user's tag instead " +
                           basic_emoji.get("Okayga"))
            return

        if user is None:
            user_id = ctx.author.id
            msg = "Your account"
        else:
            user_id = user.id
            msg = "That account"

        # Decode user's ID
        binary = str(bin(user_id)[2:])
        unix_binary = binary[:len(binary) - 22]
        unix = (int(unix_binary, 2) + 1420070400000) // 1000

        time = datetime.utcfromtimestamp(unix).strftime("%Y-%m-%d %H:%M:%S")

        await ctx.send("{0} was created at {1} UTC".format(msg, time))