Skip to content

ERROR: Unrecoverable exception thrown when parsing ./help_text_gen.py! This should NEVER happen. If encountered, please open an issue: https://github.com/PyCQA/isort/issues/new #1593

@ThatXliner

Description

@ThatXliner
ERROR: Unrecoverable exception thrown when parsing ./help_text_gen.py! This should NEVER happen.
If encountered, please open an issue: https://github.com/PyCQA/isort/issues/new
Traceback (most recent call last):
  File "/Users/bryanhu/.pyenv/versions/3.6.0/bin/isort", line 8, in <module>
    sys.exit(main())
  File "/Users/bryanhu/.pyenv/versions/3.6.0/lib/python3.6/site-packages/isort/main.py", line 953, in main
    for sort_attempt in attempt_iterator:
  File "/Users/bryanhu/.pyenv/versions/3.6.0/lib/python3.6/site-packages/isort/main.py", line 947, in <genexpr>
    for file_name in file_names
  File "/Users/bryanhu/.pyenv/versions/3.6.0/lib/python3.6/site-packages/isort/main.py", line 100, in sort_imports
    **kwargs,
  File "/Users/bryanhu/.pyenv/versions/3.6.0/lib/python3.6/site-packages/isort/api.py", line 303, in sort_file
    with io.File.read(filename) as source_file:
AttributeError: type object 'File' has no attribute 'read'

My code:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Initial author: Bryan Hu .

@ThatXliner .

Version: v0.1.0

A discord bot for `chat@vcs (Discord)`

Because we need it.

