简体   繁体   English

Discord 齿轮无法加载

[英]Discord cogs doesn't load

I am trying to run two different Discord Bots using a single python script using cogs.我正在尝试使用 cogs 使用单个 python 脚本运行两个不同的 Discord Bot。 But when I try to run the 2nd bot it throws an ImportError even-though I didn't use that specific Library.但是当我尝试运行第二个机器人时,它会抛出一个 ImportError——尽管我没有使用那个特定的库。 The reaction roles bot works fine without the anti spam bot.在没有反垃圾邮件机器人的情况下,反应角色机器人可以正常工作。 Here's my code.这是我的代码。 FYI I am working inside a Virtual Env.仅供参考,我在虚拟环境中工作。

main.py主文件

if __name__ == "__main__":
    try:
        reaction_role_bot = commands.Bot(command_prefix=config["reaction_role_bot"]["bot_prefix"], intents=discord.Intents.all())
        reaction_slash = SlashCommand(reaction_role_bot, sync_commands=True)
        reaction_role_bot.load_extension(f"cogs.{str(os.path.basename('cogs/reaction_roles.py')[:-3])}")
        
        anti_spam_bot = commands.Bot(command_prefix=config["anti_spam_bot"]["bot_prefix"], intents=discord.Intents.default())
        spam_slash = SlashCommand(anti_spam_bot, sync_commands=True)   
        anti_spam_bot.load_extension(f"cogs.{str(os.path.basename('cogs/anti_spam.py')[:-3])}")
        
        event_loop = asyncio.get_event_loop()
        event_loop.create_task(reaction_role_bot.run(config["reaction_role_bot"]["token"]))
        event_loop.create_task(anti_spam_bot.run(config["anti_spam_bot"]["token"]))
        event_loop.run_forever()
        
    except Exception as e:
        print(e)

anti_spam.py反垃圾邮件.py

import platform
import os

import discord
from discord.ext import commands

from antispam import AntiSpamHandler
from antispam.plugins import AntiSpamTracker, Options

class AntiSpamBot(commands.Cog):
    def __init__(self, client):
        self.client = client
        
        # Initialize the AntiSpamHandler
        self.client.handler = AntiSpamHandler(self.client, options=Options(no_punish=True))
        # 3 Being how many 'punishment requests' before is_spamming returns True
        self.client.tracker = AntiSpamTracker(self.client.handler, 3) 
        self.client.handler.register_extension(self.client.tracker)
        
    @commands.Cog.listener()
    async def on_ready(self):
        print("---------------------------------")
        print(f"Logged in as {str(self.client.user)}")
        print(f"Discord.py API version: {discord.__version__}")
        print(f"Python version: {platform.python_version()}")
        print(f"Running on: {platform.system()} {platform.release()} ({os.name})")
        await self.client.change_presence(status=discord.Status.idle, activity=discord.Game(name="Head of Security"))
        print("---------------------------------\n")
        
    # The code in this event is executed every time a valid commands catches an error
    @commands.Cog.listener()
    async def on_command_error(context, error):
        raise error
    
    @commands.Cog.listener()
    async def on_message(self, message):
        await self.client.handler.propagate(message)
        
        if self.client.tracker.is_spamming(message):
            await message.delete()
            await message.channel.send(f"{message.author.mention} has been automatically kicked for spamming.")
            await message.author.kick()
        
        await self.client.process_commands(message)
    
        
def setup(client):
    client.add_cog(AntiSpamBot(client))

Error错误

Extension 'cogs.anti_spam' raised an error: ImportError: cannot import name 'AsyncMock' from 'unittest.mock' (/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/mock.py)

I've no experiences using cogs and its bit confusing me.我没有使用齿轮的经验,这让我有点困惑。 Any kind of help would help me to sort this out!任何形式的帮助都会帮助我解决这个问题! Thanks in advance!提前致谢!

I do not believe this is a cog registration issue.我不相信这是一个齿轮注册问题。 I believe this is an import error from some of the dependencies in your cog file.我相信这是来自您的 cog 文件中的某些依赖项的导入错误。 I googled your error and found something similar, I recommend checking it out here for some more information.我用谷歌搜索了你的错误并发现了类似的东西,我建议在这里查看更多信息。

As a blanket statement, I would double check that you have mock installed, and that you're installing it on the version of Python that you think you're installing it on.作为一个全面的声明,我会仔细检查您是否安装了模拟,并且您正在将它安装在您认为要安装它的 Python 版本上。 It can get wonky if you have multiple python versions insealled.如果您安装了多个 python 版本,它可能会变得不稳定。

Also, on an unrelated note:: It is best to avoid running multiple bot instances in one python file, but I can help you do it the best way possible.另外,关于一个不相关的说明:最好避免在一个 python 文件中运行多个机器人实例,但我可以帮助您以最好的方式做到这一点。

For starters, you have to realize that Client.run is an abstraction of a couple of more lower level concepts.首先,您必须意识到Client.run是几个更底层概念的抽象。

There is Client.login which logs in the client and then Client.connect which actually runs the processing.Client.login登录客户端,然后Client.connect实际运行处理。 These are coroutines.这些是协程。

asyncio provides the capability of putting things in the event loop for it to work whenever it has time to. asyncio提供了将事物放入事件循环中的能力,以便它在有时间的时候工作。

Something like this eg像这样的东西,例如

loop = asyncio.get_event_loop()

async def foo():
  await asyncio.sleep(10)
  loop.close()

loop.create_task(foo())
loop.run_forever()

If we want to wait for something to happen from another coroutine, asyncio provides us with this functionality as well through the means of synchronisation via asyncio.Event.如果我们想等待另一个协程发生的事情,asyncio 也通过 asyncio.Event 同步的方式为我们提供了这个功能。 You can consider this as a boolean that you are waiting for:您可以将其视为您正在等待的布尔值:

e = asyncio.Event()
loop = asyncio.get_event_loop()

async def foo():
  await e.wait()
  print('we are done waiting...')
  loop.stop()

async def bar():
  await asyncio.sleep(20)
  e.set()

loop.create_task(bar())
loop.create_task(foo())
loop.run_forever() # foo will stop this event loop when 'e' is set to true
loop.close()

Using this concept we can apply it to the discord bots themselves.使用这个概念,我们可以将其应用于不和谐机器人本身。

import asyncio
import discord
from collections import namedtuple

# First, we must attach an event signalling when the bot has been
# closed to the client itself so we know when to fully close the event loop.

Entry = namedtuple('Entry', 'client event')
entries = [
  Entry(client=discord.Client(), event=asyncio.Event()),
  Entry(client=discord.Client(), event=asyncio.Event())
]

# Then, we should login to all our clients and wrap the connect call
# so it knows when to do the actual full closure

loop = asyncio.get_event_loop()

async def login():
  for e in entries:
    await e.client.login()

async def wrapped_connect(entry):
  try:
    await entry.client.connect()
  except Exception as e:
    await entry.client.close()
    print('We got an exception: ', e.__class__.__name__, e)
    entry.event.set()

# actually check if we should close the event loop:
async def check_close():
  futures = [e.event.wait() for e in entries]
  await asyncio.wait(futures)

# here is when we actually login
loop.run_until_complete(login())

# now we connect to every client
for entry in entries:
  loop.create_task(wrapped_connect(entry))

# now we're waiting for all the clients to close
loop.run_until_complete(check_close())

# finally, we close the event loop
loop.close()


声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM