How to stop after function from executing twice after song ends - python

The after function in ctx.guild.voice_client.play(stream, after=lambda e: self.queueCheck(ctx, id, vc)) ie, queueCheck is running two times when it should run just once. It basically pops off a track off the queue and plays it on vc. But because the function itself is running two times in a row, it leads to one song getting skipped out of nowhere.
Here is the relevant code:
queues = {}
class music(commands.Cog):
def __init__(self, client):
self.client = client
self.tracks = {}
self.isPaused = False
self.skipping = False
self.FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5 -nostdin', 'options': '-vn'}
self.YDL_OPTIONS = {'format': 'bestaudio/best',
'outtmpl': 'downloads/%(extractor)s-%(id)s-%(title)s.%(ext)s',
'restrictfilenames': True,
'nocheckcertificate': True,
'ignoreerrors': False,
'logtostderr': False,
'noplaylist': True,
'quiet': True,
'no_warnings': True,
'default_search': 'auto',
'source_address': '0.0.0.0', # ipv6 addresses cause issues sometimes
'force-ipv4': True,
'cachedir': False}
def queueCheck(self, ctx, id, vc):
text = ""
if queues[id] != []: # if server player queue not empty
stream = queues[id].pop(0)
if self.skipping == True:
print('skipping')
self.tracks[id].pop(0)
if len(self.tracks[id]) != 0:
text = "Now playing **" + self.tracks[ctx.message.guild.id][0] + "**"
self.skipping = False
else:
print('end naturally')
self.tracks[id].pop(0)
text = "Now playing **" + self.tracks[ctx.message.guild.id][0] + "**"
try:
vc.play(stream, after=lambda e: self.queueCheck(ctx, id, vc))
except Exception as e:
text = 'An error occurred while processing this request: ```py\n{}: {}\n```'.format(type(e).__name__, e)
else:
text = "Queue has finished playing!"
self.tracks[id].clear()
queues[id].clear()
print('should show up once')
coro = ctx.send(text)
fut = asyncio.run_coroutine_threadsafe(coro, self.client.loop)
try:
fut.result()
except:
# an error happened while sending the message
pass
async def playSong(self, ctx, url):
with youtube_dl.YoutubeDL(self.YDL_OPTIONS) as ydl:
info = ydl.extract_info(url, download=False)
if 'entries' in info: # if no url is input
url2 = info['entries'][0]['formats'][0]['url']
if ctx.message.guild.id not in self.tracks.keys():
self.tracks[ctx.message.guild.id] = [info['entries'][0]['title']]
else:
self.tracks[ctx.message.guild.id].append(info['entries'][0]['title'])
elif 'formats' in info: # if url is passed
url2 = info['formats'][0]['url']
if ctx.message.guild.id not in self.tracks.keys():
self.tracks[ctx.message.guild.id] = [info['title']]
else:
self.tracks[ctx.message.guild.id].append(info['title'])
#print(*(x for x in self.tracks[ctx.message.guild.id]), sep='\n')
stream = await discord.FFmpegOpusAudio.from_probe(url2, **self.FFMPEG_OPTIONS)
return stream
#commands.command(name='play', help="Plays any song", aliases=['pl'])
async def play(self, ctx, *, url):
if ctx.author.voice is None:
return await ctx.send('You are not in a voice channel!')
if ctx.voice_client is None:
await ctx.author.voice.channel.connect()
vc = ctx.guild.voice_client
guild = ctx.message.guild
if not vc.is_playing() and not self.isPaused:
stream = await self.playSong(ctx, url)
queues[guild.id] = [stream]
vc.play(stream, after=lambda e: self.queueCheck(ctx, guild.id, vc))
await ctx.send('Playing ' + '**' + str(self.tracks[ctx.message.guild.id][0]) + '**')
else:
await self.queue(ctx, url)
async def queue(self, ctx, url):
stream = await self.playSong(ctx, url)
guild = ctx.message.guild
if guild.id in queues:
queues[guild.id].append(stream)
await ctx.send('Added track ' + '**' + str(self.tracks[guild.id][len(self.tracks[guild.id]) - 1]) + '**')
#commands.command(name='queue', help="Shows the current queue", aliases=['q','Q'])
async def showQueue(self, ctx):
if ctx.voice_client is None:
return await ctx.send('I am not connected to a voice channel!')
if len(self.tracks[ctx.message.guild.id]) == 1:
queueEmbed = discord.Embed(title="Queue", description = "Your queue seems to be a tad bit empty :(", color=discord.Colour.random())
queueEmbed.add_field(name=':drum: Currently playing \n' + self.tracks[ctx.message.guild.id][0], value='\u200b', inline=False)
queueEmbed.set_footer(text=f"Requested by {ctx.author.display_name}", icon_url=ctx.author.avatar.url)
await ctx.send(embed=queueEmbed)
elif len(self.tracks[ctx.message.guild.id]) > 0:
queueEmbed = discord.Embed(title="Queue", color=discord.Colour.random())
queuee = ""
if len(self.tracks[ctx.message.guild.id]) != 0:
for i in range(1, len(self.tracks[ctx.message.guild.id])):
queuee += ":white_small_square:" + str(i) + ". " + self.tracks[ctx.message.guild.id][i] + "\n"
else:
queuee = "No songs here"
queueEmbed.add_field(name='Coming up next', value='**' + queuee + '**', inline=False)
queueEmbed.add_field(name=':drum: Currently playing \n' + self.tracks[ctx.message.guild.id][0], value='\u200b', inline=False)
queueEmbed.set_footer(text=f"Requested by {ctx.author.display_name}", icon_url=ctx.author.avatar.url)
await ctx.send(embed=queueEmbed)
else:
await ctx.send('No music in queue')

