keep message count offline discord.py - python

I have a bot that counts when the nword is said, but when the bot goes offline the count resets
here is my code(the nword is being censored)
bot.softn = 0
bot.hardn = 0
#bot.event
async def on_message(message):
user = message.author
if message.content == "nibba":
embed=discord.Embed(title="racist", description=f"{user} said the N-word! \n racist!", color=0xb1f1c0)
await message.channel.send(embed=embed)
bot.softn += 1
elif message.content == "nibberr":
embed=discord.Embed(title="racist", description=f"{user} said the N-word! \n racist!", color=0xb1f1c0)
await message.channel.send(embed=embed)
bot.softn += 1
bot.hardn += 1
await bot.process_commands(message)
#bot.command()
async def racist(ctx):
embed=discord.Embed(title="Rascist Counter", description=f"N-word has been said {ctx.bot.softn} times!\n\nand of which the hard-R has been said {ctx.bot.hardn} times", color=0xefe0b4)
embed.add_field(name="Conclusion", value="The n-word is overrated. Get a better vocabulary", inline=True)
await ctx.send(embed=embed)
how can I have the counter not be reset?

I found a pretty good solution based on different contributions here, so you should take a closer look next time. You have to save the counter in a file, otherwise it will be lost, no matter what you do.
You mainly need 2 functions:
def load_counters():
with open('counter.json', 'r') as f:
counters = json.load(f)
return counters
def save_counters(counters):
with open('counter.json', 'w') as f:
json.dump(counters, f)
We use a JSON file called counter in this case. Here we load and save the JSON as a file.
dump means that we update the counter itself.
If you now want to listen to all the messages and save your word in this file you can use the following on_message event:
#bot.event()
async def on_message(message):
if "YourWord" in message.content:
counters = load_counters() # First load the file
counters["YourWord"] += 1 # Count up
save_counters(counters) # Save the count
How do we now get the count out of the file?
To read out the file we first have to open it, before we use it in a command:
with open('counter.json', 'r') as f:
counters1 = json.load(f) # Open and load the file
Now we can use counter1 to display the counter with:
f"{counters1['YourWord']}"
I would suggest to read the docs again and also have a look at how to use JSON files in Python

Related

Discord.py Anti-spam ignore channel command broken

Hello I am trying to make an ANTI SPAM bot to work on catching spammers and kicking the from the server. My problem though with the code is that it ignores all channels in the guild and not the channels in the json file.
Here is my code can you please take a look and update me on what I did wrong. Thanks
#client.listen()
async def on_message(message):
counter = 0
with open("spam-bank.txt", "r+") as file:
for lines in file:
if lines.strip("\n") == str(message.author.id):
counter += 1
file.writelines(f"{str(message.author.id)}\n")
try:
with open("channels.json", "r") as r:
j = json.load(r)
all_channels = j["channels"]
return all_channels
if counter > 3:
await message.channel.send(f'{message.author} has been kicked for spamming')
await message.guild.kick(message.author,reason="Caught by Anti-Spam for Spamming")
print(f'{message.author} was kicked')
await asyncio.sleep(2)
except:
return
#client.command()
async def ignore(ctx, channel_):
def add_channel(channel, file="channels.json"):
with open(file, "r+") as fw:
j = json.load(fw)
j["channels"].append(channel)
with open(file, "w+") as wp:
wp.write(json.dumps(j))
try:
with open("channels.json", "r"):
pass
except:
with open("channels.json", "w+") as wp:
wp.write('{"channels" : []}')
finally:
add_channel(channel_)
await ctx.send("Done!")
The issue is here:
with open("channels.json", "r") as r:
j = json.load(r)
all_channels = j["channels"]
return all_channels
When execution hits return all_channels, the function ends, and all_channels is returned. No code after that will be reached.
Instead, you need to write code to check if the channel the message was sent in is contained in all_channels and return/skip only in that case.
One simple way to figure this out in the future is to add lots of temporary print statements, and trace through the function by following the print statements.
with open("channels.json", "r") as r:
j = json.load(r)
print("loaded json from file")
all_channels = j["channels"]
print(f"extracted channels from json: {all_channels}")
return all_channels
print(f"checking counter: {counter}")
if counter > 3:
print("user has sent more than 3 messages. Kicking..")
await message.channel.send(f'{message.author} has been kicked for spamming')
await message.guild.kick(message.author,reason="Caught by Anti-Spam for Spamming")
print(f'{message.author} was kicked')
await asyncio.sleep(2)
You'll get an output like
loaded json from file
extracted channels from json: [list]
And from that, you can easily tell that something's going wrong between that print statement and the next one, because checking counter: [number] isn't getting printed.

Process finished with exit code 0, discord bot, what's wrong here?

I made a moderator bot but when i launch the code python writes "Process finished with exit code 0". Please check my if something wrong.
import discord
import config # Config is a another py file
client = discord.Client()
#client.event
async def on_message(message):
id = client.get_guild(config.ID)
badwords = ["testword", "testword2"]
unwarnusers = (config.unwarnusers)
for word in badwords:
if word in message.content.lower():
if str(message.author) not in unwarnusers:
warnFile = open("E:/vp2/warns.txt", "a")
warnFile.write(str(message.author.mention) + "\n")
warnFile.close()
warnFile = open("E:/vp2/warns.txt", "r")
warnedUsers = []
for line in warnFile:
warnedUsers.append(line.strip())
warnFile.close()
warns = 0
for user in warnedUsers:
if str(message.author.mention) == user:
warns += 1
if warns > 4:
mutedRole = discord.utils.get(message.guild.roles, name = "JB-MUTED")
await message.author.add_roles(mutedRole)
channel = client.get_channel(959128819137146900)
await channel.send(f"\nUser {message.author.mention} made something bad. \nHe writes:\n{message.content}\nThis happened in {message.channel}\n Warns: {warns}")
Add client.run('token') to the bottom of your code.

discord py how to fetch messages with jump_url and reactions attributes

I'm trying to make a bot that would autoreact, check the amount of reactions on the messages in a channel, make a link to the message and send it on a moderation channel if it got 2 or more reactions, then log it's jump url in bot's directory. I cant find a way to fetch all the messages with jump_url and reactions attributes. im feeling super lost so i'll put the code here
async def on_message(message):
if message.channel.id == 828579458167996420:
channel = client.get_channel(828579458167996420)
if message.attachments or "http" in message.content:
await message.add_reaction("<:MashaUpset:828589397074116709>")
x = int
messages = await channel.history(limit=21).flatten()
f = open("message log.txt","r")
readfile = f.read()
f.close()
if str(messages.jump_url) not in readfile:
if messages.reactions[0].count >= 2:
x = messages.reactions[0].count - 1
link = messages.jump_url
channel = client.get_channel(892065611876823100)
await channel.send("this post was liked "+ str(x) + " times! "+ str(link))
f = open("message log.txt", "a")
f.write("\n" + str(messages.jump_url))
f.close()
im a beginner, so sorry for the mess i've made
Edit: can't fetch jump_url, so instead fetching for message.id
Ok I found it. thx to Dominik for help
Changes I've done
I've separated the script into 2 parts, an on_message and a #tasks.loop
Added a for x loop
Added an await channel.fetch_message(x.id) in the loop
Fetched for message.id rather than jump_url
Added if statement to check if the message has reactions
#client.event
async def on_message(message):
if message.channel.id == 828579458167996420:
if message.attachments or "http" in message.content:
await message.add_reaction("<:MashaUpset:828589397074116709>")
#tasks.loop(minutes=2)
async def check():
channel = client.get_channel(828579458167996420)
messages = await channel.history(limit=30).flatten()
await asyncio.sleep(3)
f = open("message log.txt","r")
readfile = f.read()
f.close()
for message in messages:
channel = client.get_channel(828579458167996420)
message = await channel.fetch_message(message.id)
if str(message.id) not in readfile:
if message.reactions:
if message.reactions[0].count >= 2:
x = message.reactions[0].count - 1
link = message.jump_url
channel = client.get_channel(892065611876823100)
await channel.send("this post was liked "+ str(x) + " times! "+ str(link))
f = open("message log.txt", "a")
f.write("\n" + str(message.id))
f.close()
#check.before_loop
async def before():
await client.wait_until_ready()
check.start()

Discord.py Embed text file

I'd like to send on a Discord bot a message embed but text is from another file.
I did this way and it doesn't work:
#bot.command()
async def gdc(ctx):
"""Wins GDC"""
message = '/home/plo/rkr/res_wins2'
title = "GDC"
embed = discord.Embed()
embed.description = message
embed.title = title
embed.colour = 0xF1C40F
await ctx.send(embed=embed)
I have the embed message displaying the directory (/home/plo/rkr/res_wins2).
I modified it to read it before send it to Embed:
bot.command()
async def gdc(ctx):
"""Wins GDC"""
index1 = 0
file = open("/home/plo/rkr/res_wins2", "r")
for line in file.readlines():
line = line.strip()
index1 += 1
if index1 == 4: break
message = line
embed = discord.Embed()
embed.description = message
embed.title = title
embed.colour = 0xF1C40F
await ctx.send(embed=embed)
However, it seems only one result goes out... Here is my txt file:
Roi mouton: 9
tomate: 8
The_Portos: 8
Are the message in a .txt file? If this is true what you should do is read the file and pass it to a text string so you can match it to message. Here you can find the documentation to Handling Files.
You can check the Documentation Here.
It will help.
However using Java will be easier with like this:
channel.sendMessage("message").addFile(new File("path/to/file")).queue();
#bot.command()
async def gdc(ctx):
"""Wins GDC"""
with open("/home/plo/rkr/res_wins2", "r") as f:
scores = f.read().splitlines()
final = '\n'.join(scores[0:3])
embed=discord.Embed(title="Leader Board", description=final,color = 0xF1C40F)
await ctx.send(embed=embed)
Try putting it in a for-loop:
#bot.command()
async def logs(ctx):
embed: discord.Embed = discord.Embed(
title="title", description="description",
color=discord.Color.red()
)
file = open("file.txt", "r")
for line in file.readlines():
l = line.strip()
loglist.append(l)
embed.add_field(name="⠀", value=" `{0}`".format(l), inline=False)
embed.set_author(name="name")
await ctx.send(embed=embed)

