object has no attribute 'to_components' - discord

I'm trying to make a blackjack command for my Discord Bot in python, I'm making small codes and little by little testing and improving, see below:
import discord
from discord.ext import commands
from discord import app_commands
import random, json, datetime
class bj(discord.ui.Button):
def __init__(self, game ,gamesum, player_cards):
super().__init__()
self.value = None
#discord.ui.button (label="Hit", style=discord.ButtonStyle.blurple)
async def confirm(self, button: discord.ui.Button, interaction: discord. Interaction):
self.value = True
self.stop()
value_1=["A", 1,2,3,4,5,6,7,8,9,10,"J","Q","K",]
nype_1=["♦️","♠️","♥️","♣️"]
card_value_3 = random.randint(0, len(value_1) - 1)
nype_card_3 = random.randint(0, len(nype_1) - 1)
card_3 = f"{card_value_3[card_value_3]} {card_value_3[nype_card_3]}"
await match.edit()
match.edit_field(name='Your hand', value=f"{player_cards} {card_value_3}{nype_card_3}")
if type(card_value_3)==str:
if value_card_3=="A":
value_letter_3=11
else:
value_letter_3=10
else:
value_letter_3=value_card_3
class client(discord.Client):
def __init__(self):
super().__init__(intents=discord.Intents.default())
self.synced = False
async def setup_hook(self) -> None:
self.add_view(DropdownView())
async def on_ready(self):
await aclient.change_presence(activity = discord.Streaming(name = "/news", url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"))
await self.wait_until_ready()
if not self.synced:
await tree.sync()
self.synced = True
print(f"We entered as {self.user}!")
print(f"That has the ID {self.user.id}")
client = client()
tree = app_commands.CommandTree(aclient)
#tree.command(name='blackjack', description='Play a game of blackjack')
async def blackjack(interaction: discord.Interaction, amount:int):
await open_account(interaction.user)
money = await add_money(interaction.user)
if amount>money[0]:
await interaction.response.send_message(f"You don't have all this amount {interaction.user.mention}.")
else:
if quantity<0:
await interaction.response.send_message(f"You must enter a positive value")
else:
value_1=["A",2,3,4,5,6,7,8,9,10,'J','Q',"K"]
nype_1=["♦️","♠️","♥️","♣️"]
value_card_a = random.randint(0, len(value_1) - 1)
nype_card_a = random.randint(0, len(nype_1) - 1)
letter_a = f"{value_1[value_card_a]}{nype_1[nype_letter_a]}"
b_card_value = random.randint(0, len(1_value) - 1)
nype_card_b = random.randint(0, len(nype_1) - 1)
letter_b = f"{value_1[value_card_b]}{nype_1[nype_letter_a]}"
player_cards = f"{card_a} {card_b}"
if type(value_card_a)==str:
if value_card_a=="A":
value_letter_a=11
else:
value_letter_a=10
else:
value_card_a=value_card_a
if type(value_card_b)==str:
if value_card_b=="A":
value_letter_b=11
else:
value_letter_b=10
else:
value_card_b=value_card_b
sum_of_game=value_card_a+value_card_b
await add_money(interaction.user, -1*amount)
if sum_of_game==21:
result='Blackjack'
titulo_resultado=f'You won ~~K~~ {1.5*amount}'
else:
result=sum_of_game
titulo_resultado=f'You invested ~~K~~ {amount} in this blackjack'
departure=discord.Embed(
description=f'{result_title}',
colour=discord.Color.random()
)
match.add_field(name='Your hand', value=f"{player_cards}\n{result}")
if result=='Blackjack':
await add_money(interaction.user, 1.5*amount)
await interaction.response.send_message(embed=game, view=bj(game ,gamesum, player_cards))
async def open_account(user):
users = await bank_data()
if str(user.id) in users:
return False
else:
users[str(user.id)] = {}
users[str(user.id)]['wallet'] = 0
users[str(user.id)]['bank']= 0
with open("money.json", "w") as f:
json.dump(users, f)
return true
async def bank_data():
with open("money.json", "r") as f:
users = json.load(f)
return users
async def add_money(user, change=0, mode = "wallet"):
users = await bank_data()
users[str(user.id)][mode] +=change
with open("money.json", "w") as f:
json.dump(users, f)
money = [users[str(user.id)]["wallet"], users[str(user.id)]["bank"]]
return money
aclient.run(Token)
But in await interaction.response.send_message(embed=match, view=bj(match ,game_sum, player_cards)) is reporting the error
2023-02-06 19:14:31 ERROR discord.app_commands.tree Ignoring exception in command 'blackjack'
Traceback (most recent call last):
File "/home/runner/Kllin/venv/lib/python3.10/site-packages/discord/app_commands/commands.py", line 862, in _do_call
return await self._callback(interaction, **params) # type: ignore
File "main.py", line 1155, in blackjack
await interaction.response.send_message(embed=partida, view=bj(partida ,soma_de_jogo, cartas_jogador))
File "/home/runner/Kllin/venv/lib/python3.10/site-packages/discord/interactions.py", line 754, in send_message
params = interaction_message_response_params(
File "/home/runner/Kllin/venv/lib/python3.10/site-packages/discord/webhook/async_.py", line 577, in interaction_message_response_params
data['components'] = view.to_components()
AttributeError: 'bj' object has no attribute 'to_components'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/runner/Kllin/venv/lib/python3.10/site-packages/discord/app_commands/tree.py", line 1242, in _call
await command._invoke_with_namespace(interaction, namespace)
File "/home/runner/Kllin/venv/lib/python3.10/site-packages/discord/app_commands/commands.py", line 887, in _invoke_with_namespace
return await self._do_call(interaction, transformed_values)
File "/home/runner/Kllin/venv/lib/python3.10/site-packages/discord/app_commands/commands.py", line 880, in _do_call
raise CommandInvokeError(self, e) from e
discord.app_commands.errors.CommandInvokeError: Command 'blackjack' raised an exception: AttributeError: 'bj' object has no attribute 'to_components'
I tried to interpret the error, as I recently started programming, it didn't help much, I asked in ChatGPT, and it also didn't help much (the error didn't even change), so the artificial intelligence itself suggested that I come and ask here, I hope it helps me help(Oh, and sorry for not leaving everything organized and well separated, they said there was a lot of code and little information).

Related

Playlist playback error. Discord py. Youtube dl

I'm writing a Discord bot to play music
When trying to play a playlist, it throws the error 'Command raised an exception: KeyError: 'webpage_url'. What could be the problem?
It won't even load the first video
def __init__(self, ctx: commands.Context, source: discord.FFmpegPCMAudio, *, data: dict, volume: float = 0.5):
super().__init__(source, volume)
self.requester = ctx.author
self.channel = ctx.channel
self.data = data
self.title = data.get('title')
self.tags = data.get('tags')
self.url = data.get('webpage_url')
self.stream_url = data.get('url')
def __str__(self):
return '**{0.title}** by **{0.uploader}**'.format(self)
#classmethod
async def create_source(cls, ctx: commands.Context, search: str, *, loop: asyncio.BaseEventLoop = None):
loop = loop or asyncio.get_event_loop()
partial = functools.partial(cls.ytdl.extract_info, search, download=False, process=False)
data = await loop.run_in_executor(None, partial)
if data is None:
raise YTDLError('Couldn\'t find anything that matches `{}`'.format(search))
if 'entries' not in data:
process_info = data
else:
process_info = None
for entry in data['entries']:
if entry:
process_info = entry
break
if process_info is None:
raise YTDLError('Couldn\'t find anything that matches `{}`'.format(search))
webpage_url = process_info['webpage_url']
partial = functools.partial(cls.ytdl.extract_info, webpage_url, download=False)
processed_info = await loop.run_in_executor(None, partial)
if processed_info is None:
raise YTDLError('Couldn\'t fetch `{}`'.format(webpage_url))
if 'entries' not in processed_info:
info = processed_info
else:
info = None
while info is None:
try:
info = processed_info['entries'].pop(0)
except IndexError:
raise YTDLError('Couldn\'t retrieve any matches for `{}`'.format(webpage_url))
return cls(ctx, discord.FFmpegPCMAudio(info['url'], **cls.FFMPEG_OPTIONS), data=info)
i'm newbie. sorry for what might be a stupid question

snipe command not sniping messages

I found a command that sends the latest deleted message. While testing I found that when I delete a message it sends a traceback error to the console. Here's the traceback error and code.
Ignoring exception in on_message_delete
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/client.py", line 343, in _run_event
await coro(*args, **kwargs)
File "/home/runner/Isla/cogs/awp.py", line 21, in on_message_delete
if msg.author.client:
AttributeError: 'Member' object has no attribute 'client'
import discord
from discord.ext import commands
import datetime
import editdistance
import re
invitere = r"(?:https?:\/\/)?discord(?:\.gg|app\.com\/invite)?\/(?:#\/)([a-zA-Z0-9-]*)"
invitere2 = r"(http[s]?:\/\/)*discord((app\.com\/invite)|(\.gg))\/(invite\/)?(#\/)?([A-Za-z0-9\-]+)(\/)?"
class Awp(commands.Cog):
def __init__(self, client):
self.client = client
self.snipes = {}
#client.listen('on_message_delete')
async def on_message_delete(msg):
if msg.author.client:
return
self.snipes[msg.channel.id] = msg
#client.listen('on_message_edit')
async def on_message_edit(before, after):
if before.author.client or after.author.client:
return # DEPARTMENT OF REDUNDANCY DEPARTMENT
if (editdistance.eval(before.content, after.content) >= 10) and (
len(before.content) > len(after.content)):
self.snipes[before.channel.id] = [before, after]
#commands.Cog.listener()
async def on_ready(self):
print('Gifs bot is online.')
def sanitise(self, string):
if len(string) > 1024:
string = string[0:1021] + "..."
string = re.sub(invitere2, '[INVITE REDACTED]', string)
return string
#commands.command()
async def awp(self, ctx):
'"Snipes" someone\'s message that\'s been edited or deleted.'
try:
snipe = self.snipes[ctx.channel.id]
except KeyError:
return await ctx.send('No snipes in this channel!')
if snipe is None:
return await ctx.send('No snipes in this channel!')
# there's gonna be a snipe after this point
emb = discord.Embed()
if type(snipe) == list: # edit snipe
emb.set_author(
name=str(snipe[0].author),
icon_url=snipe[0].author.avatar_url)
emb.colour = snipe[0].author.colour
emb.add_field(
name='Before',
value=self.sanitise(snipe[0].content),
inline=False)
emb.add_field(
name='After',
value=self.sanitise(snipe[1].content),
inline=False)
emb.timestamp = snipe[0].created_at
else: # delete snipe
emb.set_author(
name=str(snipe.author),
icon_url=snipe.author.avatar_url)
emb.description = self.sanitise(snipe.content)
emb.colour = snipe.author.colour
emb.timestamp = snipe.created_at
emb.set_footer(
text=f'Message sniped by {str(ctx.author)}',
icon_url=ctx.author.avatar_url)
await ctx.send(embed=emb)
self.snipes[ctx.channel.id] = None
def setup(client):
client.add_cog(Awp(client))
You simply have to change message.author.client to message.author.bot, regardless of you using client or bot.
References:
discord.Member

pymongo.errors.ConfigurationError: A DNS label is empty

I'm making discord bot with python. I was making leveling system using database (https://account.mongodb.com/) and I got this syntax error: pymongo.errors.ConfigurationError: A DNS label is empty. Please help me.
main.py:
import os
import discord
import datetime
import levelsys
intents = discord.Intents.all()
bot = commands.Bot(command_prefix='$', intents=intents)
cogs = [levelsys]
for i in range(len(cogs)):
cogs[i].setup(bot)
# Setting permissions that a user should have to execute this command.
print('Server Running')
bot.run(os.getenv('token'))
levelsys.py:
import discord
from discord.ext import commands
from pymongo import MongoClient
import urllib.parse
bot_channel = 798127930295058442
talk_channels = [690995360834912327]
level = ['new', 'old_new', 'Master Oogway']
levelnum = [5, 15, 30]
intents = discord.Intents.all()
bot = commands.Bot(command_prefix='$', intents=intents)
cluster = MongoClient("mongodb+srv://Myself:" + urllib.parse.quote("stackoverflow") + "#cluster0.4h226.mongodb.n...")
leveling = cluster["discord"]["leveling"]
class levelsys(commands.Cog):
def __init__(self, bot):
self.bot = bot
#commands.Cog.listener()
async def on_ready(self):
print('ready!')
#commands.Cog.listener()
async def on_message(self, message):
if message.channel.id in talk_channels:
stats = leveling.find_one({"id": message.author.id})
if not message.author.bot:
if stats is None:
newuser = {"id": message.auhor.id, "xp": 100}
leveling.insert_one(newuser)
else:
xp = stats["xp"] + 5
leveling.update_one({"id": message.author.id}, {"set":{"xp":xp}})
lvl = 0
while True:
if xp < ((50*(lvl**2))+(50*(lvl-1))):
break
lvl += 1
xp -= ((50*(lvl**2))+(50*(lvl-1)))
if xp == 0:
await message.channel.send(f"Well done {message.author.mention}: you advanced to **level: {lvl}**!")
for i in range(len(level)):
if lvl == levelnum[1]:
await message.author.add_roles(discord.utils.get(message.author.guild.roles, name=level[i]))
embed = discord.Embed(
description= f"{message.author.mention} you have gotten role **{level[i]}**!!!"
)
embed.set_thumbnail(url=message.author.avatar_url)
await message.channel.send(embed=embed)
#commands.command()
async def rank(self, ctx):
if ctx.channel.id == bot_channel:
stats = leveling.find_one({"id": ctx.author.id})
if stats is None:
embed = discord.Embed(description="You need to write more messages to get the rank!")
await ctx.channel.send(embed=embed)
else:
xp = stats["xp"]
lvl = 0
rank = 0
while True:
if xp < ((50*(lvl**2))+(50*lvl)):
break
lvl += 1
xp -= ((50*((lvl-1)**2))+(50*(lvl-1)))
boxes = int((xp/(200*((1/2)*lvl)))*20)
rankings = leveling.find().sort("xp",-1)
for x in rankings:
rank += 1
if stats["id"] == x["id"]:
break
embed = discord.Embed(title="{}'s level stats".format(ctx.author.name))
embed.add_field(name="Name", value=ctx.author.mention, inline=True)
embed.add_field(name="Xp", value=f"{xp}/{int(200*((1/2)*lvl))}", inline=True)
embed.add_field(name="Rank", value=f"{rank}/{ctx.guild.member_count}", inline=True)
embed.add_field(name="Level Bar", value=boxes*":blue_square:"+ (20-boxes)* ":white_large_square:", inline=False)
embed.set_thumbnail(url=ctx.author.avatar_url)
await ctx.channel.send(embed=embed)
#commands.command()
async def leaderboard(self, ctx):
if (ctx.channel.id == bot_channel):
rankings = leveling.find().sort("xp",-1)
i=1
embed = discord.Embed(title="Rankings:")
for x in rankings:
try:
temp = ctx.quild.get_member(x["id"])
tempxp = x["xp"]
embed.add_field(name=f"{i}: {temp.name}", value=f"Total XP: {tempxp}", inline= False)
i+=1
except:
pass
if i == 11:
break
await ctx.channel.send(embed=embed)
def setup(bot):
bot.add_cog(levelsys(bot))
error:
pymongo.errors.ConfigurationError: A DNS label is empty.
Please help me a little and tell me if there are other errors I need to fix. Thank you very much!
At a guess your issue is with the connection string; mongodb in "SRV" mode uses DNS to determine the replicaset / shard details.

When I use the play command on my discord bot nothing happens

I am new to using discord.py but have experience using python. I am currently working on a discord music bot using discord.py and when I use the command "*play (song name)" nothing happens even though the bot is in the VC. I want the bot to be able to search youtube for the user's request and play it like any other music bot on discord like Rythum or Groovy. Any other suggestions you have for the code would be greatly appreciated as well. Thanks!
here is my code:
import discord
from discord.ext import commands, tasks
import youtube_dl
import asyncio
from random import choice
client = commands.Bot(command_prefix='*')
queue=[]
status = '18 Naked Cowboys'
#client.event
async def on_ready():
print("Rancher is online!")
await client.change_presence(activity=discord.Activity(type=discord.ActivityType.watching,name=status))
#client.command(name='ping',help='This command will show that my ping is superior than yours!')
async def ping(ctx):
await ctx.send(f'**Pong!** Latency: {round(client.latency * 1000)}ms')
#client.command(name='hello',help='This command returns a random the welcome message!')
async def hello(ctx):
responses = ['***grumble*** Why you wake me up?!','Penis']
await ctx.send(choice(responses))
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)
#client.command(name='join', help='This command makes the bot join the voice channel')
async def join(ctx):
if not ctx.message.author.voice:
await ctx.send("You are not connected to a voice channel")
return
else:
channel = ctx.message.author.voice.channel
await channel.connect()
#client.command(name='queue', help='This command adds a song to the queue')
async def queue_(ctx, url):
global queue
queue.append(url)
await ctx.send(f'`{url}` added to queue!')
#client.command(name='remove', help='This command removes an item from the list')
async def remove(ctx, number):
global queue
try:
del(queue[int(number)])
await ctx.send(f'Your queue is now `{queue}!`')
except:
await ctx.send('Your queue is either **empty** or the index is **out of range**')
#client.command(name='play', help='This command plays songs')
async def play(ctx):
global queue
server = ctx.message.guild
voice_channel = server.voice_client
async with ctx.typing():
player = await YTDLSource.from_url(queue[0], loop=client.loop)
voice_channel.play(player, after=lambda e: print('Player error: %s' % e) if e else None)
await ctx.send('**Now playing:** {}'.format(player.title))
del(queue[0])
#client.command(name='pause', help='This command pauses the song')
async def pause(ctx):
server = ctx.message.guild
voice_channel = server.voice_client
voice_channel.pause()
#client.command(name='resume', help='This command resumes the song!')
async def resume(ctx):
server = ctx.message.guild
voice_channel = server.voice_client
voice_channel.resume()
#client.command(name='view', help='This command shows the queue')
async def view(ctx):
await ctx.send(f'Your queue is now `{queue}!`')
#client.command(name='leave', help='This command stops makes the bot leave the voice channel')
async def leave(ctx):
voice_client = ctx.message.guild.voice_client
await voice_client.disconnect()
#client.command(name='stop', help='This command stops the song!')
async def stop(ctx):
server = ctx.message.guild
voice_channel = server.voice_client
voice_channel.stop()
client.run('')
You haven't assign anything to queue list. So you might need to modify play function a bit and append the url from user input to your queue. Here is an example of what the user will input *play https://youtube.com/watch?v=abcdefghij. And here's the code:
#client.command(name='play', help='This command plays songs')
async def play(ctx, *, search_url):
global queue
queue.append(search_url)
server = ctx.message.guild
voice_channel = server.voice_client
async with ctx.typing():
player = await YTDLSource.from_url(queue[0], loop=client.loop)
voice_channel.play(player, after=lambda e: print('Player error: %s' % e) if e else None)
await ctx.send('**Now playing:** {}'.format(player.title))
del(queue[0])

Discord bot ctx is being displayed as argument

Thats a test code where im trying to work in classes. Even tho in commands it displayes ctx as required arg instead and it works only if i put it before self.
class Quiz:
def __init__(self, question, answer):
self.question = question
self.answer = answer
#bot.command(pass_context=True)
async def quiz(self, ctx):
fido = Quiz("Starter mass?", "yeah")
nope = Quiz("WHAT?", "lel")
await ctx.send(fido.question)
def check(m):
return m.content == 'heh'
msg = await bot.wait_for('message', check=check)
await ctx.send('Right {.author}!'.format(msg))
Error:
discord.ext.commands.errors.MissingRequiredArgument: ctx is a required argument that is missing.
How can I fix this?
As crazy as it sounds, remove the self argument from your method. The commands decorator will take care of this. (You can also use a command cog)
class Quiz:
def __init__(self, question, answer):
self.question = question
self.answer = answer
#bot.command(pass_context=True)
async def quiz(ctx):
fido = Quiz("Starter mass?", "yeah")
nope = Quiz("WHAT?", "lel")
await ctx.send(fido.question)
def check(m):
return m.content == 'heh'
msg = await bot.wait_for('message', check=check)
await ctx.send('Right {.author}!'.format(msg))
Also your check function doesn't work correctly. It always uses the fido question and says you are correct only after responding with 'heh'.
#bot.command(pass_context=True)
async def quiz(ctx):
fido = Quiz("Starter mass?", "yeah")
nope = Quiz("WHAT?", "lel")
question = random.choice((fido, nope))
await ctx.send(question.question)
check = lambda m: m.content.lower() == question.answer
msg = await bot.wait_for('message', check=check)
await ctx.send(f'Right **{msg.author.name}**!')

Resources