You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord机器人Reddit表情包获取脚本故障求助

Discord机器人Reddit表情包功能修复方案

问题描述

跟着教程编写自定义Discord机器人,实现从Reddit获取随机表情包功能时遇到问题:运行主脚本无报错,但功能完全失效,PyCharm日志无反馈。通过打印语句排查,确定问题出在meme()函数(第18行)。

原代码

主脚本

import discord
from discord.ext import commands, tasks
import os
import asyncio
from itertools import cycle

bot = commands.Bot(command_prefix='.', intents=discord.Intents.all())

bot_statuses = cycle(["Status One", "Hello from Jimbo", "Status Code 123"])

@tasks.loop(seconds=5)
async def change_bot_status():
    await bot.change_presence(activity=discord.Game(next(bot_statuses)))

@bot.event
async def on_ready():
    print("Bot ready!")
    change_bot_status.start()


with open("token.txt") as file:
    token = file.read()

async def load():
    for filename in os.listdir('./cogs'):
        if filename.endswith('.py'):
            await bot.load_extension(f'cogs.{filename[:-3]}')

async def main():
    async with bot:
        await load()
        await bot.start(token)


asyncio.run(main())

Reddit脚本

import discord
from discord.ext import commands
from random import choice
import asyncpraw as praw


class Reddit(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.reddit = praw.Reddit(client_id="REDACTED", client_secret="REDACTED", user_agent="script:randommeme:v1.0 (by u/REDACTED)")
        print(type(self.reddit))

    @commands.Cog.listener()
    async def on_ready(self):
        print(f"{__name__} is ready!")

    @commands.command()
    async  def meme(self, ctx: commands.Context):

        subreddit = await self.reddit.subreddit("memes")
        posts_lists = []

        async for post in subreddit.hot(limit=40):
            if not post.over_18 and post.author is not None and any(post.url.endswith(ext) for ext in [".png", ".jpg", ".jpeg", ".gif"]):
                author_name = post.author.name
                posts_lists.append((post.url, author_name))
            if post.author is None:
                posts_lists.append((post.url, "N/A"))

            if posts_lists:

                random_post = choice(posts_list)

                meme_embed = discord.Embed(title="Random Name", description="Fetches random meme from r/memes", color=discord.Color.random())
                meme_embed.set_author(name=f"Meme requested by {ctx.author.name}", icon_url=ctx.author.avatar)
                meme_embed.set_image(url=random_post[0])
                meme_embed.set_footer(text=f"Post created by {random_post[1]}.", icon_url=None)
                await ctx.send(embed=meme_embed)

            else:
                await ctx.send("Unable to fetch post, try again later.")


    def cog_unload(self):
        self.bot.loop.create_task(self.reddit.close())


async def setup(bot):
    await bot.add_cog(Reddit(bot))

错误点分析及修复

  1. 变量名拼写错误

    • 定义的列表是posts_lists,但随机选择时写成了posts_list,会触发NameError。修复:统一变量名为posts_list(更符合命名习惯)。
  2. 逻辑位置错误

    • 发送表情包的代码放在了async for循环内部,会导致每遍历一个帖子就尝试发送一次,而非收集完所有符合条件的帖子后再随机选一个发送。修复:将判断列表是否为空、随机选帖、发送消息的代码移到循环外部。
  3. 条件判断逻辑漏洞

    • 当post.author为空时,没有检查帖子是否为图片链接,会导致非图片帖子被加入列表;且两个if条件没有互斥,可能导致重复添加。修复:用elif处理作者为空的情况,并同样检查图片格式。
  4. Avatar调用错误

    • ctx.author.avatar是Asset对象,直接作为icon_url参数会报错,需要使用ctx.author.avatar.url获取头像链接。
  5. AsyncPRAW初始化错误

    • 导入了asyncpraw但用praw.Reddit初始化,这会使用同步版本的PRAW,与异步环境冲突。修复:改用asyncpraw.Reddit初始化客户端。

修复后的Reddit脚本

import discord
from discord.ext import commands
from random import choice
import asyncpraw


class Reddit(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        # 使用asyncpraw正确初始化异步客户端
        self.reddit = asyncpraw.Reddit(
            client_id="REDACTED",
            client_secret="REDACTED",
            user_agent="script:randommeme:v1.0 (by u/REDACTED)"
        )
        print(type(self.reddit))

    @commands.Cog.listener()
    async def on_ready(self):
        print(f"{__name__} is ready!")

    @commands.command()
    async def meme(self, ctx: commands.Context):
        subreddit = await self.reddit.subreddit("memes")
        posts_list = []

        # 遍历帖子,收集所有符合条件的图片帖
        async for post in subreddit.hot(limit=40):
            # 检查是否为非NSFW、图片链接
            is_image = any(post.url.endswith(ext) for ext in [".png", ".jpg", ".jpeg", ".gif"])
            if not post.over_18 and is_image:
                if post.author is not None:
                    author_name = post.author.name
                else:
                    author_name = "N/A"
                posts_list.append((post.url, author_name))

        # 收集完成后再处理发送逻辑
        if posts_list:
            random_post = choice(posts_list)
            meme_embed = discord.Embed(
                title="Random Meme",
                description="Fetches random meme from r/memes",
                color=discord.Color.random()
            )
            # 使用avatar.url获取正确的头像链接,兼容无头像的情况
            meme_embed.set_author(
                name=f"Meme requested by {ctx.author.name}",
                icon_url=ctx.author.avatar.url if ctx.author.avatar else None
            )
            meme_embed.set_image(url=random_post[0])
            meme_embed.set_footer(text=f"Post created by {random_post[1]}.")
            await ctx.send(embed=meme_embed)
        else:
            await ctx.send("Unable to fetch post, try again later.")

    def cog_unload(self):
        self.bot.loop.create_task(self.reddit.close())


async def setup(bot):
    await bot.add_cog(Reddit(bot))

内容的提问来源于stack exchange,提问作者Monxer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 01:57:16