Related

Getting duplicate Network Response Playwright Python

I have a working script but when I changed the page.on in playwright it actually runs the network response a certain number of times as per the loop count. I have been trying to figure out why that happens.
For example at i=0 it gives one response.url print but at i=10 it prints response.url 10 times and then send 10 duplicate data to mongodb. I have no idea why this is happening. The link being sent based on the print are all the same.
Would be a great help if anyone can let me know what it is that I am doing wrong that is causing this issue.
Pls see sample code here.
#imports here
today = datetime.today().strftime("%m%d%Y")
filenamearr = []
mongousername = 'XXX'
mongopassword = 'XXXX'
client = MongoClient("mongodb+srv://%s:%s#XXXXX.XXXX.mongodb.net/?retryWrites=true&w=majority"%(mongousername,mongopassword))
db = client.DB1
logg = []
async def runbrowser(playwright,url):
async def handle_response(response,buttonnumber):
l = str(response.url)
para = 'param'
if para in l:
print(response.url)
textdata = await response.text()
subtask = asyncio.create_task(jsonparse(textdata))
done, pending = await asyncio.wait({subtask})
if subtask in done:
print("Success in Json parser")
result = await subtask
status = [buttonnumber,result]
logg.append(status)
print(status)
logdf = pd.DataFrame(logg)
logdf.columns = ['BUTTON','RESULT']
fname = 'XXXX' + today +".csv"
logdf.to_csv(fname,index=False)
async def jsonparse(textdata):
try:
#parsing happens here to output to MongoDB
return "Success"
except Exception as e:
print("Failled parsing")
return e
browser = await playwright.firefox.launch(
headless=True,
)
context = await browser.new_context(
locale='en-US',
ignore_https_errors = True,
)
page = await context.new_page()
await page.goto(url,timeout=0)
button = page.locator("xpath=//button[#event-list-item='']")
bcount = button.locator(":scope",has_text="Locator")
count = await bcount.count()
print(count)
for i in range(count):
print("\n\n\n\n\nSleeping 10 seconds before clicking button")
buttonnumber = i
await asyncio.sleep(10)
print("Clickking Button: ", i)
cbtn = bcount.nth(i)
await cbtn.hover()
await asyncio.sleep(4)
await cbtn.click()
if i==0:
print("i=0")
await page.reload(timeout=0)
retry = page.on("response",lambda response: handle_response(response,buttonnumber))
title = await page.title()
print(title)
print("Heading back to the main page.")
await page.go_back(timeout=0)
await page.reload()
await page.wait_for_timeout(5000)
await page.close()
print("Closing Tab")
await browser.close()
async def main():
tasks = []
async with async_playwright() as playwright:
url = 'https://samplelink.com'
tasks.append(asyncio.create_task(runbrowser(playwright,url)))
for t in asyncio.as_completed(tasks):
print(await t)
await asyncio.gather(*tasks)
asyncio.run(main())

heroku-22 stack discord.py bot doesn't play music

I'm making music bot with discord.py and using heroku. bot is playing music my localhost but heroku host is not playing music.
I found what cause a bug.
It working nicely in heroku-20, but not working in heroku-22 stack.
How can I use heroku-22 stack without error?
What can I do?
I'm sorry my english is bad.
my code:
import youtube_dl
import discord
from discord import app_commands,Interaction
import asyncio
import os
class MyClient(discord.Client):
async def on_ready(self):
await self.wait_until_ready()
await tree.sync()
print(f"login at {self.user}")
intents= discord.Intents.all()
client = MyClient(intents=intents)
tree = app_commands.CommandTree(client)
youtube_dl.utils.bug_reports_message = lambda: ''
ytdl_format_options = {
'format': 'bestaudio/best',
'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s',
'restrictfilenames': True,
'noplaylist': True,
'nocheckcertificate': True,
'ignoreerrors': False,
'logtostderr': False,
'quiet': True,
'no_warnings': True,
'default_search': 'auto',
'source_address': '0.0.0.0', # bind to ipv4 since ipv6 addresses cause issues sometimes
}
ffmpeg_options = {
'options': '-vn',
}
ytdl = youtube_dl.YoutubeDL(ytdl_format_options)
class YTDLSource(discord.PCMVolumeTransformer):
def __init__(self, source, *, data, volume=0.5):
super().__init__(source, volume)
self.data = data
self.title = data.get('title')
self.url = data.get('url')
#classmethod
async def from_url(cls, url, *, loop=None, stream=True):
loop = loop or asyncio.get_event_loop()
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream))
if 'entries' in data:
# take first item from a playlist
data=data['entries'][0]
filename = data['url'] if stream else ytdl.prepare_filename(data)
return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data)
queue={}
#tree.command(name="play", description="play music")
async def playmusic(interaction:Interaction,url_title:str,playfirst:bool=False):
await interaction.response.send_message("I'm looking for music!!")
guild=str(interaction.guild.id)
try:
queue[guild]
except KeyError:
queue[guild]=[]
if interaction.user.voice is None:
await interaction.edit_original_response(content="you must join any voice channel")
else:
voice_client: discord.VoiceClient = discord.utils.get(client.voice_clients, guild=interaction.guild)
if voice_client == None:
await interaction.user.voice.channel.connect()
voice_client: discord.VoiceClient = discord.utils.get(client.voice_clients, guild=interaction.guild)
player = await YTDLSource.from_url(url_title, loop=None)
if playfirst and len(queue[guild])>1:
queue[guild].insert(1,player)
else:
queue[guild].append(player)
if not voice_client.is_playing():
voice_client.play(player,after=None)
await interaction.edit_original_response(content=f"{player.title} playing!!")
else:
await interaction.edit_original_response(content=f"{player.title} enqueued!")
await asyncio.sleep(7)
await interaction.delete_original_response()
client.run(token)

How to display the title of the song in the embed?

Here's my code (The bot answers are in Spanish)
I was trying to put the self.info['title'] in the embed description but it was an error that said 'music_cog' object has no attribute 'info':
def search_yt(self, item):
with YoutubeDL(self.YDL_OPTIONS) as ydl:
try:
self.info = ydl.extract_info("ytsearch:%s" % item, download=False)['entries'][0]
except Exception:
return False
return {
'source': self.info['formats'][0]['url'],
'title': self.info['title'],
'channel': self.info['channel']
}
#client.command()
async def p(self, ctx, *args):
embed = discord.Embed(
title = 'Reproduciendo 🎵',
description = 'song_title'
)
query = " ".join(args)
voice_channel = ctx.author.voice.channel
if voice_channel is None:
await ctx.send("Antes debes meterte a un canal de voz")
else:
song = self.search_yt(query)
if type(song) == type(True):
await ctx.send("Hubo un error al intentar reproducir la canción >-<")
else:
await ctx.send(embed=embed)
await ctx.send("**Canción agregada con exito**")
self.music_queue.append([song, voice_channel])
if self.is_playing == True:
await ctx.send('La canción se agrego a la lista de reproducción')
else:
await self.play_music()
await ctx.send("**Reproduciendo**")
Write song = self.search_yt(query) before the embed initialization and create the embed like this:
embed = discord.Embed(
title = "Reproduciendo 🎵",
description = song['title']
)

Command raised an exception: TypeError: unhashable type: 'list' when updating my database

