Discord.py Embed text file, get more results - discord.py

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"""
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 a part of my txt file:
Roi mouton: 9
tomate: 8
The_Portos: 8
And here is the result:

You're changing the value of line every loop in the for loop so you'll have to make a list of the lines
lines = []
with open("/home/plo/rkr/res_wins2", "r") as file: # Use this to open and close the file
for line in file.readlines():
line = line.strip()
lines.append(line)
index1 += 1
if index1 == 4: break
embed = discord.Embed()
embed.description = '\n'.join(lines)
embed.title = title
embed.colour = 0xF1C40F
await ctx.send(embed=embed)

Related

discord.py file append rewrite the file instead of appending

When I want to append something to a file (with the append mode), it just erases everything before writing what I would like to append.
I have an on_voice_state_update event, when triggered, it checks if the user joined a specific channel. If yes: it creates a voice channel with some permissions for the user who created the voice channel. It is also supposed to append to a file called member_channel.txt this: {member.id}:{the_member's_voice_channel.id} but instead of adding this at the end of the file, it first erases everything and then add what I want to add.
Here are the codes:
#bot.event
async def on_voice_state_update(member, before, after):
if after.channel is not None and after.channel.id == 1059553884286230608:
guild = bot.get_guild(966749409314504774)
everyone_role = discord.utils.get(guild.roles, id = 966749409314504774)
community_role = discord.utils.get(guild.roles, id = 1006304076331483256)
muted_role = discord.utils.get(guild.roles, id = 1059109986258653244)
global member_channel
member_channel = await guild.create_voice_channel(name = f"Vocal de {member.name}")
await member_channel.edit(category = discord.utils.get(get_guild().channels, id = 1057730051321372692))
await member_channel.set_permissions(member, connect = True, manage_channels = True, manage_permissions = True, priority_speaker = True, move_members = True)
await member_channel.set_permissions(everyone_role, view_channel = False)
await member_channel.set_permissions(community_role, view_channel = True)
await member_channel.set_permissions(muted_role, speak = False)
await member.move_to(member_channel)
with open("member_channel.txt", "a") as file: # THIS IS WHAT
file.write(str(member.id) + ":" + str(member_channel.id) + "\n") # IS'NT WORKING
print(f"[{await get_hour()}] {member.name} created a temporary voice channel.")
#then we want to delete the channel if it is empty and equal to a member's channel, and also delete the line in member_channel.txt corresponding to this member and channel
elif before.channel is not None and len(before.channel.members) == 0:
new_file_value = ""
try:
with open("member_channel.txt", "r") as file:
lines = file.readlines()
splited_lines = []
for line in lines:
splited_lines.append((line.split(":")))
for lines in splited_lines:
for line in lines:
line.replace("\n", "")
if str(before.channel.id) in line:
await before.channel.delete()
del splited_lines[line.index(str(before.channel.id))]
for line in splited_lines:
print(new_file_value)
new_file_value += line
for ele in line:
print(new_file_value)
new_file_value += line + ":"
with open("member_channel.txt", "w+") as file:
file.write(new_file_value)
print(f"[{await get_hour()}] I deleted the temporary voice channel {member_channel.name}.")
file.close()
file.close()
except NameError:
return

Remove Discord Markdown

How do I remove mark down in discord.py?
I was making an eval command but I realized that sending it with markdown eg. '```py print("example code")```', breaks it.
I want to make it easier for me and the other admin/mod to use it for debugging purposes in my bot.
#client.command()
async def eval(ctx, *, code):
out, err = io.StringIO(), io.StringIO()
sys.stdout = out
sys.stderr = err
await ctx.channel.trigger_typing()
await aexec(code)
results = out.getvalue()
errors = err.getvalue()
await ctx.send(embed = discord.Embed(title = "Eval", description=f"Output Is \n```bash\n{results}```"))
await ctx.send(embed = discord.Embed(title = "Code", description=f"Input Is \n```py\n{code}```"))
the above code is what I've tried so far..
I've been playing with your code for the past hours, I wanted to figured it out :P
This is the only way i could access the code when there was markdown in the command input.
#client.command()
async def eval(ctx, *, code):
raw = f'{ctx.message.content}'[12:-3] # Get rid of markdown + py and last 3 ```
#Might want to add if statements in case the input doesn't include py / something else.
print (raw) # Testing purpose
out, err = io.StringIO(), io.StringIO()
sys.stdout = out
sys.stderr = err
await ctx.channel.trigger_typing()
exec(raw) # no need for await
results = out.getvalue()
errors = err.getvalue()
await ctx.send(embed = discord.Embed(title = "Eval", description=f"Output Is \n```bash\n{results}```"))
await ctx.send(embed = discord.Embed(title = "Code", description=f"Input Is \n```py\n{raw}```"))
await ctx.send(embed = discord.Embed(title = "Errors", description=f"Errors are \n```py\n{errors}```")) #Added this output to see errors

Word limit in an embed description

I want to make that when the description of the embed exceeds the word limit it continues in another separate embed but that the previous embed ends with 3 dots (...) eliminating a small part of the message and following it in the other embed, at the moment this is the code I have:
#commands.command(aliases=["pj"])
async def personaje(self, ctx, personaje=None, member: discord.Member=None):
if personaje is None:
await ctx.send(":x: Debes proporcionar la id del personaje que quieres visualizar")
else:
if member is None:
member = ctx.author
if os.path.exists("json/Roleplay/Personajes/{member}/{idpersonaje}.json".format(member=member.id, idpersonaje=personaje)):
with open("json/Roleplay/Personajes/{member}/{idpersonaje}.json".format(member=member.id, idpersonaje=personaje), 'r') as f:
data = json.load(f)
Nombre = data["Nombre"]
Historia = data["Historia"]
color = data["Color"]
personalizado = data["Personalizado"]
text = ""
text = "".join(f"\n**{key}:** {value}" for key, value in personalizado.items())
color = int(color, 16)
timestamp = datetime.datetime.now()
prueba = f"**{Nombre} {text}\n\n**Historia:**\n {Historia}"
if len(prueba) < 2000:
embed=discord.Embed(description=prueba, color=color)
embed.set_author(name=ctx.author, icon_url=ctx.author.avatar_url)
embed.timestamp = timestamp
await ctx.send(embed=embed)
else:
embed=discord.Embed(description=prueba[:-3] + "...", color=color)
embed.set_author(name=ctx.author, icon_url=ctx.author.avatar_url)
embed.timestamp = timestamp
await ctx.send(embed=embed)
else:
await ctx.send(":x: Este personaje no existe")
return
Example of what I want to do (obviously with a longer text that exceeds 2000 words):
https://imgur.com/zytqLKm
Best method is making a function to split the data every n char.
Making fields with name of empty line might be better then using new embed.
Keep in mind don't split at 2000 exactly because you have ...
def split_length(data: str, n: int):
'''Splits the data given at each given n'''
out_data = []
for i in range(0, len(data), n):
out_data.append(data[i:i+n])
return out_data
#bot.command()
async def longtext(ctx):
embed = discord.Embed(title='Example of long text split')
long_text = 'qwerty'
field_values = split_length(data=long_text, n=2)
for value in field_values:
# "\u200b" is just an empty line
embed.add_field(name="\u200b", value=f"{value} ...", inline=True)
await ctx.send(embed=embed)

Ignoring exception in command buy

An error pops up when I do the buy command. This code comes from The coding academy discord server but they didn't seem to know how to help. This is for a currency bot. Here is my code followed by the error:
`mainshop = [{"name":"Knife","price":65,"description":"Mug people! Unlocks `mug`"},
{"name":"Laptop","price":5000,"description":"Post some sweet memes on reddit! Unlocks `postmemes`"},
{"name":"Gun","price":10000,"description":"Rob people and businesses! Unlocks `rob` and `mug`"}]
#client.command()
async def shop(ctx):
em = discord.Embed(title = "Shop")
for item in mainshop:
name = item["name"]
price = item["price"]
desc = item["description"]
em.add_field(name = name, value = f"${price} | {desc}")
await ctx.send(embed = em)
#client.command()
async def buy(ctx,item,amount = 1):
await open_account(ctx.author)
res = await buy_this(ctx.author,item,amount)
if not res[0]:
if res[1]==1:
await ctx.send("That Object isn't there!")
return
if res[1]==2:
await ctx.send(f"You don't have enough money in your wallet to buy {amount} {item}")
return
await ctx.send(f"You just bought {amount} {item}")
#client.command()
async def inventory(ctx):
await open_account(ctx.author)
user = ctx.author
users = await get_bank_data()
try:
bag = users[str(user.id)]["bag"]
except:
bag = []
em = discord.Embed(title = "Inventory")
for item in bag:
name = item["item"]
amount = item["amount"]
em.add_field(name = name, value = amount)
await ctx.send(embed = em)
async def buy_this(user,item_name,amount):
item_name = item_name.lower()
name_ = None
for item in mainshop:
name = item["name"].lower()
if name == item_name:
name_ = name
price = item["price"]
break
if name_ == None:
return [False,1]
cost = price*amount
users = await get_bank_data()
bal = await update_bank(user)
if bal[0]<cost:
return [False,2]
try:
index = 0
t = None
for thing in users[str(user.id)]["bag"]:
n = thing["item"]
if n == item_name:
old_amt = thing["amount"]
new_amt = old_amt + amount
users[str(user.id)]["bag"][index]["amount"] = new_amt
t = 1
break
index+=1
if t == None:
obj = {"item":item_name , "amount" : amount}
users[str(user.id)]["bag"].append(obj)
except:
obj = {"item":item_name , "amount" : amount}
users[str(user.id)]["bag"] = [obj]
with open("mainbank.json","w") as f:
json.dump(users,f)
await update_bank(user,cost*-1,"wallet")
return [True,"Worked"]
Error:
Ignoring exception in command buy: Traceback (most recent call last): File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
ret = await coro(*args, **kwargs) File "main.py", line 50, in buy
res = await buy_this(ctx.author,item,amount) File "main.py", line 104, in buy_this
if bal[0]<cost: TypeError: 'bool' object is not subscriptable
The above exception was the direct cause of the following exception:
Traceback (most recent call last): File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 902, in invoke
await ctx.command.invoke(ctx) File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 864, in invoke
await injected(*ctx.args, **ctx.kwargs) File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: 'bool' object is not subscriptable
As much as I see your value of the variable bal is somehow a bool value due to which if you try to take out values from it as a list, it gives you the following error.
You should try checking the definition of the update_bank() command and check it's return type.
Check this website for more info on the error : https://www.tutorialexample.com/fix-typeerror-bool-object-is-not-subscriptable-in-python-python-tutorial/

python, import csv file, read columns and rows, remove blank spaces, convert strings to real numbers

I'm having trouble with importing a csv file into python and having it separate the information. I want to also remove all the blank spaces and convert the numbers (which are strings right now) into integers. Here is what I have so far. These lines work but do not accomplish the task of removing the blank spaces and converting the strings to integers.
filename = 'myfile.csv'
f = open(filename, 'r')
read = f.readlines()
print(read)
for i in range(len(read)):
read[i] = read[i].split(',')
print(read)
header = read[0]
print(header)
info = {}
cntr = 0
for name in header:
info[name] = [line[cntr] for line in read]
cntr += 1
print(info)
I searched through past examples on this forum and this is what I tried to do to have the blank spaces removed but now I'm lost:
import csv
aList = []
with open('myfile.csv', 'r') as f:
reader = csv.reader(f, skipinitialspace = True, delimiter = ',', quoting = csv.QUOTE_NONE)
for row in reader:
aList.append(row)
print(aList)
info = {}
cntr = 0
for i in aList:
info[aList] = [line[cntr] for line in reader]
cntr += 1
print(info)
#sample input
#1 23,456,789
#11 2,11 3,114
import csv
aList = []
with open('myfile.csv', 'r') as f:
reader = csv.reader(f, skipinitialspace = True, delimiter = ',', quoting = csv.QUOTE_NONE)
for row in reader:
aList.append(row)
print(aList)
info = {}
cntr = 0
print [map(int,[j.replace(" ","") for j in i]) for i in aList]
#[[123,456,789][112,113,114]]
Explanation - making the last line simple, and breaking into parts,
#[i for i in aList] gives [["1 23","456","789"]["11 2","11 3","114"]]
#[j.replace(" ","") for j in i] gives [["123","456","789"]["112","113","114"]]
#[map(int,[j.replace(" ","") for j in i]) for i in aList]
#maps all string in list to int and gives [[123,456,789][112,113,114]]

Resources