DISCORD.PY Ticket System error how to fix - discord.py

i learned how to make a ticket system from some github user and I implemented the same code it worked perfectly like creating a ticket channel but there is a problem when i clicked the reaction to close my ticket and to delete my ticket channel which was created by the bot but it didn't delete the channel
here is the code:
#client.event
async def on_reaction_add(reaction, user):
if 'React with :ticket: to create a ticket' in reaction.message.embeds[0].description and reaction.emoji == '🎫' and not user.bot:
role = discord.utils.get(user.guild.roles, name="#everyone")
chan = await user.guild.create_text_channel(name=f'ticket - {user}')
await chan.set_permissions(role, send_messages=False, read_messages=False, add_reactions=False, embed_links=False, attach_files=False, read_message_history=False, external_emojis=False)
await chan.set_permissions(user, send_messages=True, read_messages=True, add_reactions=True, embed_links=True, attach_files=True, read_message_history=True, external_emojis=True)
embed = discord.Embed(
title="Ticket",
description="React with :lock: to close a ticket",
color=0x00FFFF
)
embed.set_footer(text="Ticket system")
msg = await chan.send(embed=embed)
await msg.add_reaction("🔒")
if 'React with :lock: to close a ticket' in reaction.message.embeds[0].description and reaction.emoji == '🔒' and not user.bot:
await channel.delete()
#client.command()
#commands.has_permissions(administrator=True)
async def ticket(ctx, channel: discord.TextChannel = None):
if channel==None:
await ctx.channel.purge(limit=1)
embed = discord.Embed(
title="Ticket",
description="React with :ticket: to create a ticket",
color=0
)
embed.set_footer(text="Ticket system")
msg = await ctx.send(embed=embed)
await msg.add_reaction("🎫")
else:
await ctx.channel.purge(limit=1)
embed = discord.Embed(
title="Ticket",
description="React with :ticket: to create a ticket",
color=0
)
embed.set_footer(text="Ticket system")
msg = await channel.send(embed=embed)
await msg.add_reaction("🎫")

You are trying to do await channel.delete() but you haven't defined channel variable. Replace it with await reaction.message.channel.delete().
Also note that
chan = await user.guild.create_text_channel(name=f'ticket - {user}')
await chan.set_permissions(role, send_messages=False, read_messages=False, add_reactions=False, embed_links=False, attach_files=False, read_message_history=False, external_emojis=False)
await chan.set_permissions(user, send_messages=True, read_messages=True, add_reactions=True, embed_links=True, attach_files=True, read_message_history=True, external_emojis=True)
is very slow and it isn't a good practice.
You can create channel with specific overwrites at once:
overwrites = {
role: discord.PermissionOverwrite(read_messages=False),
user: discord.PermissionOverwrite(send_messages=True, read_messages=True, add_reactions=True, embed_links=True, attach_files=True, read_message_history=True, external_emojis=True)
}
chan = await user.guild.create_text_channel(name=f"ticket - {user}", overwrites=overwrites)
And you don't need to set up other permissions for role if read_messages=False.

Related

Python integration aiogram + Socket.IO Server

The question arose how to correctly call the functions seo.edit(), so.and(), sio.call() in the aiogram function.
Is it possible to implement such code somehow:
`
#dp.message_handler()
async def process_start_command(message: types.Message):
await sio.send(message.text)
await message.reply('Готово')
`
The connection between the Client and the Server was successfully created.
server.py:
from aiohttp import web
import socketio
sio = socketio.AsyncServer(logger=True, engineio_logger=True)
app = web.Application()
sio.attach(app)
#sio.on('message')
async def print_message(sid, message):
print('\n' + "ID: " , sid)
print(message)
#sio.event()
async def connect(sid, environ):
print(f'Соединение с {sid} установленно')
if __name__ == '__main__':
web.run_app(app)
client.py:
import asyncio
import socketio
sio = socketio.AsyncClient(logger=True, engineio_logger=True)
#sio.event
async def message(data):
print('Получил сообщение ', data)
async def main():
await sio.connect('http://localhost:8080')
await sio.wait()
if __name__ == '__main__':
asyncio.run(main())

RuntimeWarning: coroutine 'my_after' was never awaited (discord.py)