My entire code:
from discord.ext.commands import Bot, CheckFailure, has_role
import discord
import os
import random
from replit import db
from keep_alive import keep_alive
from statistics import mode
from operators import embeds
from datetime import date
#embed preset
'''
embed = discord.Embed(title="title", description="desc", color=PURPLE)
embed.set_author(name="Jäger Bot", icon_url="https://cdn.discordapp.com/avatars/816636186323189780/019dbb41d6f5b301c1fce6980d487f23.webp?size=128")
embed.add_field(name="name", value="value", inline=True)
embed.set_footer(text="requested by " + authormention + "| " + send_date)
await ctx.send(embed=embed)
'''
bot = Bot(command_prefix="j!", help_command=None)
# bot ready and activity
#bot.event
async def on_ready():
print("Bot started")
game = discord.Game("with Jäger")
await bot.change_presence(status=discord.Status.online, activity=game)
# --------------------
PURPLE = 0x800080
STAFF_ROLE_ID = 817476654297383002
SOTW_ROLE_ID = 817458661982994463
FORMER_SOTW_ROLE_ID = 817030310663028736
JAGER_ROLE_ID = 818950349016137739
today = date.today()
global is_voting
is_voting = False
global send_date
send_date = today.strftime("%d-%m-%Y")
#update db
#bot.event
async def update_db(key, value):
if key in db.keys():
old_value = db[key]
old_value.append(value)
db[key] = old_value
else:
db[key] = [value]
#keys:
#nominating_perons ppl who have nominated
#nominated_persons ppl who have been nominated
#voting_perons ppl who have voted
#voted_persons ppl who have been voted for
#----commands----
#help
#bot.command()
async def help(ctx ,category=None):
print("command: help")
staff_category = "staff"
sotw_category = "sotw"
misc_category = "misc"
if category is None:
print("no category")
embed = discord.Embed(title="Select a category with `j!help \"category\"`", description="Prefix = j!", color=PURPLE)
embed.set_author(name="Jäger Bot | Help menu", icon_url="https://cdn.discordapp.com/avatars/816636186323189780/019dbb41d6f5b301c1fce6980d487f23.webp?size=128")
embed.add_field(name="Categories:", value="`staff` `sotw` `misc`", inline=True)
embed.set_footer(text="Made by ZoutigeWolf#0002 | Big thx to gang#5039 for helping")
await ctx.send(embed=embed)
else:
if category == staff_category:
print("staffhelp")
staff = discord.Embed(title="Staff commands", description="prefix = j!", color=PURPLE)
staff.set_author(name="Jäger Bot | Help menu", icon_url="https://cdn.discordapp.com/avatars/816636186323189780/019dbb41d6f5b301c1fce6980d487f23.webp?size=128")
staff.add_field(name="startvote", value="Starts the voting process", inline=False)
staff.add_field(name="finishvote", value="Finishes the voting process", inline=False)
staff.add_field(name="list <key> | debug only", value="Shows all the items in a specific list", inline=False)
staff.add_field(name="clear <key> | debug only", value="Clears all the items in a specific list", inline=False)
staff.add_field(name="ph <key> | debug only", value="Adds a `place_holder` to a specific list", inline=False)
staff.set_footer(text="Made by ZoutigeWolf#0002 | Big thx to gang#5039 for helping")
await ctx.send(embed=staff)
else:
if category == sotw_category:
print("sotwhelp")
sotw = discord.Embed(title="Sotw commands", description="prefix = j!", color=PURPLE)
sotw.set_author(name="Jäger Bot | Help menu", icon_url="https://cdn.discordapp.com/avatars/816636186323189780/019dbb41d6f5b301c1fce6980d487f23.webp?size=128")
sotw.add_field(name="nominate <member>", value="Nominate a member", inline=False)
sotw.add_field(name="vote <member>", value="Vote for a member", inline=False)
sotw.set_footer(text="Made by ZoutigeWolf#0002 | Big thx to gang#5039 for helping")
await ctx.send(embed=sotw)
else:
if category == misc_category:
print("mischelp")
misc = discord.Embed(title="Misc commands", description="prefix = j!", color=PURPLE)
misc.set_author(name="Jäger Bot | Help menu", icon_url="https://cdn.discordapp.com/avatars/816636186323189780/019dbb41d6f5b301c1fce6980d487f23.webp?size=128")
misc.add_field(name="quote", value="A random siege operator quote", inline=False)
misc.add_field(name="profile <operator>", value="Shows the profile of the specified siege operator", inline=True)
misc.add_field(name="shoot <member>", value="Shoot someone", inline=False)
misc.add_field(name="sexy <member>", value="Shows how sexy someone is", inline=False)
misc.set_footer(text="Made by ZoutigeWolf#0002 | Big thx to gang#5039 for helping")
await ctx.send(embed=misc)
else:
print("wrong category")
embed = discord.Embed(title="Select a category with `j!help \"category\"`", description="Prefix = j!", color=PURPLE)
embed.set_author(name="Jäger Bot | Help menu", icon_url="https://cdn.discordapp.com/avatars/816636186323189780/019dbb41d6f5b301c1fce6980d487f23.webp?size=128")
embed.add_field(name="Categories:", value="`staff` `sotw` `miscellaneous`", inline=True)
embed.set_footer(text="Made by ZoutigeWolf#0002 | Big thx to gang#5039 for helping")
await ctx.send(embed=embed)
#help end
#SOTW
#nominate
#bot.command()
async def nominate(ctx, nominatedperson: discord.Member):
print("command: nominate")
print(nominatedperson)
nominated_person = nominatedperson.mention
nominating_person = ctx.author.mention
former_sotw_role = discord.utils.get(ctx.guild.roles, id=FORMER_SOTW_ROLE_ID)
if not is_voting:
print("is_voting was false")
nominated_persons = db["nominated_persons"]
nominating_persons = db["nominating_persons"]
if nominating_person not in nominating_persons:
print("nominating person wasnt in nominating persons")
if nominated_person in nominated_persons:
print("nominated_person was in nominated_persons")
await ctx.send("That member has already been nominated!")
else:
print("nominated_person wasnt in nominated_persons")
former_sotw_role = discord.utils.get(ctx.guild.roles, id=FORMER_SOTW_ROLE_ID)
if former_sotw_role in nominatedperson.roles:
print("nominated_person was former sotw")
await ctx.send("That member has already been SOTW this year!")
else:
print("nominated_person wasnt former sotw")
embed = discord.Embed(title="Member nominated:", description=nominated_person, color=PURPLE)
embed.set_author(name="Jäger Bot", icon_url="https://cdn.discordapp.com/avatars/816636186323189780/019dbb41d6f5b301c1fce6980d487f23.webp?size=128")
embed.add_field(name="By:", value=nominating_person, inline=True)
embed.set_footer(text=send_date)
print(nominated_persons)
await update_db(nominated_persons, nominated_person)
await update_db(nominating_persons, nominating_person)
await ctx.send(embed=embed)
else:
print("nominating_person was in nominating_persons")
await ctx.send("You already nominated someone")
else:
print("is_voting was true")
await ctx.send("You can't nominate while we are voting for the next SOTW!")
#nominate end
#SOTW end
#insert place_holder
#bot.command()
#has_role(STAFF_ROLE_ID)
async def ph(ctx, key):
print("command: ph")
await update_db(key, "place_holder")
await ctx.send("Placeholder has been added to " + key)
#ph.error
async def ph_error(ctx, error):
if isinstance(error, CheckFailure):
await ctx.send("Only staff members can use this command")
#insert place_holder end
#list
#bot.command()
#has_role(STAFF_ROLE_ID)
async def list(ctx, to_list):
print("command: list")
if to_list in db.keys():
requester = ctx.author
requestermention = str(requester)
items = db[to_list]
embed = discord.Embed(title="List", description=to_list, color=PURPLE)
embed.set_author(name="Jäger Bot", icon_url="https://cdn.discordapp.com/avatars/816636186323189780/019dbb41d6f5b301c1fce6980d487f23.webp?size=128")
embed.add_field(name="Items:", value=items, inline=True)
embed.set_footer(text="requested by " + requestermention + " | " + send_date)
await ctx.send(embed=embed)
else:
await ctx.send("That list doesn't exist")
#list.error
async def list_error(ctx, error):
if isinstance(error, CheckFailure):
await ctx.send("Only staff members can use this command")
#list end
#list keys
#bot.command()
async def keys(ctx):
allkeys = db.keys()
await ctx.send(allkeys)
#list keys end
#clear
#bot.command()
#has_role(STAFF_ROLE_ID)
async def clear(ctx, to_clear):
print("command: clear")
str_userid = ctx.author.id
str_zoutigewolfid = "298516275322290188"
userid = int(str_userid)
zoutigewolfid = int(str_zoutigewolfid)
if userid == zoutigewolfid:
if to_clear in db.keys():
del db[to_clear]
await ctx.send("List " + to_clear + " has been cleared")
else:
await ctx.send("That list doesn't exist")
else:
await ctx.send("Only my daddy Wolf can use this command!")
#clear.error
async def clear_error(ctx, error):
if isinstance(error, CheckFailure):
await ctx.send("Only staff members can use this command")
#clear end
#quote
# preset {"title": "", "description": ""},
quotes_list = [
{"title": "A really big fucking hole coming right up!", "description": "Jordan 'Thermite' Trace"},
{"title": "Pass those plates around!", "description":"Julien 'Rook' Nizan"},
{"title": "You can stop worrying about grenades now!", "description": "Marius 'Jäger' Streicher"},
{"title": "if it runs on batteries, I'll see it!", "description": "Monica 'IQ' Weiss"},
{"title": "Fookin' laser sights!", "description": "Mike 'Thatcher' Baker"},
{"title": "Toxic babes are in position!", "description": "James 'Smoke' Porter"},
{"title": "Jammah in position!", "description": "Mark 'Mute' R. Chandar"},
{"title": "EDD primed, let them come!", "description": "Maxim 'Kapkan' Basuda"},
{"title": "Mine flying out!", "description": "Elżbieta 'Ela' Bosak"},
{"title": "You're mine bloody asshole!", "description": "Taina 'Caveira' Pereira"},
{"title": "Malbodan haengdong-iji (말보단 행동이지)", "description": "Chul 'Vigil' Kyung Hwa"},
{"title": "Launching override!", "description": "Grace 'Dokkaebi' Nam"},
{"title": "Camera in position!", "description": "Meghan 'Valkyrie' J. Castellano"},
{"title": "As my friend would say: A really big fucking hole coming right up.", "description": "Yumiko 'Hibana' Imagawa"},
{"title": "Big brother coming in for overwatch!", "description": "Olivier 'Lion' Flament"},
{"title": "Time for a wakeup call", "description": "Grace 'Dokkaebi' Nam"},
{"title": "No runnin' in the halls!", "description": "Morowa 'Clash' Evans"},
{"title": "LMG mounted and loaded!", "description": "Alexsandr 'Tachanka' Senaviev, RIP old tachanka"},
{"title": "Rtila active!", "description": "Jalal 'Kaid' El Fassi"},
{"title": "Now you see me, now you don't!", "description": "Elena 'Mira' María Álvarez"},
{"title": "Why do it yourself when robots do it better?", "description": "Masaru 'Echo' Enatsu"},
{"title": "Bullseye, got us a drone", "description": "Max 'Mozzie' Goose"},
]
#bot.command()
async def quote(ctx):
requester = ctx.author
requestermention = str(requester)
random_index = random.randint(0,21)
quote = quotes_list[random_index]
embed = discord.Embed(**quote, color=PURPLE)
embed.set_footer(text="Requested by " + requestermention + " | " + send_date)
await ctx.send(embed=embed)
#quote end
#operator profile
#bot.command()
async def profile(ctx, operator_name):
await ctx.send(embed=embeds[operator_name])
#operator profile end
#sexy
#bot.command()
async def sexy(ctx, person: discord.Member):
jager_role = discord.utils.get(ctx.guild.roles, id=JAGER_ROLE_ID)
sexyperson = person.mention
if jager_role in person.roles:
print("person was jager")
embed = discord.Embed(title="Sexy meter", description="Lord Jäger is 69420% sexy", color=PURPLE)
await ctx.send(embed=embed)
else:
print("person wasnt jager")
outputint = random.randint(0,100)
output = str(outputint)
embed = discord.Embed(title="Sexy meter", description=sexyperson + " is " + output + "% sexy", color=PURPLE)
await ctx.send(embed=embed)
#sexy end
#gun list
guns_list = [
"MP5",
"M4",
"AK-47",
"MP7",
"SCAR-L",
"Desert Eagle",
"MP5K",
"AUG A2",
"M249",
"AR15"
]
#title list
title_list = [
"Elimination",
"Homicide",
"Assasination",
"Drive-by",
"Sniped",
"Popped",
"Capped",
"No-scoped",
]
#shoot
#bot.command()
async def shoot(ctx, person: discord.Member):
print("command: shoot")
shooter = ctx.author.mention
shotperson = person.mention
shooterid = ctx.author.id
shotpersonid = person.id
randomnumber = random.randint(0,9)
randomgun = guns_list[randomnumber]
randomtitlenumber = random.randint(0,7)
title = title_list[randomtitlenumber]
if shooterid != shotpersonid:
embed = discord.Embed(title=title, description=shooter + " shot " + shotperson + " with " + randomgun, color=PURPLE)
await ctx.send(embed=embed)
else:
await ctx.send("Shooting yourself is a very dumb idea")
#shoot end
#anti nword
racist_words = [
"nigga",
"niggas",
"nigger",
"niggers",
"/Vigga",
"/Viggas",
"/Vigger",
"/Viggers",
"niga",
"nega",
"negga",
"nibba",
"/vigga",
"/viggas",
"/vigger",
"/viggers",
]
# racist detector 9000
"""
#bot.event
async def on_message(msg):
if any(word in msg.content for word in racist_words):
print("someone said the n word")
await msg.channel.send(msg.author.mention + " did you just seriously say the n-word?")
await msg.channel.send("Not poggers bro, not poggers")
await msg.channel.send(f"<#&{STAFF_ROLE_ID}> come get this bitch")
await msg.delete()
await bot.process_commands(msg)
"""
#racist end
#commands end
keep_alive()
bot.run(os.getenv("TOKEN"))
when i do the command j!nominate #discord mention it gives the error "Command raised an exception: TypeError: unhashable type: 'list'" but dont remember hashing any list. can someone please tell me why this is happening? the database is formatted like this ["1", "2", "3"] if you need to know
error:
Ignoring exception in command nominate:
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 148, in nominate
await update_db(nominated_persons, nominated_person)
File "main.py", line 53, in update_db
db[key] = [value]
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/replit/database/database.py", line 182, in __setitem__
r = self.sess.post(self.db_url, data={key: j})
TypeError: unhashable type: 'list'
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: unhashable type: 'list'
Untested but try the following
async def update_db(key, value):
if key in db.keys():
db[key].append(value)
else:
db[key] = [value]
Can you see why you were getting the TypeError by comparing my code with yours?
Ok, thanks for updating the question with the full code and traceback.
The offending line is db[key] = [value] that throws a TypeError:unhashable type list,
which means you passed a list type as key argument for the update_db function.
That cannot be done because, as the traceback clearly states, you cannot hash a list type (meaning you cannot access a dictionary value using a key that is a list type).
But the real source of the pain is right above that line:
if key in db.keys():
key = db[key]
key.append(value)
db[key] = key
That's a lot of key, isn't it? The problem here is that you used the variable name key referring to different things and you ended up with a bit of confusion, so I suggest you use different variables to indicate different things:
async def update_db(key, value):
if key in db.keys():
old_value = db[key]
old_value.append(value)
db[key] = old_value
else:
db[key] = [value]
In this way it is the value that is actually updated in the database and not the key, so the latter would never end up being a list.
This last one is just out of curiosity. Why are you defining a function to update the database, aren't there defined methods to do that? What db are you using?
I FOUND THE ANSWER!
the problem was with await update_db(nominated_persons, nominated_person)
as it is like that, it doesn't update the db because nominated_persons is undefined, so i defined it with nominated_persons = db["nominated_persons"]. but then i would get the hash error because that is a list and i cant use that, so i just did nominated_persons = "nominated_persons" so the nominated_persons is defined as the word "nominated_persons". so now it works
i feel so stupid
here is the updated code:
#bot.command()
async def nominate(ctx, nominatedperson: discord.Member):
print("command: nominate")
nominated_person = nominatedperson.mention
nominated_persons = "nominated_persons"
await update_db(nominated_persons, nominated_person)
await ctx.send("whatever")
(Side note: you can just put “nominated_persons” in the update_db command you don’t have to refer to it with a variable like i did.)

