2
votes

So I was building this discord bot that reads the latest.log file from a Minecraft server and sends user, advancement, and death messages in a specific channel. Now the problem is, after a while, the bot starts sending out multiple messages and I don't really know why. I've tried adding lines I've already sent in a file and cross-checking new lines to see if they are duplicates. This is around the time when my friend (who runs my bot on his computer) sends me a screenshot of his python.exe window which shows the 'Bot is Online' message multiple times. My best guess is multiple bot instances are running at the same time but I can't figure out how it does that in the first place. Can someone help me out?. This is my code:

from discord.ext import commands

client = commands.Bot(command_prefix='.')
deth_msgs = ['was shot', 'was pummeled by', 'was pricked to death',
             'walked into a cactus whilst trying to escape', 'drowned', 'experienced kinetic energy whilst trying to escape', 'blew up', 'was blown up by',
             'was killed by', 'hit the ground too hard', 'hit the ground too hard whilst trying to escape',
             'fell from a high place', 'fell off', 'was impaled', 'was squashed by', 'was skewered by', 'went up in flames', 'walked into fire whilst fighting',
             'burned to death',
             'was burnt to a crisp whilst fighting', 'went off with a bang', 'tried to swim in lava', 'was struck by lightning', 'discovered the floor was lava',
             'walked into danger zone due to', 'was killed', 'froze to death', 'was frozen to death by', 'was slain by', 'was fireballed by', 'was stung to death',
             'was shot by a skull from', 'starved to death', 'suffocated in a wall', 'was squished too much', 'was poked to death', 'was impaled by',
             'fell out of the world', "didn't want to live in the same world as"]

players = []

with open('usercache.json') as u_file:
    details = json.load(u_file)
    for dict in details:
        players.append(dict['name'])

try:
    f = open("dupli_lines.txt")
except FileNotFoundError:
    f = open('dupli_lines.txt', 'w+')
finally:
    f_stats = os.stat('dupli_lines.txt')
    f.close()
    if f_stats.st_size > 1000000:
        os.remove('dupli_lines.txt')
        f = open('dupli_lines.txt', 'w+')
    f.close()

#------------------------------------------------ Events -----------------------------------------------------------------------


@client.event
async def on_ready():
    print('Bot is Online')
    channel = client.get_channel(id)
    pos = 0
    while True:

        with open('dupli_lines.txt','r') as f:
            logs = f.read()
        
        with open(absolutepath) as file:
            file.seek(pos)
            line = file.readline()
            if line not in logs:
                # if 'joined the game\n' in line:
                #     string = line[33:]
                #     player = string.replace(' joined the game\n', '')
                #     if check_dup(player) == False:
                #         players.append(player) 

                if '!coords' in line:
                    if line not in logs:
                        with open('dupli_lines.txt', 'a+') as f:
                            if line not in logs:
                                f.write(line)
                        string = line[33:].replace('!coords', '')
                        words = string.split()
                        for player in players:
                            for word in words:
                                if player in word:
                                    embed = discord.Embed(
                                        title=player,
                                        colour=discord.Colour.from_rgb(57, 255, 20)
                                    )
                                    words.pop(0)
                                    tup_words = tuple(words[1:])
                                    msg = ' '.join(tup_words)
                                    embed.add_field(
                                        name=words[0], value=msg, inline = False)
                                    embed.set_thumbnail(
                                        url='http://static.wikia.nocookie.net/minecraft_gamepedia/images/2/2c/Compass_JE3.gif/revision/latest/scale-to-width-down/150?cb=20201125191224')
                                    
                                    await channel.send(embed=embed)
                                break
                    time.sleep(1)
                    break

                if line[33:].startswith('<'):
                    await channel.send(line[33:])
                    with open('dupli_lines.txt', 'a+') as f:
                        f.write(line)
                    time.sleep(1)

                if 'made the advancement' in line:
                    embed = discord.Embed(
                        title = line[33:],
                        colour=discord.Colour.from_rgb(255,215,0)
                        )
                    embed.set_thumbnail(
                        url='https://www.pikpng.com/pngl/b/456-4569150_michael-rosen-noice-png-brian-rosen-clipart.png')
                    await channel.send(embed=embed)
                    with open('dupli_lines.txt', 'a+') as f:
                        f.write(line)
                    time.sleep(1)
            
                else:
                    for msg in deth_msgs:
                        if msg in line:
                            await channel.send(line[33:])
                            with open('dupli_lines.txt', 'a+') as f:
                                f.write(line)
                            break
                    time.sleep(1)
                    
            pos = file.tell()

client.run('TOKEN')

And this is what shows up in the python window: Bot is Online x 6

P.S.: I am aware that all my code's written in the on_ready() function, but I intended to use this bot for just this specific reason, i.e.to read in-game messages and present them in the discord channel.

1
I don't think you want your Discord API key in the question. You probably want to disable that one and generate a new one. And in your code - if the command is !coords, you break the inner loop and do not update the file pos. There is also nothing that says on_ready only will be called once; if the client has to reconnect to Discord, it will be invoked again: discordpy.readthedocs.io/en/stable/api.html#discord.on_readyMatsLindh
This function is not guaranteed to be the first event called. Likewise, this function is not guaranteed to only be called once. This library implements reconnection logic and thus will end up calling this event whenever a RESUME request fails.MatsLindh
Add a check if you've already run the function, then return. You might want to restructure the code to only have that check inside on_ready and then a separate function that you call outside for clarity.MatsLindh
on_ready is called when the bot re-establishes the connection, it can be called multiple times. I suggest you use tasks for this.Ceres
Your while True loop with file-bound IO is blocking. Have you tried tasks (as mentioned above)?Frederick Reynolds

1 Answers

0
votes

If multiple instances are running you can always change the bot token to revoke the access of any instance running.

You can do this do by going to https://discord.com/developers/applications