guys. my code gives the error "RuntimeWarning: coroutine 'my_after' was never awaited". I am using my_after and serverQueue functions to create a queue in my music bot. the problem occurs in "voice.play (FFmpegPCMAudio (URL, ** FFMPEG_OPTIONS), after = lambda e: my_after (voice, message))". everything works correctly only when there is one song in the queue. the rest should be automatically loaded from the queue, which does not happen. when one song ends, the next song is not playing due to an error. but if you use the "& skip" command, the next song in the queue will start playing.
async def play(video_link, voice, message):
with YoutubeDL(YDL_OPTIONS) as ydl:
info = ydl.extract_info(video_link, download = False)
print(info.get('title'))
URL = info['formats'][0]['url']
voice.play(FFmpegPCMAudio(URL, **FFMPEG_OPTIONS), after = lambda e: my_after(voice, message))
voice.is_playing()
await message.channel.send('**Now playing** - ' + info.get('title'))
queue = []
async def my_after(voice, message):
coro = await musicQueue(voice, message)
await asyncio.run_coroutine_threadsafe(coro).result()
async def serverQueue(voice, message):
if ( queue != [] and not voice.is_playing() ):
await play(queue.pop(0), voice, message)
async def skip(voice, message):
voice.stop()
await serverQueue(voice, message)
#client.event
async def on_message(message):
if message.author == client.user:
return
voice = get(client.voice_clients, guild=message.channel.guild)
if message.content.startswith('&' + 'join'):
await join(message)
if message.content.startswith('&' + 'play'):
arg = message.content[:0] + message.content[6:]
await join(message)
voice = get(client.voice_clients, guild=message.channel.guild)
if arg.startswith('https:'):
video_link = arg
if voice.is_playing() == False:
await play(video_link, voice, message)
else:
await message.channel.send('added to queue')
queue.append(video_link)
The error explains it. You didn't awaited the asynchronous function.
Change this:
after = lambda e: my_after(voice, message))
To this:
after = lambda e: asyncio.run(my_after(voice, message))

Discord.py how could you turn these reactions into buttons?

Hey how would you be able to turn these reactions into buttons, I would like something like this: https://cdn.upload.systems/uploads/A6AXyuYA.png
I dont understand buttons that much, im in a little hurry to do this for my friend but i take a while to learn things, any help would be appreciated!
The part I wanna turn reactions to buttons to is the config menu part.
Code:
import asyncio
import copy
import dateutil
import discord
from discord.ext import commands
from discord.ext.commands.view import StringView
from core import checks
from core.models import DummyMessage, PermissionLevel
from core.utils import normalize_alias
class Menu(commands.Cog):
"""Reaction-based menu for threads"""
def __init__(self, bot):
self.bot = bot
self.db = self.bot.plugin_db.get_partition(self)
#commands.Cog.listener()
async def on_thread_ready(self, thread, creator, category, initial_message):
"""Sends out menu to user"""
menu_config = await self.db.find_one({'_id': 'config'})
if menu_config:
message = DummyMessage(copy.copy(initial_message))
message.author = self.bot.modmail_guild.me
message.content = menu_config['content']
msg, _ = await thread.reply(message)
for r in menu_config['options']:
await msg.add_reaction(r)
await asyncio.sleep(0.3)
try:
reaction, _ = await self.bot.wait_for('reaction_add', check=lambda r, u: r.message == msg and u == thread.recipient and str(r.emoji) in menu_config['options'], timeout=120)
except asyncio.TimeoutError:
message.content = 'No reaction received in menu... timing out'
await thread.reply(message)
else:
alias = menu_config['options'][str(reaction.emoji)]
ctxs = []
if alias is not None:
ctxs = []
aliases = normalize_alias(alias)
for alias in aliases:
view = StringView(self.bot.prefix + alias)
ctx_ = commands.Context(prefix=self.bot.prefix, view=view, bot=self.bot, message=message)
ctx_.thread = thread
discord.utils.find(view.skip_string, await self.bot.get_prefix())
ctx_.invoked_with = view.get_word().lower()
ctx_.command = self.bot.all_commands.get(ctx_.invoked_with)
ctxs += [ctx_]
for ctx in ctxs:
if ctx.command:
old_checks = copy.copy(ctx.command.checks)
ctx.command.checks = [checks.has_permissions(PermissionLevel.INVALID)]
await self.bot.invoke(ctx)
ctx.command.checks = old_checks
continue
#checks.has_permissions(PermissionLevel.MODERATOR)
#commands.command()
async def configmenu(self, ctx):
"""Creates a new menu"""
config = {}
try:
await ctx.send('What is the menu message?')
m = await self.bot.wait_for('message', check=lambda x: ctx.message.channel == x.channel and ctx.message.author == x.author, timeout=300)
config['content'] = m.content
await ctx.send('How many options are available?')
m = await self.bot.wait_for('message', check=lambda x: ctx.message.channel == x.channel and ctx.message.author == x.author and x.content.isdigit(), timeout=300)
options_len = int(m.content)
config['options'] = {}
for _ in range(options_len):
await ctx.send('What is the option emoji?')
while True:
m = await self.bot.wait_for('message', check=lambda x: ctx.message.channel == x.channel and ctx.message.author == x.author, timeout=300)
try:
await m.add_reaction(m.content)
except discord.HTTPException:
await ctx.send('Invalid emoji. Send another.')
else:
emoji = m.content
break
await ctx.send('What is the option command? (e.g. `reply Transferring && move 1238343847384`)')
m = await self.bot.wait_for('message', check=lambda x: ctx.message.channel == x.channel and ctx.message.author == x.author, timeout=300)
config['options'][emoji] = m.content
except asyncio.TimeoutError:
await ctx.send('Timeout. Re-run the command to create a menu.')
else:
await self.db.find_one_and_update({'_id': 'config'}, {'$set': config}, upsert=True)
await ctx.send('Success')
#checks.has_permissions(PermissionLevel.MODERATOR)
#commands.command()
async def clearmenu(self, ctx):
"""Removes an existing menu"""
await self.db.find_one_and_delete({'_id': 'config'})
await ctx.send('Success')
def setup(bot):
bot.add_cog(Menu(bot))
First of all, you have to have the development version of discord.py, which you can install using pip install -U git+https://github.com/Rapptz/discord.py
in the command prompt.
To add buttons to messages, you add a view=your_view_here() argument to ctx.send.
To get the view, you subclass discord.ui.View and then initialise it:
class config_menu_view(discord.ui.View):
def __init__(self):
super().__init__()
And then you can add buttons to your view using the decorator #discord.ui.button(label='label[optional]', emoji=emoji[optional] you can read all the possible arguments in the documentation :
#discord.ui.button(label='Button 1')
async def button_1(self, button: discord.ui.Button, interaction: discord.Interaction):
await interaction.response.send_message('Button 1 was clicked', ephemeral=True)
#do whatever you want to do here if the button was clicked
And then you can send it.
All of this code together would be:
class config_menu_view(discord.ui.View):
def __init__(self):
super().__init__()
#discord.ui.button(label='Button 1')
async def button_1(self, button: discord.ui.Button, interaction: discord.Interaction):
await interaction.response.send_message('Button 1 was clicked', ephemeral=True)
#do whatever you want to do here if the button was clicked
#and then when you want to send the view, do this:
await ctx.send("Button click!", view=config_menu_view())
From this information you should be able to make your own code.
Great places to learn more about buttons are the examples directory in GitHub
and the documentation