"""
import asyncio
import json
import random
import sys
import datetime
import aiohttp
import discord
from bs4 import BeautifulSoup

# from rich.traceback import install
# install(theme="monokai")  # For better error messages

# from typing import Iterable

# NOTE: In the future, we'll be using discord.Role instead of IDs

# Intent chooser
intents = discord.Intents.all()
client = discord.Client(intents=intents)


PREFIX = "bb"
TOKEN = "SECRET"

with open("help_text.json", mode="rt") as f:
    HELP_TEXT = json.loads(f.read())


@client.event
async def on_ready() -> None:
    print(
        "We have logged in as {0.user}. All systems go!".format(client), file=sys.stderr
    )


@client.event
async def on_message(message: discord.Message) -> None:

    try:
        # Shortened versions
        CHANNEL: discord.TextChannel = message.channel
        SEND = CHANNEL.send  # NOTE: Is it preferred to do `SEND` or `CHANNEL.send`
        GUILD: discord.Guild = message.guild
        AUTHOR: discord.Member = message.author
        if AUTHOR.bot:  # It is a bot
            return
        STATUS_UPDATE_CHANNEL = GUILD.get_channel(766077636975788072)
        LOG_CHANNEL = GUILD.get_channel(773686991212380161)

        # Useful constants
        MENTIONED: bool = False
        _ = GUILD.get_role
        ROLES = {  # These are in here because of dynamicism
            "Role #1": _(766780249589153873),
            "Role #2": _(766780358908837898),
            "Role #3": _(766780549930156042),
            "Role #4": _(766780732089434162),
            "Role #5": _(766780860157919232),
            "Role #6": _(766781042916196382),
            "Verify | Pending": _(766066811963179029),
            "Verify | In progress": _(766110909755293746),
            "Verified": _(766057652400160818),
            "Administrator": _(766032588829491200),
            "Assistants": _(766063222360375326),
            "Moderators": _(766030895215542303),
        }
        NEED_VERIFY = [
            ROLES["Role #1"],
            ROLES["Role #2"],
            ROLES["Role #3"],
            ROLES["Role #4"],
            ROLES["Role #5"],
            ROLES["Role #6"],
            ROLES["Verify | Pending"],
            ROLES["Verify | In progress"],
        ]

        IS_PREVILEGED: bool = AUTHOR.roles in (
            ROLES["Administrator"],
            ROLES["Assistants"],
            ROLES["Moderators"],
        )

        async def command_delete(messages: int) -> None:
            await CHANNEL.purge(limit=messages)
            await SEND(
                f"I have deleted {int(lexed_message[1])} messages! :partying_face:",
                delete_after=1,
            )

        async def command_verify() -> None:
            if IS_PREVILEGED:
                try:
                    person_to_verify: discord.Member = GUILD.get_member(int(arg2[3:-1]))
                except IndexError:
                    await SEND(
                        "You must enter the @Mention of the person to verify. ;-;"
                    )
                else:
                    if (
                        person_to_verify is not None
                        and person_to_verify in CHANNEL.members
                    ):
                        # Add the "Verified" role
                        await person_to_verify.add_roles(
                            ROLES["VERIFIED"],
                            reason="Automatic role verification.",
                        )

                        # Remove the "need verification" roles
                        await person_to_verify.remove_roles(
                            [
                                role
                                for role in person_to_verify.roles
                                if role in NEED_VERIFY
                            ],
                            reason="Automatic role verification.",
                        )
                        await SEND("Done! Updating status message...")

                        # Update the status message
                        await STATUS_UPDATE_CHANNEL.send(
                            f"STATUS UPDATE:\n{person_to_verify.mention} : Verified"
                        )

                    else:
                        await SEND("That person does not exist in this server.")
            else:
                await SEND(
                    f"Sorry, {AUTHOR.mention},"
                    " you don't have permission to use that."
                )

        async def command_meme() -> None:
            provider = random.choice(("imgflip", "memedroid"))
            async with aiohttp.ClientSession() as session:
                if provider == "imgflip":
                    async with session.get(
                        f"https://imgflip.com/?page={random.randint(0,10)}"
                    ) as response:
                        html = BeautifulSoup(await response.text(), features="lxml")
                        image_url = (
                            "https:"
                            + random.choice(
                                html.find_all("img", attrs={"class": "base-img"})
                            )["src"]
                        )
                elif provider == "memedroid":
                    async with session.get("https://www.memedroid.com/") as response:
                        soup = BeautifulSoup(await response.text(), features="lxml")
                        image_url = random.choice(
                            [
                                str(img.get("src"))
                                for img in soup.find_all(class_="img-responsive")
                                if str(img.get("src")).startswith("https://")
                            ]
                        )
                await SEND(image_url)

        async def command_help() -> None:
            if arg2 is None:
                await SEND(HELP_TEXT["main"])
            else:
                command_to_help = HELP_TEXT.get(arg2)
                await SEND(
                    command_to_help
                    if command_to_help is not None
                    else "Invalid help choice ;-;"
                )

        # Message parsing
        _ = message.content
        if _.lstrip().startswith(PREFIX):
            _ = _[len(PREFIX) :]  # If this fails (i.e. IndexError) we'll catch it
            MENTIONED = True
        elif client.user in message.mentions:
            _ = _.replace(f"<@!{client.user.id}>", "")  # Pinging the bot
            MENTIONED = True

        # Main driver point
        if MENTIONED:
            # NOTE(ThatXliner): Should we put this in "message parsing"?
            lexed_message = _.split()
            try:
                arg2 = lexed_message[1]
            except IndexError:
                arg2 = None

            # We do the following for case insensitivity
            COMMAND: str = lexed_message[0].lower()  # Case insensitive

            # The reason why we make our own message parsing system
            # is because of *control*. I want full control of
            # parsing, etc because I might make this into a
            # framework...

            # COMMAND: Ping
            if COMMAND == "ping":
                await SEND("pong")

            # COMMAND: Delete
            elif COMMAND in {"!", "del", "delete"}:
                if arg2 is None:
                    arg2 = 0
                await command_delete(int(arg2) + 1)

            # COMMAND: Verify
            elif COMMAND in {"v", "verify"}:
                await command_verify()

            # COMMAND: Help
            elif COMMAND in {"help", "h"}:
                await command_help()

            # COMMAND: Meme
            elif COMMAND in {"m", "meme", "memes"}:
                await command_meme()
            else:
                await SEND("Invalid command ;-;")

    except IndexError as e:  # `CLEAN_MESSAGE = CLEAN_MESSAGE[1:]` from 85:13 failed
        print(e)
        await SEND("mhm?")

    except Exception as e:
        await LOG_CHANNEL.send("Oh no, something went wrong. :boom: . Exception:")
        await LOG_CHANNEL.send(e)
        await LOG_CHANNEL.send(f"MESSAGE: {message.content}")
        print(f"MESSAGE: {message.content}")
        raise e


loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(client.start(TOKEN))
except KeyboardInterrupt:
    loop.run_until_complete(client.logout())
    # cancel all tasks lingering
    with open("logs.log") as f:
        f.write(f.read() + f"\n---{datetime.date.today()}---")  # Appends date to logs
finally:
    loop.close()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions