I recently made a command that saves the information into a JSON file. So basically, I have 2 commands, first command sets the global variable, and the second command uses the variables provided to add into the JSON file. And once I tested it, it saves the text as a global variable, and then it saved into the JSON file as {'test'}. I don't want the {''}, so is there a way to don't have {''}, only the text test?
Script:
#global variables
namereg = None
cbreg = None #more
bdreg = None
descreg = None
libreg = None
invreg = None
btreg = None
ssreg = None
slugreg = None
#client.command(pass_context=True)
async def namereg(ctx, *, arg):
global namereg
namereg = {arg}
embed = discord.Embed(title='Registed Name.',description=f'Set the name as {arg}',colour=discord.Color.dark_green())
print(f'{arg}')
await ctx.send(embed = embed)
#client.command(pass_context=True)
async def add(ctx):
role_names = [role.name for role in ctx.message.author.roles]
if "Server Moderator" in role_names:
def write_json(data, filename='bots.json'):
with open (filename, "w") as f:
json.dump(data, f, indent=4)
with open ('bots.json') as json_file:
data = json.load(json_file)
temp = data["bots"]
y = {"name": f"{namereg}"}
temp.append(y)
write_json(data)
embed = discord.Embed(title='Added!',description='Successfully added with the following!',timestamp=ctx.message.created_at,colour=discord.Color.dark_green())
await ctx.send(embed = embed)
If there is a way to not have {''}, please reply to this thread! Thank you.
If you're writing it to a JSON file, the quotes will be added every time as part of JSON syntax. If you just need to write a dictionary to a file (which is also readable), you can write it to a normal .txt file.
Issues:
namereg = None
#client.command(pass_context=True)
async def namereg(ctx, *, arg):
global namereg
This is broken. Functions at the top level of your code are global variables, and are in the same namespace. Give it a different name from the storage variable.
namereg = {arg}
This takes the string that came from the user's input, and creates a set with a single element. That is not what you want. You wanted the input string to be the registered name, so just assign it directly.
y = {"name": f"{namereg}"}
I assume you did this fancy formatting because you were getting an error before (because the json will not serialize sets by default, because the JSON data format does not have a direct way to represent them). You should have listened to this error message more closely, by questioning why you had data of the invalid type in the first place. The {} and '' in your output come from the string representation of the set that you stringify using the string formatting. The plain string that you want to use does not require any formatting to convert to string, because it is already a string.
Related
So I have a bot which moves from stage to stage using the stage names as a product of return of each function.
e.g.
STEP_1, STEP_2, STEP_3 = range(3)
def askforfile(update, context):
chat_id = update.message.chat_id
context.bot.send_message(chat_id=chat_id, text="give a file!")
return STEP_1
def getfile(update, context):
chat_id = update.message.chat_id
filename = 'newfile'+str(chat_id)+ '.txt'
f = open(filename, 'wb')
context.bot.get_file(update.message.document.file_id).download(out=f)
f.close()
return STEP_2
def get_info(update, context):
chat_id = update.message.chat_id
info = update.message.text
return STEP_3
def end(update, context):
with open(filename, 'rb') as f:
writecsv1 = some_module.some_function(filename, info)
with open(writecsv1, 'rb') as doc:
context.bot.send_document(chat_id=chat_id, document=doc)
return ConversationHandler.END
So in the end() function I need to pass the variables from functions getfile() and get_info() in the some_function. But I have no clue how to do it, because returning multiple values doesn't work for me and even if it worked, obviously I can't call functions.
You could use global variables filename and info (maybe don't name them that) that you rewrite within your functions. Just define them with some default value above your function definitions. Right now they're just defined locally and disappear once the function returns.
I highly recommend not to use global variables. Global variables are considered bad practive in general and in this case they can easily get you into trouble when multiple users are using your bot at the same time and each overrides the global variables. python-telegram-bot comes with a built-in solution for storing data in memory. I recommend to leverage that.
Disclaimer: I'm currently the maintainer of python-telegram-bot.
Let me explain:
if config == "create":
if str(user.id) in submissions:
await ctx.send(embed=discord.Embed(title="ERROR", description='you already have a submission!', color=discord.Color.red()))
return
if len(submission_full) > 2 and len(submission_full) < 100:
submissions[str(user.id)] = {}
submissions[str(user.id)]["submission"] = submission_full
Basically what I have here is a discordpy submission command that creates a submission and dumps it into a json file. I am currently working on a command that does the same thing but reversed, so it deletes your submission if you want to undo.
My first thought was doing this:
if config.lower() in ["delete","remove","undo","cancel"]:
await ctx.send(embed=discord.Embed(title="Removing Current Submission..", description="You will no longer have any submissions. You can create a new one at any time!", color=0xFFD700))
submissions[str(user.id)] = None
But it simply replaces your submission with "null".
Here is the output in the json file:
{"710826704259645450": null}
Help appreciated!
You want:
del submissions[str(user.id)]
You can use :
submissions.pop(str(user.id))
And then dump it
What I'm trying to do: I had some people abuse my bot's commands, so I wanted to put a stop to this. Therefore, after reviewing multiple sources of code, I got as far as inserting member ids into a .txt document.
My problem: My 'custom check' has been having errors. All the custom check examples that I had found were in cogs or were not related to what I was trying to do, therefore I haven't gotten mine to work as expected yet. Note that I am not using cogs, either.
Code:
def blacklist(ctx): # this is the def used for the check, it reads the .txt file for user
file = open("blacklist.txt", "r")
members_banned = file.readlines()
if str(ctx.author.id) not in members_banned:
return ctx.author.id not in members_banned
#client.command() # this command is used for adding people to the blacklist. This is most likely not the problem..
#commands.is_owner()
async def blacklist(ctx, member: discord.Member):
file = open("blacklist.txt", "r")
anything = False
while anything == False:
content = file.read()
things = content.split("\n")
for line in things:
if str(line) == str(member.id):
await ctx.send(f"{member.name} is already in blacklist, please remove manually!")
anything = True
else:
pass
if anything == False:
thing = open("blacklist.txt", "a")
thing.write(f"\n{member.id}")
thing.close()
anything = True
await ctx.send(f"{ctx.author.mention}: {member.name} has been blacklisted, hopefully")
file.close()
break
#client.command()
#commands.check(blacklist) # This is the code I used to test the custom check for the blacklist
async def bltest(ctx):
await ctx.send("Cool, you're not blacklisted")
Errors: (via this code)
return await self.callback(*args, **kwargs)
TypeError: blacklist() missing 1 required positional argument: 'member'
The above error doesn't make any sense to me.
Others:
The .txt file
Other code I have looked at:
Code found after looking through previous questions asked in the discord.py server
Code found while trying to look for check examples, this is in a cog
The discord.py documentation
Both of your functions have the same name. The command is named blacklist with the ctx and member parameter, while the function's name is blacklist with just ctx as a parameter. This means if the wrong one is chosen, you're calling a function that expects 2 arguments & only giving it 1.
Give the first function (the one that reads the file) a different name, like "check_blacklist" or "blacklisted" or whatever suits you best.
As it says in the error in the first line of code add member as an argument to the function blacklist. You need it because in this function you are dealing with member of the discord server.
I am building a bot that sends a txt file based on a command.
Problem is that when two people send the same command at the same time, the bot only sends one of the two twice, which is something I should avoid at all costs.
Do you have any solutions?
I tried to come up with a solution but it didn't work: I tried to delete the file right after it has been sent, but as I said, it didn't work.
NOTE: the bot successfully sends two embeds with the correct information, but then sends two identical files (always the one generated by the second request)
Here's the code of the command:
#bot.command(name='sendfile', help='Sends a file', pass_context=True)
async def quick(ctx, *args):
try:
arg1 = str(args[0])
arg2 = args[1].capitalize()
arg3 = args[2].upper()
quantity = args[3]
generate_file(order_id, arg2, quantity)
except:
embed = Embed(title="FILE GENERATION", description="An error has occurred. Please retry", color=16711702)
fields = [("Error ID", "1", False)]
for name, value, inline in fields:
embed.add_field(name=name, value=value, inline=inline)
print(f"{bcolors.FAIL} [{datetime.now()}] - ERROR {bcolors.ENDC}")
raise TypeError
embed = Embed(title="FILE GENERATION", description="FILE DETAILS", color=15859711)
fields = [("ARG 1", f"{arg1}", False), ("Arg2", f"{arg2}", False), ("arg3", f'{arg3}',False), ("Quantity", f"{quantity}", False)]
for name, value, inline in fields:
embed.add_field(name=name, value=value, inline=inline)
await ctx.send(embed=embed)
print(f"{bcolors.OKCYAN} [{datetime.now()}] - Command successfully executed! {bcolors.ENDC}")
with open("generated_file.txt", "rb") as file:
await ctx.send(file=discord.File(file, "generated_file.txt"))
Thanks for your help :)
The solution I came up with it solves the problem but it's not the best, but it works.
The idea is basically that I generate an alphanumeric string and include that in the file name.
e.g.: 'file_fu56d.txt'
After creation, I send it over to discord and then delete it.
Here's some code:
list= []
random_string = get_random_string(5)
for p in range(0, int(quantity)):
to_append = f'{arg1}-something-{arg2}-soimething_else-{arg2}\n'
list.append(to_append)
# writes the txt file assigning each element of the list to each line
with open(f'file_{random_string}.txt', 'w') as file:
file.writelines(list)
print(f'[{datetime.now()}] - {quantity} lines successfully generated.')
# opens the file and sends it to discord
with open(f"file_{random_string}.txt", "rb") as file:
await ctx.send(file=discord.File(file, f"file_{random_string}.txt"))
print(f"[{datetime.now()}] - File successfully sent! ")
# deletes the file
os.remove(f'file_{random_string}.txt')
print(f"[{datetime.now()}] - 'file_{random_string}.txt' successfully deleted!")
So i'm making some scoring system type thing in python with json and discord.py, this is its code:
import json
def getPoints(bot, user):
f = open('points.json', 'r')
points = json.load(f)
name = str(user)
f.close()
return points.get(name)
#later on down the line
#bot.group()
async def pointSystem(ctx):
pass
#pointSystem.command()
async def enable(ctx):
f = open('points.json', 'r')
points = json.load(f)
if points.get(str(ctx.author)) != None:
await ctx.send('Already enabled for this user!')
return
io = await ui.prompt(ctx, 'This command enables the point system\nAre you sure you want to enable this?')
if io == 'yes':
await ctx.send('Ok, enabling...')
points[str(ctx.author)] = 0
f.close()
f = open('points.json', 'w')
json.dump(points, f, indent=4)
f.close()
await ctx.send('Enabled for this user!')
else:
await ctx.send('Alright, stopping command execution...')
f.close()
in points.json i should have:
{}
And that's what i put in there originally, but sometimes, i look into points.json and i see a string with some random word in it. It doesn't give an error of any kind, it just does what i described, which doesn't make much sense, because i don't think i have any code that would set it to a string of any kind. I have no reproduction code, as i don't know the real culprit of this problem, i would point you towards doing something like what i did, which is creating a discord bot with this scoring system thing, but i don't really think even that would reproduce it.
Edit: Okay, this is getting really weird. 3 months later, with completely new code, I still have a file named "points.json" in my root directory, and it contains the random string I mentioned above, that literally makes no sense. Even when I remove it, a couple weeks later it will come back.