discord.py how to improve show avatar command that it'll show not only mentioned member but your too

i want to improve this command that when you write it without mention, it'll show your avatar, and if with menthion it will show mentioned person avatar, but i don't know how to do it correctly, i tried using if error show ctx.author.avatar_url but it didn’t work out for me, here is my code that show only mentioned member av
#commands.command( aliases = ['av'] )
async def showavatar( self, ctx, member: discord.Member ):
await ctx.channel.purge( limit = 1 )
emb = discord.Embed( color = discord.Color.green() )
emb.set_image( url = member.avatar_url )
await ctx.send( embed = emb )
EDITED
error - discord.ext.commands.errors.CommandInvokeError Command raised an exception: AttributeError:'NoneType'object has no attribute 'avatar_url'
tryed to put self before member.avatar_url but it doesn't help
#commands.command( aliases = ['av'] )
async def showavatar( self, ctx, member: discord.Member = None ):
await ctx.channel.purge( limit = 1 )
emb = discord.Embed( color = discord.Color.green() )
emb.set_image( url = member.avatar_url )
await ctx.send( embed = emb )
if member is None:
member = author.avatar_url
emb = discord.Embed( color = discord.Color.green() )
emb.set_image( url = member )
await ctx.send( embed = emb )
Simply set a default value of None to member and inside the command check for it, if the member variable is None then member = ctx.author
#commands.command(aliases=['av'])
async def showavatar(self, ctx, member: discord.Member=None):
if member is None:
member = ctx.author
await ctx.channel.purge(limit=1)
emb = discord.Embed(color=discord.Color.green())
emb.set_image(url=member.avatar_url)
await ctx.send(embed=emb)

Can i detect 'connection lost' in websockets using Python3.6 Sanic?

can i detect ( if yes how?) when my Python3.6 Sanic Web Server lost connection with client application (example: user closes web browser or network fails, etc...)
from sanic import Sanic
import sanic.response as response
app = Sanic()
#app.route('/')
async def index(request):
return await response.file('index.html')
#app.websocket('/wsgate')
async def feed(request, ws):
while True:
data = await ws.recv()
print('Received: ' + data)
res = doSomethingWithRecvdData(data)
await ws.send(res)
if __name__ == '__main__':
app.run(host="0.0.0.0", port=8000, debug=True)
Solved
from sanic import Sanic
import sanic.response as response
from websockets.exceptions import ConnectionClosed
app = Sanic()
#app.route('/')
async def index(request):
return await response.file('index.html')
#app.websocket('/wsgate')
async def feed(request, ws):
while True:
try:
data = await ws.recv()
except (ConnectionClosed):
print("Connection is Closed")
data = None
break
print('Received: ' + data)
res = doSomethingWithRecvdData(data)
await ws.send(res)
if __name__ == '__main__':
app.run(host="0.0.0.0", port=8000, debug=True)

Resources