如何循环消息

Posted

技术标签:

【中文标题】如何循环消息【英文标题】:How To Loop Through Messages 【发布时间】:2021-10-13 09:55:30 【问题描述】:

我被卡住了,一直在查看文档,但没有什么清楚地跳出来。 我要做的是让我的机器人在指定范围内加载消息,并计算特定定义短语的出现次数。

例如。 短语=“货车” !phrase 5 - 返回过去 5 天内的所有消息 然后返回过去 5 天内“wagons”被提及的次数

""" Simple program for the bot to return information about the guild """
import os
import datetime as dt
import discord
from discord.ext import commands

from dotenv import load_dotenv

load_dotenv()  # loads the encapsulated values from the .env file

# Declaration of Encapsulated Variables
TOKEN = os.getenv('BOT_TOKEN')
TESTING_GUILD_KEY = os.getenv('TESTING_GUILD_KEY')
TESTING_CHANNEL = os.getenv('TESTING_CHANNEL')

# Declaration of Discord.py Intents
intents = discord.Intents.default()  # Turns on the connection
intents.members = True  # Ensures the member list will be updated properly
client = discord.Client(intents=intents)  # captures the connection to discord

# Declaration of Discord.py Variables
guild_key = client.get_guild(int(TESTING_GUILD_KEY))
bot = commands.Bot(command_prefix='!')


@client.event
async def on_message(message):
    """ Defines events for which the bot will return information by the user typing commands """
    all_members = get_all_members()  # has all the members visible to the bot

    # Sends to the channel the event is called, the total amount of users in the guild
    if message.content.find("!userCount") != -1:
        await message.channel.send(f"""We currently have len(all_members) members in the server""")
    # Sends to the channel the event is called, a list of users currently in the guild
    elif message.content.startswith('!member'):
        await message.channel.send(f"""The current member list is: \n""")
        for each_member in all_members:
            await message.channel.send(f"""- each_member""")


def get_all_members():
    """ Returns A list of users currently in the server """
    list_of_members = []  # Declaration of Empty Dictionary

    # Declaration of logic to print out each user in the guild
    for each_guild in client.guilds:
        for each_member in each_guild.members:
            list_of_members.append(each_member)  # adds the member
    return list_of_members


# @client.event
# async def keyword(ctx, word):
#     channel = client.get_channel(int(TESTING_CHANNEL))
#     messages = await ctx.channel.history(limit=200).flatten()
#     count = 0
#
#     for msg in messages:
#         if word in msg.content:
#             count += 1
#             print(count)


@bot.command()
async def something(ctx):
    pass


@bot.command()
async def find(ctx, days: int = None, phrase: str = None):
    if days and phrase:
        after_date = dt.datetime.utcnow() - dt.timedelta(days=days)
        # limit can be changed to None but that this would make it a slow operation.
        messages = await ctx.channel.history(limit=10, oldest_first=True, after=after_date).flatten()
        # loop each message to check for phrase
        for message in messages:
            if phrase in message.content:
                print(message)
    else:
        await ctx.send("please enter the number of days wanted")


client.run(TOKEN)

我认为我使用短语功能很接近,但是它无法正常工作。不确定我是否必须打开意图,或者代码中是否缺少某些内容。 感谢您的帮助!

【问题讨论】:

【参考方案1】:

您没有使用discord.ext.commands。请阅读 this example 以获取从文档中获取的示例机器人。

from discord.ext import commands

bot = commands.Bot(command_prefix='$')

@bot.command()
async def something(ctx):
    pass

bot.run("TOKEN")

您使用名为daysint 参数创建一个命令,然后从调用命令的时间开始获取时间增量。

还要检查每条消息是否包含phrase

!find 4 long text to check 打印过去 4 天的所有消息以及该短语。

!find 14 long text to check 打印过去 14 天的所有消息以及该短语。

# import datatime as dt

@bot.command()
async def find(ctx, days: int = None, *, phrase:str = None):
    if not (days or phrase):
        return await ctx.send("Please enter a phrase and days")
        
    if days and phrase:
        after_date = dt.datetime.utcnow()-dt.timedelta(days=days)
        # limit can be changed to None but that this would make it a slow operation.
        messages = await ctx.channel.history(limit=10, oldest_first=True, after=after_date).flatten()
        # loop each message to check for phrase
        for message in messages:
            if phrase in message.content:
                print(message)
    else:
        await ctx.send("please enter the number of days wanted")

TextChannel.history

返回一个允许接收目标消息历史的 AsyncIterator。您必须拥有 read_message_history 权限才能使用它。

更新:

请阅读此discord.ext.commands

同时更改以下内容:

@client.event@bot.event client.run(TOKEN)bot.run(TOKEN) 删除client = discord.Client(intents=intents),因为bot = commands.Bot(command_prefix='!', intents=intents) 会发生

我还编辑了上面的代码以包含没有默认短语的历史记录。

【讨论】:

当我输入您提供的示例时,我的机器人似乎没有做任何事情。我更新了上面的代码 取自TextChannel.historyYou must have read_message_history permissions to use this. 确保运行bot并将所有client更改为bot 右键单击频道 > 编辑频道 > 权限 > 阅读消息历史记录上的绿色复选标记 b> 对吗?我做到了。它似乎仍然不起作用,也调用 !find 没有时间参数也不会向控制台打印任何内容。另外,非常感谢您的时间和帮助。我非常感谢这一点。

以上是关于如何循环消息的主要内容,如果未能解决你的问题,请参考以下文章

Windows 消息循环 - WPF中的消息循环

WPF的usercontrol中如何使用消息循环,就是DefWndProc

消息循环是不是在 UI 线程上执行?

C ++循环:如何让程序在用户输入无效输入时多次重复“错误”消息

如何循环列表,直到列表中的所有项目都与用户输入匹配,然后在 python 中使用 Bingo 消息停止循环

如何将应用程序定义的消息发送到 SDL 中的事件循环?