Anonyo Noor
Anonyo Noor

Reputation: 553

Building a discord antispam bot and getting errors

Very new to discord bots and python in general and building an antispam bot, here's my code:

import discord
from discord.ext import commands
import time

b = commands.Bot(command_prefix='not a bot')
b.remove_command("help")

@b.event
async def on_ready():
    print('Bot is Ready')

authors = {}
authors1 = []
@b.event
async def on_message(ctx):
    global authors
    global authors1
    author_id = ctx.author.id
    for author2 in authors1:
        if author_id == author2:
            authors[author_id] += 1
        else:
            authors[author_id] = 1
            authors1.append(author_id)
    stop = False
    timer = 5
    while stop == False:
        if timer > 0:
            time.sleep(0.985)
            timer -= 1
            if authors[author_id] > 5:
                await ctx.send("Stop Spamming")
        else:
            timer = 5
            authors[author_id] = 0

b.run('stack overflow')

Basically on every message it gets every users discord id and then assigns a value to it, default is 1 since the user just sent a message, where the while loop starts is a timer, every 5 seconds it resets and if the user who's sent the message has sent 5 messages, it tells them to stop spamming, I don't know why I'm getting errors, also since I'm new to python is I could make any code simpler it would be much appreciated if you could let me know.

Here's the error I keep getting

Bot is Ready
Ignoring exception in on_message
Traceback (most recent call last):
  File "C:\Users\12488\AppData\Local\Programs\Python\Python38\lib\site-packages\discord\client.py", line 333, in _run_even
    await coro(*args, **kwargs)
  File "C:\Users\12488\Downloads\Bot\antispam.py", line 31, in on_message
    if authors[author_id] > 5:
KeyError: 234295307759108106

Upvotes: 3

Views: 7560

Answers (1)

Tim
Tim

Reputation: 2187

A few things:

  1. The error message is occurring because you are referencing a author_id which isn't set
  2. Your variable names are extremely confusing, this makes it difficult to understand what you were going for.
  3. I think there is an issue with your logic. I am not sure why there is a sleep loop at the bottom.

Anyway, I think the following code will do what you'd like it to.

import discord
from discord.ext import commands

import datetime
import time

b = commands.Bot(command_prefix='not a bot')
b.remove_command("help")

time_window_milliseconds = 5000
max_msg_per_window = 5
author_msg_times = {}
# Struct:
# {
#    "<author_id>": ["<msg_time>", "<msg_time>", ...],
#    "<author_id>": ["<msg_time>"],
# }


@b.event
async def on_ready():
    print('Bot is Ready')


@b.event
async def on_message(ctx):
    global author_msg_counts

    author_id = ctx.author.id
    # Get current epoch time in milliseconds
    curr_time = datetime.datetime.now().timestamp() * 1000

    # Make empty list for author id, if it does not exist
    if not author_msg_times.get(author_id, False):
        author_msg_times[author_id] = []

    # Append the time of this message to the users list of message times
    author_msg_times[author_id].append(curr_time)

    # Find the beginning of our time window.
    expr_time = curr_time - time_window_milliseconds

    # Find message times which occurred before the start of our window
    expired_msgs = [
        msg_time for msg_time in author_msg_times[author_id]
        if msg_time < expr_time
    ]

    # Remove all the expired messages times from our list
    for msg_time in expired_msgs:
        author_msg_times[author_id].remove(msg_time)
    # ^ note: we probably need to use a mutex here. Multiple threads
    # might be trying to update this at the same time. Not sure though.

    if len(author_msg_times[author_id]) > max_msg_per_window:
        await ctx.send("Stop Spamming")

b.run('stack overflow')

Upvotes: 7

Related Questions