Discord.py music bot raising TypeError when a youtube link is given in the play command

My discord bot raises TypeError when I give a youtube url in the play command.
It works when I give a music name but doesn't work when I give a url like https://youtu.be/ylVnYh-b3Qg......
I could not understand where the problem is...
Is it in my play command or the MusicSource....
Thanks in advance for your kind help.
This is the code I have written:
class MusicSource(discord.PCMVolumeTransformer):
youtube_dl.utils.bug_reports_message = lambda: '' # Suppressing Random Youtube_Dl warnings
ytdl_format_options = { # options for the youtube_dl module, for the audio quality
'format': 'bestaudio/best',
'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s',
'restrictfilenames': True,
'noplaylist': True,
'nocheckcertificate': True,
'ignoreerrors': False,
'logtostderr': False,
'quiet': True,
'no_warnings': True,
'default_search': 'ytsearch', # We will use Youtube for searching musics
'source_address': '0.0.0.0', # IPv6 causes problem sometimes so we are using IPv4
'youtube_include_dash_manifest': False # Turning off dash manifest
# (Enabling it sometimes makes the bot not play anything)
}
ytdl = youtube_dl.YoutubeDL(ytdl_format_options) # Sending the options to the Youtube_DL class
def __init__(self, source: discord.AudioSource, *, data):
self.volume = 0.4
super().__init__(source, self.volume)
self.data = data
self.title = data.get('title')
self.url = data.get('url')
self.link = data.get('webpage_url') # Fetching the youtube link for the song and
# will be used later for sending it to the user
self.time = data.get('duration')
self.img = data.get('thumbnail')
self.artist = data.get('artist')
self.likes = data.get('like_count')
self.dislikes = data.get('dislike_count')
self.albm = data.get('album')
#classmethod
async def from_url(cls, url, *, loop=None, stream=False, timestamp=0): # The player that plays the
# audio from the url
ffmpeg_options = {
'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
'options': f'-vn -ss {timestamp}'
}
loop = loop or asyncio.get_event_loop()
data = await loop.run_in_executor(None, lambda: cls.ytdl.extract_info(url, download=not stream))
if 'entries' in data:
data = data['entries'][0] # Taking the first item from the search results
filename = data['url'] if stream else cls.ytdl.prepare_filename(data)
return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data)
And the join and play command:
class Music(commands.Cog):
def __init__(self, client):
self.client = client
self.player = dict()
self.links = dict()
self.auto_loop_is_on = dict()
#commands.command(name="join", aliases=["j", "connect", "come", "fuck-on"])
async def join_voice(self, ctx: commands.Context):
voice_channel = ctx.author.voice
if voice_channel is None:
return await ctx.send("`Please connect to a voice channel first!`")
if ctx.voice_client is not None:
await ctx.voice_client.move_to(voice_channel.channel)
return await ctx.send("`Voice channel shifted!`")
elif ctx.voice_client is None:
self.player[str(ctx.guild.id)] = None
self.links[str(ctx.guild.id)] = list()
self.auto_loop_is_on[str(ctx.guild.id)] = False
await voice_channel.channel.connect()
return await ctx.send("`Voice channel connected! Use <play> command to play a music`")
#commands.command(name="play", aliases=["p"])
async def play_(self, ctx: commands.Context, timestamp: Optional[int] = 0, *, url):
if ctx.voice_client is None or ctx.author.voice is None:
return await ctx.send("`Not connected to any voice!`")
if ctx.voice_client.is_playing():
self.links[str(ctx.guild.id)].append(url)
await ctx.send(f"`Song {url} added to queue. `")
elif not ctx.voice_client.is_playing():
self.links[str(ctx.guild.id)].append(url)
await ctx.send("`Loading awesomeness! Wait a bit. `")
async with ctx.typing():
self.player[str(ctx.guild.id)] = await MusicSource.from_url(url=self.links[str(ctx.guild.id)][0],
loop=self.client.loop, stream=True,
timestamp=timestamp)
ctx.voice_client.play(self.player[str(ctx.guild.id)], after=lambda x: self.play_next(ctx))
And the Error I get:
Ignoring exception in on_command_error
Traceback (most recent call last):
File "C:\Users\Ronny\Python3.9\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "C:\Users\Ronny\PycharmProjects\XENON_DISCORD\Bot_Features\music.py", line 108, in play_
ctx.voice_client.play(self.player[str(ctx.guild.id)], after=None)
File "C:\Users\Ronny\Python3.9\lib\site-packages\discord\voice_client.py", line 561, in play
raise TypeError('source must an AudioSource not {0.__class__.__name__}'.format(source))
TypeError: source must an AudioSource not NoneType
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\Ronny\Python3.9\lib\site-packages\discord\client.py", line 343, in _run_event
await coro(*args, **kwargs)
File "C:\Users\Ronny\PycharmProjects\XENON_DISCORD\XENON.py", line 82, in on_command_error
raise err
File "C:\Users\Ronny\Python3.9\lib\site-packages\discord\ext\commands\bot.py", line 902, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\Ronny\Python3.9\lib\site-packages\discord\ext\commands\core.py", line 864, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\Ronny\Python3.9\lib\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: source must an AudioSource not NoneType
Try this out, it should work for both a YouTube song name and a YouTube URL:
import asyncio
import discord
import youtube_dl
from discord.ext import commands
# Suppress noise about console usage from errors
youtube_dl.utils.bug_reports_message = lambda: ''
ytdl_format_options = {
'format': 'bestaudio/best',
'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s',
'restrictfilenames': True,
'noplaylist': True,
'nocheckcertificate': True,
'ignoreerrors': False,
'logtostderr': False,
'quiet': True,
'no_warnings': True,
'default_search': 'auto',
'source_address': '0.0.0.0' # bind to ipv4 since ipv6 addresses cause issues sometimes
}
ffmpeg_options = {
'options': '-vn'
}
ytdl = youtube_dl.YoutubeDL(ytdl_format_options)
class YTDLSource(discord.PCMVolumeTransformer):
def __init__(self, source, *, data, volume=0.5):
super().__init__(source, volume)
self.data = data
self.title = data.get('title')
self.url = data.get('url')
#classmethod
async def from_url(cls, url, *, loop=None, stream=False):
loop = loop or asyncio.get_event_loop()
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream))
if 'entries' in data:
# take first item from a playlist
data = data['entries'][0]
filename = data['url'] if stream else ytdl.prepare_filename(data)
return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data)
class Music(commands.Cog):
def __init__(self, bot):
self.bot = bot
#commands.command(description="joins a voice channel")
async def join(self, ctx):
if ctx.author.voice is None or ctx.author.voice.channel is None:
return await ctx.send('You need to be in a voice channel to use this command!')
voice_channel = ctx.author.voice.channel
if ctx.voice_client is None:
vc = await voice_channel.connect()
else:
await ctx.voice_client.move_to(voice_channel)
vc = ctx.voice_client
#commands.command(description="streams music")
async def play(self, ctx, *, url):
async with ctx.typing():
player = await YTDLSource.from_url(url, loop=self.bot.loop, stream=True)
ctx.voice_client.play(player, after=lambda e: print('Player error: %s' % e) if e else None)
await ctx.send('Now playing: {}'.format(player.title))

Categories

Resources