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))
错误点分析及修复
变量名拼写错误
- 定义的列表是
posts_lists,但随机选择时写成了posts_list,会触发NameError。修复:统一变量名为posts_list(更符合命名习惯)。
- 定义的列表是
逻辑位置错误
- 发送表情包的代码放在了
async for循环内部,会导致每遍历一个帖子就尝试发送一次,而非收集完所有符合条件的帖子后再随机选一个发送。修复:将判断列表是否为空、随机选帖、发送消息的代码移到循环外部。
- 发送表情包的代码放在了
条件判断逻辑漏洞
- 当
post.author为空时,没有检查帖子是否为图片链接,会导致非图片帖子被加入列表;且两个if条件没有互斥,可能导致重复添加。修复:用elif处理作者为空的情况,并同样检查图片格式。
- 当
Avatar调用错误
ctx.author.avatar是Asset对象,直接作为icon_url参数会报错,需要使用ctx.author.avatar.url获取头像链接。
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
相关产品推荐
相关产品推荐