Replacing a line in a file with Python doesn't work like it's supposed to

I'm creating a discord bot and tryying to save stats about every user and their messages sent but it's not working. This is what I have:
async def update_stats():
await client.wait_until_ready()
global messages, author
data = []
if author != 0:
try:
with open("stats.txt", "r") as f:
data = f.readlines()
for item in data:
author2, messages2 = item.split(":")
print(author2, messages2)
index = data.index(item)
if author == author2:
with open("stats.txt", "w") as f1:
data.pop(index)
novi_stat = f"""{author}:{int(messages) + int(messages2)}\n"""
data.insert(index, novi_stat)
str = ''.join(data)
f1.write(str)
else:
with open("stats.txt", "w") as f2:
data.append(f"""{author}:{messages}\n""")
str = ''.join(data)
f2.write(str)
await asyncio.sleep(5)
except Exception as e:
print(e)
await asyncio.sleep(5)
And this is the content of the text file it loads and is supposed to change when number of messages changes:
DrDEagle#4984:100
kreten:123
This is what I get when running the code:
DrDEagle#4984:100
kreten:123
:0
It is supposed to change the number from 100 to 101 if I send one message, but instead it writes a new line which doesn't even contain the right data, what am I doing wrong?
EDIT: After an hour of editing and rewriting the code, I did this and it works.
import discord
import random
import aiohttp
import asyncio
import json
import datetime
client = discord.Client()
sentdex_guild = client.get_guild(No, No!) # I didn't post the code...
author = ''
messages = 0
#client.event
async def on_message(message):
global author, messages
author = message.author.name
messages += 1
authorsInFile = []
f = open("stats.txt", 'r')
data = f.readlines()
for item in data:
author2, messages2 = item.split(":")
authorsInFile.append(author2)
print(author2, messages2)
if author in authorsInFile:
index = authorsInFile.index(author)
else:
pass
if author2 == author:
f1 = open("stats.txt", "w")
print(author)
data.pop(index)
novi_stat = f"""{author}:{int(messages2) + 1}\n"""
data.insert(index, novi_stat)
str = ''.join(data)
f1.write(str)
f1.close()
f.close()
else:
f2 = open("stats.txt", "w")
data.append(f"""{author}:{messages}\n""")
str = ''.join(data)
f2.write(str)
f2.close()
f.close()
await asyncio.sleep(5)
with open('log.txt', 'a') as f:
f.write(f"""{datetime.datetime.now()} | {message.author} je rekao: {message.content}\n""")
if message.content == "!bok":
await message.channel.send("Pozdrav!")
elif message.content == "!korisnici":
online = 0
idle = 0
offline = 0
for m in sentdex_guild.members:
if str(m.status) == "online":
online += 1
if str(m.status) == "offline":
offline += 1
else:
idle += 1
await message.channel.send(f"""Broj korisnika: {online+offline - 1}\nˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ\nOnline korisnika: {online - 1}\nOffline korisnika: {offline}\n^^^^^^^^^^^^^^^^^^^^^^^^""") # printa broj korisnika, ali ne broji sebe
elif message.content == "!ping":
latency = client.latency
await message.channel.send(f"""Moj ping iznosi {round(latency, 6)}ms""")
elif message.content == "!yacketty":
await message.channel.send("Dostupne komande su: !ping, !bok, !korisnici, !bitcoin...")
elif message.content == "!bitcoin":
url = 'https://api.coindesk.com/v1/bpi/currentprice/BTC.json'
async with aiohttp.ClientSession() as session: # Async HTTP request
raw_response = await session.get(url)
response = await raw_response.text()
response = json.loads(response)
await message.channel.send("Cijena bitcoina: $" + response['bpi']['USD']['rate'])
elif "!8ball" in message.content:
moguci_odgovori = [
'Nema jebene šanse',
'Možda, ali samo možda',
'Ahhh, 50-50',
'Vrlo moguće',
'Apsolutno da'
]
await message.channel.send(random.choice(moguci_odgovori) + ", " + message.author.mention)
#client.event
async def welcome(member):
for channel in member.server.channels:
if str(channel) == "general":
await client.send_message(f"""{member.mention}, dobrodošao na server!""")
client.run("I'm not showing you this hehe")
I don't see anywhere that you set either author or messages. You have them set as globals, so I assume you're setting them before calling this function. If author is an empty string, and messages is 0, then the output you are getting is just what I would expect from your code.
Since there is not yet an author named "", it appends an entry for that author to the file that is the empty author name, a colon, and the 0 that is the value of message.
Note that your first if test would succeed and the if block entered in this proposed case, as "" != 0 is True.
Another observation...you're reading in multiple existing authors, but you seem to be only comparing the passed in author against the last author read in from the file. I'm assuming that's not what you want...you probably want to be comparing each author you read in against the passed in author in the loop that is processing each line of the file.

Categories

Resources