Permission Check Discord.py Bot
I am working on a discord bot for basic moderation which does kick , ban and mute for now at least. But the problem is other members can use it too. I want only a few specified role who can use it. Don’t want to work on it depending on the @role either because the name of the roles across different servers aren’t the same. Also wanting to keep the bot as simple as possible. Now, I started out as this:
@client.command(name='ban') async def mod_ban(member: discord.User): try: await client.ban(member, delete_message_days=0) await client.say('**** has been banned.'.format(str(member))) except Exception as error: await client.say(error)
But any member can use the commands then. So, tried follow this one = Permission System for Discord.py Bot and ended up with this:
@client.command(name='ban') async def mod_ban(context, member: discord.User): if context.message.author.server_premission.administrator: try: await client.ban(member, delete_message_days=0) await client.say('**** has been banned.'.format(str(member))) except Exception as error: await client.say(error) else: await client.say('Looks like you don\'t have the perm.')
Which lands me with this error: ;-;
raise MissingRequiredArgument(' is a required argument that is missing.'.format(param)) discord.ext.commands.errors.MissingRequiredArgument: member is a required argument that is missing.
Also, besides context.message.author.server_premission.administrator I don’t only want the roles with Admin perm to use this command. I also want a few other roles with have few perms like manage message , manage roles etc. to use to command too. Thanks in advance for the help! Also, sorry if I’ve missed anything stupid or silly ;-;
Welcome to discord.py¶
discord.py is a modern, easy to use, feature-rich, and async ready API wrapper for Discord.
Features:
- Modern Pythonic API using async / await syntax
- Sane rate limit handling that prevents 429s
- Command extension to aid with bot creation
- Easy to use with an object oriented design
- Optimised for both speed and memory
Getting started¶
Is this your first time using the library? This is the place to get started!
- First steps:Introduction | Quickstart | Setting Up Logging
- Working with Discord:Creating a Bot Account | A Primer to Gateway Intents
- Examples: Many examples are available in the repository.
Getting help¶
If you’re having trouble with something, these resources might help.
- Try the Frequently Asked Questions first, it’s got answers to all common questions.
- Ask us and hang out with us in our Discord server.
- If you’re looking for something specific, try the index or searching .
- Report bugs in the issue tracker.
- Ask in our GitHub discussions page.
Extensions¶
These extensions help you during development when it comes to common tasks.
- discord.ext.commands – Bot commands framework
- discord.ext.tasks – asyncio.Task helpers
Manuals¶
These pages go into great detail about everything the API can do.
- API Reference
- Interactions API Reference
- discord.ext.commands API Reference
- discord.ext.tasks API Reference
Meta¶
If you’re looking for something related to the project itself, it’s here.
- Changelog
- Version Guarantees
- Migrating to v2.0
- Migrating to v1.0
discord.py 2.3.2
A modern, easy to use, feature-rich, and async ready API wrapper for Discord written in Python.
Key Features
- Modern Pythonic API using async and await .
- Proper rate limit handling.
- Optimised in both speed and memory.
Installing
Python 3.8 or higher is required
To install the library without full voice support, you can just run the following command:
python3 -m pip install -U discord.py py -3 -m pip install -U discord.py
Otherwise to get voice support you should run the following command:
python3 -m pip install -U py -3 -m pip install -U discord.pyTo install the development version, do the following:
$ git clone https://github.com/Rapptz/discord.py discord.py python3 -m pip install -U .
Optional Packages
- PyNaCl (for voice support)
Please note that when installing voice support on Linux, you must install the following packages via your favourite package manager (e.g. apt , dnf , etc) before running the above commands:
- libffi-dev (or libffi-devel on some systems)
- python-dev (e.g. python3.8-dev for Python 3.8)
Quick Example
Bot Example
You can find more examples in the examples directory.
Links
- Documentation
- Official Discord Server
- Discord API
Saved searches
Use saved searches to filter your results more quickly
Cancel Create saved search
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Voice Receive API Design/Usage #1094
imayhaveborkedit opened this issue Feb 20, 2018 · 90 comments
RFC: Voice Receive API Design/Usage #1094
imayhaveborkedit opened this issue Feb 20, 2018 · 90 comments
feature request This is a feature request. RFC Request for Comment
Comments
Contributor
imayhaveborkedit commented Feb 20, 2018 •
Note: DO NOT use this in production. The code is messy (and possibly broken) and probably filled with debug prints. Use only with the intent to experiment or give feedback, although almost everything in the code is subject to change.
Behold the voice receive RFC. This is where I ask for design suggestions and feedback. Unfortunately not many people seem to have any idea of what their ideal voice receive api would look like so it falls to me to come up with everything. Should anyone have any questions/comments/concerns/complaints/demands please post them here. I will be posting the tentative design components here for feedback and will update them occasionally. For more detailed information on my progress see the project on my fork. I will also be adding an example soonish.
Overview
The main concept behind my voice receive design is to mirror the voice send api as much as possible. However, due to receive being more complex than send, I’ve had to take some liberties in creating some new concepts and functionality for the more complex parts. The basic usage should be relatively familiar:
vc = await channel.connect() vc.listen(MySink())
The voice send api calls an object that produces PCM packets a Source , whereas the receive api refers to them as a Sink . Sources have a read() function that produces PCM packets, so Sinks have a write(data) function that does something with PCM packets. Sinks can also optionally accept opus data to bypass the decoding stage if you so desire. The signature of the write(data) function is currently just a payload blob with the opus data, pcm data, and rtp packet, mostly for my own convenience during development. This is subject to change later on.
The new VoiceClient functions are basically the same as the send variants, with listen() being the new counterpart to play() .
Note: The stop() function has been changed to stop both playing and listening. I have added stop_playing() and stop_listening() for individual control.
Built in Sinks
For simply saving voice data to a file, you can use the built in WaveSink to write them to a wav file. The way I have this currently implemented, however, is completely broken for more than one user.
Note: Here lies my biggest problem. I currently do not have any way to combine multiple voice «streams» into one stream. The way this works is Discord sends packets for all users on the same socket, differentiated by an id (aka ssrc, from RTP spec). These packets have timestamps, but with a random start offset, per ssrc. RTP has a mechanism where the reference time is sent in a control packet, but as far as I can tell, Discord doesn’t send these control packets. As such, I have no way of properly synchronizing streams without excessive guesswork based on arrival time in the socket (unreliable at best). Until I can solve this there will be a few holes in the design, for example, how to record the whole conversation in a voice channel instead of individual users.
Sinks can be composed much like Sources can (PCMVolumeTransformer+FFmpegPCMAudio, etc). I will have some built in sinks for handling various control actions, such as filtering by user or predicate.
# only listen to message.author vc.listen(UserFilter(MySink(), message.author)) # listen for 10 seconds vc.listen(TimedFilter(MySink(), 10)) # arbitrary predicate, could check flags, permissions, etc vc.listen(ConditionalFilter(MySink(), lambda data: . ))
and so forth. As usual, these are subject to change when I go over this part of the design again.
As mentioned before, mixing is still my largest unsolved problem. Combining all voice data in a channel into one stream is surely a common use case, and i’ll do my best to try and figure out a solution, but I can’t promise anything yet. If it turns out that my solution is too hacky, I might have to put it in some ext package on pypi (see: ext.colors).
For volume control, I recently found that libopus has a gain setting in the decoder. This is probably faster and more accurate than altering pcm packets after they’ve been decoded. Unfortunately, I haven’t quite figured out how to expose this setting yet, so I don’t have any public api to show for it.
That should account for most of the public api part that i’ve designed so far. I still have a lot of miscellaneous things to do so no ETA. Again, if you have any feedback whatsoever please make yourself known either here or in the discord server.
Old issue content Voice receive has been an occasionally requested feature for a very long time now, but its actual usage seems to be limited to some form of voice recognition (for commands or some other form of automation) and for recording. This is all fine and dandy, but issue that appears is how to expose this in the library. With the v1.0 rewrite voice send was redesigned to be more composable and give more control to the user. However, that also means the voice systems were designed with *only* send in mind. Voice send is far less complex than receive, so some considerable amount of effort has to go into designing an api that both fits well with the library and, more importantly, is useful and user friendly.
Essentially, voice receive is reading RTP packets from a socket and then decrypting and decoding them from Opus to PCM. At this point is fairly trivial to simply expose an event that produces PCM data and a member object, but this is far from useful or user friendly. This leads us to the main question:
Those who want to use voice receive, what kind of api do you want? What kind of api would you expect from the library?
Ideally, simple or common use cases should be trivial to accomplish. More complex requirements should not be difficult or unwieldy. The library should have enough batteries included to handle most simple situations, such as saving audio to a file. What form this takes is what needs to be decided.
My part in all this
I’ve been working on voice receive for a few months now, with most of my time spend trying to wrangle technical or design related problems. Those who have been listening have heard of my struggles with RTCP packets (or rather lack thereof), the ultimate goal being functional stream mixing. This means combining the audio streams from multiple users into one stream of data (each user has their own stream). In the RTP spec, discord is supposed to send RTCP packets with the timing information necessary to synchronize these streams together. Actually mixing them afterwards is trivial. The problem is that Discord does not reliably send RTCP packets. You may or may not get them depending on which voice server you end up on. Trying to bodge some optimistic yolo handling is too sketchy to be the official implementation, and is subject to the kind of problems that creep in from having questionable code. Danny would never approve of that kind of code anyways, seeing as he then has to support it.
Possible design
In the following section I will explain the design I came up with when working on this. If you want to reply to this RFC without being biased by reading my design, skip this section and come back after you’ve had your say.
Click to be biased expand
My idea was to essentially mirror the voice send api. This seemed like the logical conclusion to me. The voice send api has source objects which produce voice data. These can be composed in any way and eventually fed to the lib where it handles it from there. So why not do the reverse for voice receive? Have objects that receive voice data and do some arbitrary operations on it. These can be composed the same way source objects can be: usually nested, but advanced usages can have branching or some other form of dynamic usage. I decided to call these objects Sinks. You would use them the same way you would sources.
# using a source voice_client.play(discord.FFmpegPCMAudio("song.mp3")) # using a sink voice_client.read(discord.WaveSink("voice.wav"))
The WaveSink is a simple built-in sink for writing the PCM data to a wav file. This may seem simple but it doesn’t actually work. Since there’s no way to mix audio, this can only work for one user, otherwise you end up mashing audio from multiple users together. It worked great with just one person though!
Technical issues aside, this demonstrates the main concept for simple usages. However the more I worked on this the more I realized that trying to mirror the voice send as much as possible just wouldn’t work due to how simple it was. There’s also the need to have controls for deciding who to handle data from (who to ignore), how long to record data for (besides explicitly stopping the whole reader), etc.
Basically, without mixing, my design is incomplete. I can’t complete it until I have a reliable way to mix audio since I can’t design an api around something that doesn’t exist. Supposedly discord is going to push out an update to all voice servers in the future, which hopefully means either RTCP will reliably be sent or there will be some other synchronization mechanism. I decided that if I do go through with this design i’ll have to complete it without a way to mix audio, since there’s just no good way to do it without RTCP packets for timing data.
The text was updated successfully, but these errors were encountered:
Contributor Author
imayhaveborkedit commented Feb 28, 2018
I’ve already had a go at writing all of the decoding and processing for this. I spent a lot of time writing classes for packet types discord doesn’t send. The timestamp data in RTP packets starts from a random offset, and that offset is different per ssrc. RTCP packets have the reference time for calculating when these packets were created. Relying on gateway websocket events to sync up voice socket UDP packets is racy and not reliable, especially considering the gateway code can be blocked by user code and speaking events have no id (timestamp).
Ruuttu commented Mar 1, 2018
Seems safe to bet that Discord makes no effort to synchronize speakers. Each stream is basically played «as soon as it’s received» with the shortest buffer they think they can get away with.
If there’s someone in the call from New Zealand and we’re always making fun of him for laughing at jokes three seconds too late, I would expect the data coming from the Voice Receive API to reflect that. I would not expect it to «fix» the latency.
So I think you can track the local packet receive times and use some of those without shame. Again, most packets can actually be placed right after the previous one, ignoring the receive time. Never the first packet after silence tho, of course.
modelmat mentioned this issue May 11, 2018
Epictek mentioned this issue May 19, 2018
Harmon758 mentioned this issue Dec 3, 2018
wgaylord commented Feb 11, 2019
Going to assume that this attempt has stalled?
Any idea on if anyone will try and implement it?
Also a good api would just pass in the raw PCM that comes out of the opus library. Must like the mumble python api. (Another chat server that uses opus)
This should always be the same length unless discord is changing the opus config options on the fly.
Contributor Author
imayhaveborkedit commented Feb 11, 2019 •
I’m still working on it. The fact that this is an «unsupported» feature and my desire to make a sufficiently high level api for ease of use coupled with my sporadic motivation and inspiration make for slow progress. It also seems that few people have useful input on this issue meaning that I am basically on my own for the most part. If you want to see what I have so far I keep my fork updated. There’s still a lot to do and I haven’t written docs or added an example yet so make of it what you will. https://github.com/imayhaveborkedit/discord.py
wgaylord commented Feb 12, 2019
Welp guess I am stuck on using my own server with mumble for my HamRadio Remote station.
Harmon758 mentioned this issue Feb 24, 2019
Apfelin commented Mar 18, 2019
I see this fork is still getting regular updates.
You’ve mentioned a use-case, where it’s possible to use a WaveSink to get raw PCM/Wav data. As it happens this is exactly the kind of thing I need.
Basically, my use-case is simply getting raw PCM data and passing it along to do some basic speech recognition (fwiw, a very basic speech-to-text bot for a deaf friend). I assume no audio mixing means there is no way to actually tell which packet comes from which user? Regardless, such a situation doesn’t impact me greatly, since, assuming the (in my case, 2 or 3) users speak in a somewhat orderly fashion, my output would simply be the transcript of what has been said, no matter who said it. The only other thing needed in this case, for me, would be a way to detect when a user has stopped speaking so I can pass along the file/buffer without words being cut out. Ideally, this could be done by storing the audio data in a buffer, but writing to a file and using that as input would work fairly good, as well.
Would it be possible to share a minimal piece of code that exemplifies the use-case you described, or provide any hints for the direction I should take in my implementation of this use-case?
Contributor Author
imayhaveborkedit commented Mar 18, 2019
Don’t worry, that use case is probably one of the two major cases that I expect people to have. WaveSink is specifically for writing data to a wav file, the point being that the built in wave module takes care of writing all the headers and such. The data you get in the first place is already PCM, so unless whatever flow you have requires a file on the filesystem, you don’t need that one.
When I mention «mixing» I’m referring to combining the various streams of user voice data into a single combined stream. This is a problem I haven’t quite figured out how to do properly yet since discord doesn’t seem to provide the required RTCP packets necessary to synchronize the streams. If I do come up with something and it ends up being too jank to be in the main lib I’m considering making some sort of ext.voice package on pypi. Anyways, these «streams» are per user (actually ssrc, which is just an id in the RTP spec, but are mapped to user ids), so the data you get will include a member object. The exact format of this I haven’t decided on yet, so right now it’s just sort of a payload blob object with the pcm, opus, and rtppacket object (mostly for my own convenience during development).
Delimiting speech segments is still something I don’t quite know how to handle yet. I think this might be a problem I have to put onto the user since I don’t see a good way to do it lib-side. In the example I’m writing for this I’m thinking about setting the pattern for doing so to use the priority speaking feature. Relying on speaking events and or arbitrary waiting periods does not sound reliable enough to use by default. Using priority speaking to indicate the segment of speech to be recognized/processed would be very convenient for both me since I don’t need to do anything in the lib for it and for the user since being a PTT feature means if they mess it up it’s their fault.
Unfortunately have speech recognition in an example is a bit out of scope for the lib examples, but I plan on having an additional example in a gist that demonstrates this using the SpeechRecognition module most likely. In your case, until I design out how it would work with the various services in the aforementioned library (which might end up being the same anyways), it would probably be waiting for priority speaking from some member, collecting their voice data in your container of choice (in memory or filesystem based), and processing them once priority speaking ends.
