rapptz / discord.py Goto Github PK
View Code? Open in Web Editor NEWAn API wrapper for Discord written in Python.
Home Page: http://discordpy.rtfd.org/en/latest
License: MIT License
An API wrapper for Discord written in Python.
Home Page: http://discordpy.rtfd.org/en/latest
License: MIT License
The client crashes if the internet connection is dropped (ethernet cable unplugged in my case):
Fatal read error on SSL transport
protocol: <websockets.client.WebSocketClientProtocol object at 0x7fc1ede993c8>
transport: <_SelectorSslTransport fd=7 read=polling write=<idle, bufsize=0>>
Traceback (most recent call last):
File "/usr/lib/python3.4/asyncio/selector_events.py", line 896, in _read_ready
data = self._sock.recv(self.max_size)
File "/usr/lib/python3.4/ssl.py", line 733, in recv
return self.read(buflen)
File "/usr/lib/python3.4/ssl.py", line 622, in read
v = self._sslobj.read(len or 1024)
OSError: [Errno 113] No route to host
Task exception was never retrieved
future: <Task finished coro=<run() done, defined at /usr/local/lib/python3.4/dist-packages/websockets/protocol.py:296> exception=OSError(113, 'No route to host')>
Traceback (most recent call last):
File "/usr/lib/python3.4/asyncio/tasks.py", line 237, in _step
result = coro.throw(exc)
File "/usr/local/lib/python3.4/dist-packages/websockets/protocol.py", line 302, in run
msg = yield from self.read_message()
File "/usr/local/lib/python3.4/dist-packages/websockets/protocol.py", line 324, in read_message
frame = yield from self.read_data_frame(max_size=self.max_size)
File "/usr/local/lib/python3.4/dist-packages/websockets/protocol.py", line 379, in read_data_frame
frame = yield from self.read_frame(max_size)
File "/usr/local/lib/python3.4/dist-packages/websockets/protocol.py", line 411, in read_frame
self.reader.readexactly, is_masked, max_size=max_size)
File "/usr/local/lib/python3.4/dist-packages/websockets/framing.py", line 77, in read_frame
data = yield from reader(2)
File "/usr/lib/python3.4/asyncio/streams.py", line 500, in readexactly
block = yield from self.read(n)
File "/usr/lib/python3.4/asyncio/streams.py", line 473, in read
yield from self._wait_for_data('read')
File "/usr/lib/python3.4/asyncio/streams.py", line 414, in _wait_for_data
yield from self._waiter
File "/usr/lib/python3.4/asyncio/futures.py", line 385, in __iter__
yield self # This tells Task to wait for completion.
File "/usr/lib/python3.4/asyncio/tasks.py", line 288, in _wakeup
value = future.result()
File "/usr/lib/python3.4/asyncio/futures.py", line 274, in result
raise self._exception
File "/usr/lib/python3.4/asyncio/selector_events.py", line 896, in _read_ready
data = self._sock.recv(self.max_size)
File "/usr/lib/python3.4/ssl.py", line 733, in recv
return self.read(buflen)
File "/usr/lib/python3.4/ssl.py", line 622, in read
v = self._sslobj.read(len or 1024)
OSError: [Errno 113] No route to host
Right now you always have to wait for a channel or user to be active in some way, which results in problems. For example when you want the bot to type regularly in a specific channel you always need to grab it from someone typing in it first. So you cant make the bot post a text every five minutes in the channel unless somebody types in that channel before. Equal for users, but the problem is rather minor there.
Thread with discord client stops working with this in logs:
[23/Nov/2015 02:20:19] DEBUG [discord.client:77] (Thread-5 ) Keeping websocket alive with timestamp 1448238019
[23/Nov/2015 02:20:19] DEBUG [discord.client:509] (Thread-5 ) Dispatching event socket_raw_send
[23/Nov/2015 02:20:33] DEBUG [ws4py:360] (Bot ) Closing message received (1000) ''
[23/Nov/2015 02:20:33] INFO [discord.client:95] (Bot ) Closed with 1006 ("Going away") at 1448238033
[23/Nov/2015 02:20:33] DEBUG [discord.client:509] (Bot ) Dispatching event socket_closed
[23/Nov/2015 02:20:33] DEBUG [discord.client:509] (Bot ) Dispatching event socket_closed
[23/Nov/2015 02:20:33] INFO [requests.packages.urllib3.connectionpool:756] (Bot ) Starting new HTTPS connection (1): discordapp.com
[23/Nov/2015 02:20:33] DEBUG [requests.packages.urllib3.connectionpool:387] (Bot ) "GET /api/gateway HTTP/1.1" 200 43
[23/Nov/2015 02:20:33] INFO [discord.client:428] (Bot ) websocket gateway found
Might be an error around self.ws.connect()
but there are no handlers at this point or in my thread code.
It is extremely rare, I have updated my code to log exceptions from client thread so next time hopefully I'll see why it happens.
My script tries to reboot when it crashes. I frequently, on reboot, see the exception:
Traceback (most recent call last):
File "/home/luke/Desktop/discord/discord_main.py", line 48, in run
client.run()
File "/usr/local/lib/python2.7/dist-packages/discord/client.py", line 542, in run
self.ws.run()
File "/usr/local/lib/python2.7/dist-packages/ws4py/websocket.py", line 420, in run
self.sock.setblocking(True)
AttributeError: 'NoneType' object has no attribute 'setblocking'
Is this a bug or something on my end?
GUILD_BAN_ADD
denotes that a member was banned. This is then followed by GUILD_MEMBER_REMOVE
.
GUILD_BAN_REMOVE
is straightforward and doesn't have much context to it.
{
"t": "GUILD_BAN_REMOVE",
"s": 362,
"op": 0,
"d": {
"user": {
"username": "\u300c Zeta \u300d",
"id": "94129005791281152",
"discriminator": "1920",
"avatar": "a8503d9d0f3a8867ee7adb4b434e2c7a"
},
"guild_id": "104158907944939520"
}
}
when discord.py sends a mention string (<@id>
) it should highlight the user. I've noticed that recently it doesn't do that any longer, and mobile users see @invalid-user
instead of the mention, screenshot: https://i.imgur.com/qCFwKJE.png
I've checked with discord support and other bot devs who use other libraries, and ultimately it sounds like a problem with discord.py
can you reproduce this at all? the following command doesn't highlight me, and appears broken on mobile:
return discord.send_message(message.channel, '<@%s> pong' % message.author.id)
I use this code to list all voice members in each channel on my server
server = discord.utils.find(lambda m: m.id == self.server, self.client.servers)
if server is not None:
for channel in server.channels:
print(channel.voice_members)
However if i move channels after my bot has connected to the server, voice_members doesn't reflect the changes. it still shows me in the old channel.
Hopefully i'm just missing something small but i've been at this for a while so i believe its a bug.
The discord client only supports a limited set of colours (or rather, it will soon) so those limited colours should be the ones exposed via the library rather than a free-form rgb value.
Spent a couple of minutes banging head against wall today; the json
parameter for requests.post()
was only added in requests 2.4.2 (see http://docs.python-requests.org/en/latest/user/quickstart/#more-complicated-post-requests), and yet when I installed discord.py requests 2.4.2+ was not installed (it took sudo pip3 install --upgrade requests
). Therefore, interesting crash:
Traceback (most recent call last):
File "./dissonance.py", line 26, in <module>
client.login(email, password)
File "/usr/local/lib/python3.4/dist-packages/discord/client.py", line 654, in login
r = requests.post(endpoints.LOGIN, json=payload)
File "/usr/lib/python3/dist-packages/requests/api.py", line 88, in post
return request('post', url, data=data, **kwargs)
File "/usr/lib/python3/dist-packages/requests/api.py", line 44, in request
return session.request(method=method, url=url, **kwargs)
TypeError: request() got an unexpected keyword argument 'json'
To fix: depend on requests โฅ 2.4.2 (assuming that's possible with pip/pip3).
When you leave a server, a GUILD_DELETE message is sent on the WebSocket deleting the server. But afterwards a GUILD_MEMBER_REMOVE may appear referencing yourself, and the just deleted guild. Causing the following traceback:
Traceback (most recent call last):
File "bot.py", line 66, in <module>
bot.run()
File "/home/julian/prog/record/discord/client.py", line 472, in run
self.ws.run()
File "/usr/lib/python3.5/site-packages/ws4py/websocket.py", line 427, in run
if not self.once():
File "/usr/lib/python3.5/site-packages/ws4py/websocket.py", line 305, in once
if not self.process(b):
File "/usr/lib/python3.5/site-packages/ws4py/websocket.py", line 377, in process
self.received_message(s.message)
File "/home/julian/prog/record/discord/client.py", line 122, in received_message
self.dispatch('socket_update', event, data)
File "/home/julian/prog/record/discord/client.py", line 459, in dispatch
getattr(self, handle_method, _null_event)(*args, **kwargs)
File "/home/julian/prog/record/discord/client.py", line 467, in handle_socket_update
getattr(self.connection, method)(data)
File "/home/julian/prog/record/discord/client.py", line 285, in handle_guild_member_remove
member = utils.find(lambda m: m.id == user_id, server.members)
AttributeError: 'NoneType' object has no attribute 'members'
See also the WebSocket context.
Changing bot status to away or playing a certain game would be cool.
The payload should be something to send to the websocket with op
of 3 and d
of { idle_since: unix-timestamp, game_id: some-id }
.
I don't seem to be getting any error messages when running code using this library. Is this an artifact of the WebSocketClient library? Is it a bug? Is there some way of enabling errors that I'm missing?
I'm trying to write a bot using this API which will let people play a game but I'm coming across some weird behaviours and I can't tell whether I'm doing something wrong or whether there's actually a problem.
The below code, upon talk_to_discord()
being called, attempts to start a client and then listens for a message to tell it when to start the game (I'm going with !start). When it hears that message, it starts a Game object, passing both the Discord client (self.client
) and the user who started the game (self.owner
). The idea is that the Game object then messages the owner to ask who's playing (generating a list of usernames from the input string) and also what roles are available to players (generating a list of roles from the second input string).
The module is called werewolf
. If I open Python and then type import werewolf
and werewolf.talk_to_discord()
, the client starts and I can message the relevant user on Discord.
The chat log in Discord between me and the user (also called 'werewolf') looks like this:
me: !start
werewolf: Let's start a game!
werewolf: Who will be playing?
me: Player 1, Player 2, Player 3, Player 4, Player 5
pause
me: !start
werewolf: Let's start a game!
werewolf: Who will be playing?
me: Player 1, Player 2, Player 3, Player 4, Player 5
werewolf: What roles will be in effect?
me: Tanner, Werewolf, Werewolf, Hunter, Robber, Seer, Insomniac, Villager
The console output before pause is:
Successfully logged in as werewolf with ID 100233992065814528.
A game is starting!
users input
[]
The output after pause is:
A game is starting!
users input
[u'!start', u'Player 1, Player 2, Player 3, Player 4, Player 5']
roles input
[u'!start', u'Player 1, Player 2, Player 3, Player 4, Player 5']
test
The code I've written is:
import discord
def talk_to_discord():
client = discord.Client()
client.login('email', 'password')
@client.event
def on_message(message):
if message.content.startswith("!start"):
client.send_message(message.channel, "Let's start a game!")
Game(client, message.author)
@client.event
def on_ready():
print('Successfully logged in as {0} with ID {1}.'.format(client.user.name, client.user.id))
client.run()
# --------------------------------------------------------------------------------------------------
class Game(object):
"""Object for the entire game."""
def __init__(self, client, owner):
import random
print('A game is starting!')
self.client = client
self.owner = owner
# Work out who's playing.
self.client.send_message(self.owner, 'Who will be playing?')
time.sleep(30)
print('users input')
received = [m.content for m in self.client.messages if m.author == self.owner]
print(received)
self.users = received[-1].split(', ')
self.client.send_message(self.owner, 'What roles will be in effect?')
time.sleep(30)
print('roles input')
received = [m.content for m in self.client.messages if m.author == self.owner]
print(received)
roles = received[-1].split(', ')
self.roles = random.sample([n.lower() for n in roles], len(roles))
print('test')
if len(self.users) + 3 != len(self.roles):
raise ValueError('The number of roles must be the number of players + 3.')
print('test2')
Here are my questions:
test2
to print to the console. Why does the if statement as written cause Python to just stop, rather than either raising a ValueError
or moving onto the next line?talk_to_discord()
again, does every message start appearing in duplicate (or triplicate, or more depending on how many times I've hit Ctrl-C and run the function again)?while new_message_from_author(author) == False
with a much shorter time delay in it, and then have the rest of the code run once a new message from the owner has been received, rather than having a preset amount of time in which to provide the relevant inputs.I would be very grateful for any pointers on whether this is a problem with the API, or whether it's a problem with my trying to use the API.
When a guild is unavailable, it will contain
{
"unavailable": true,
"id": "41771983423143937"
}
in the guilds array in the READY event. This is not handled properly, and a KeyError is raised.
Traceback (most recent call last):
File "bot.py", line 345, in <module>
bot.run()
File "/home/julian/prog/record/logger/discord/client.py", line 530, in run
self.ws.run()
File "/usr/lib/python3.5/site-packages/ws4py/websocket.py", line 427, in run
if not self.once():
File "/usr/lib/python3.5/site-packages/ws4py/websocket.py", line 305, in once
if not self.process(b):
File "/usr/lib/python3.5/site-packages/ws4py/websocket.py", line 377, in process
self.received_message(s.message)
File "/home/julian/prog/record/logger/discord/client.py", line 130, in received_message
self.dispatch('socket_update', event, data)
File "/home/julian/prog/record/logger/discord/client.py", line 507, in dispatch
getattr(self, handle_method, _null_event)(*args, **kwargs)
File "/home/julian/prog/record/logger/discord/client.py", line 515, in handle_socket_update
getattr(self.connection, method)(data)
File "/home/julian/prog/record/logger/discord/client.py", line 202, in handle_ready
self._add_server(guild)
File "/home/julian/prog/record/logger/discord/client.py", line 161, in _add_server
guild['roles'] = [Role(**role) for role in guild['roles']]
KeyError: 'roles'
Relevant WebSocket message (Warning: big).
Most functions either return a True
/False
or a value/None
.
Exceptions are the proper way to go for Python and thus they should be used to denote errors instead. Return codes/values can be ignored while exceptions can't.
Version: 0.9.1
Branch: main
Hello, from week before, my chat bot keeps receives errors after some time of work (random time):
In python IDLE I see this errors: http://pastebin.com/MhDgE3CK
And at same time logging gives: 'Closed with 1006 ("Going away")'
What can I do with it? May be I can somehow make bot restart after this error? please help
Events on new user joining and user leaving the server lack information on server parameter. As a result, it's hard to have meaningful use of those events.
See: handle_guild_member_add and handle_guild_member_remove
After running smoothly for a very long time, I suddenly got the error:
Traceback (most recent call last):
File "/home/luke/Desktop/discord/discord_main.py", line 16, in <module>
client.run()
File "/usr/local/lib/python2.7/dist-packages/discord/client.py", line 542, in run
self.ws.run()
File "/usr/local/lib/python2.7/dist-packages/ws4py/websocket.py", line 427, in run
if not self.once():
File "/usr/local/lib/python2.7/dist-packages/ws4py/websocket.py", line 305, in once
if not self.process(b):
File "/usr/local/lib/python2.7/dist-packages/ws4py/websocket.py", line 362, in process
self.close(s.closing.code, s.closing.reason)
File "/usr/local/lib/python2.7/dist-packages/ws4py/client/__init__.py", line 198, in close
self._write(self.stream.close(code=code, reason=reason).single(mask=True))
File "/usr/local/lib/python2.7/dist-packages/ws4py/websocket.py", line 243, in _write
self.sock.sendall(b)
File "/usr/lib/python2.7/ssl.py", line 721, in sendall
v = self.send(data[count:])
File "/usr/lib/python2.7/ssl.py", line 687, in send
v = self._sslobj.write(data)
error: [Errno 14] Bad address
Normally i'm pretty good at interpreting python errors, but as I've never used any of the libraries on which discord depends, I'm having trouble. Can someone explain to me why this happens and whether this is a bug?
on the on_message event handler i was getting the author of the message, and printing their role array, but it would give me an empty array every time, so i couldn't even check if a role was the everyone role.
here's some sample code:
import discord
import json
import os
client = discord.Client()
if os.path.isfile("auth.json"):
print("auth details loaded from auth.json")
with open("auth.json") as data_file:
authdetails = json.load(data_file)
client.login(authdetails["email"], authdetails["pass"])
@client.event
def on_message(message):
print(message.content)
print(message.author.roles)
@client.event
def on_ready():
print("logged in")
client.run()
and here's what i get if i run that, and send a message, with my account role set to everyone:
is this intended behavior? am i being stupid and missing something?
I got an error when new users join a channel:
Traceback (most recent call last):
File "gm_bot.py", line 85, in <module>
client.run()
File "C:\Python27\lib\site-packages\discord\client.py", line 550, in run
self.ws.run()
File "C:\Python27\lib\site-packages\ws4py\websocket.py", line 427, in run
if not self.once():
File "C:\Python27\lib\site-packages\ws4py\websocket.py", line 305, in once
if not self.process(b):
File "C:\Python27\lib\site-packages\ws4py\websocket.py", line 377, in process
self.received_message(s.message)
File "C:\Python27\lib\site-packages\discord\client.py", line 129, in received_message
self.dispatch('socket_update', event, data)
File "C:\Python27\lib\site-packages\discord\client.py", line 527, in dispatch
getattr(self, handle_method, utils._null_event)(*args, **kwargs)
File "C:\Python27\lib\site-packages\discord\client.py", line 535, in handle_socket_update
getattr(self.connection, method)(data)
File "C:\Python27\lib\site-packages\discord\client.py", line 262, in handle_guild_member_add
member = Member(server=server, deaf=False, mute=False, **data)
TypeError: type object got multiple values for keyword argument 'mute'
Nothing special in my own code (just some setting roles with commands, thats it). This happens every time when a new member joins a channel, tested on multiple channels.
That way you can pass in an id without doing the search.
Discord provides "Widget"'s API which allows anyone with server ID to collect general info on server (channels, members, etc). Also has invite url.
API endpoint is https://discordapp.com/api/servers/{server.id}/widget.json
Example: https://discordapp.com/api/servers/94367845990805504/widget.json
For Widgets to work anyone with Manage Server
permission must enable it under Server Settings > Widget
tab.
https://i.gyazo.com/cf85583cc07a981a88025839616e949c.png
This is what I see from it.
Right now the client has be started with the client.run()
command. This blocks the script so I can't manually execute commands like client.send_message()
whenever I like, I am constrained to the events that the client detects. Can this be fixed?
If the client sends too many messages in a short amount of time on the WebSocet connection (for example by sending status updates too often), it will be terminated with the data "rate limited". The current rate limit on the WebSocet is 60/60 according to the discord devs.
The debug logs shows the following appearing:
DEBUG:websockets.protocol:client << Frame(fin=True, opcode=8, data=b'\x0f\xa8rate limited')
DEBUG:websockets.protocol:client >> Frame(fin=True, opcode=8, data=b'\x0f\xa8rate limited')
The Client.connect()
method then exits with no errors logged or exceptions raised, making it hard to track down what happened.
I have a function that my bot provides that is designed to replace a role on a user with a different one. If I call remove_roles to remove the old role, then immediately call add_roles to add the new one, the end result is that the user now has both roles applied. I would expect that the user would only have the new role after this. My current workaround is to edit member.roles myself to remove the old role from that before calling add_roles.
Ignoring exception in on_message
Traceback (most recent call last):
File "C:\Program Files (x86)\Python35-32\lib\site-packages\discord\client.py", line 251, in _run_event
yield from getattr(self, event)(*args, **kwargs)
File "red.py", line 145, in on_message
if settings["FILTER"] and not isMemberAdmin(message):
File "red.py", line 1475, in isMemberAdmin
if discord.utils.get(message.author.roles, name=settings["ADMINROLE"]) != None:
File "C:\Program Files (x86)\Python35-32\lib\site-packages\discord\utils.py", line 137, in get
return find(predicate, iterable)
File "C:\Program Files (x86)\Python35-32\lib\site-packages\discord\utils.py", line 78, in find
if predicate(element):
File "C:\Program Files (x86)\Python35-32\lib\site-packages\discord\utils.py", line 131, in predicate
obj = getattr(obj, attribute)
AttributeError: 'str' object has no attribute 'name'
discord.utils.get(message.server.members, name="ThatGuysName").roles
['132984642558099456', <discord.role.Role object at 0x050942F0>]
This isn't first time it happens. It seem to only ever happen to me on that particular server, which is the only twitch related one I have a bot on.
That guy was recently synced (been assigned to the "[stream_name] Subscriber" role after he linked his Twitch account) and I'm quite sure it's the reason it happens. That's also the only role he has.
I'm using this commit, 5a1d7a2, my apologies if it turns out to be already fixed.
At the moment there is no support for:
And probably some more.
It's possible to receive a GUILD_MEMBER_REMOVE for a member that has not been present in the guilds.members array in the READY event and for which no GUILD_MEMBER_ADD has been received for. Resulting in ValueError
being raised with the following traceback.
Traceback (most recent call last):
File "bot.py", line 345, in <module>
bot.run()
File "/home/julian/prog/record/logger/discord/client.py", line 560, in run
self.ws.run()
File "/usr/lib/python3.5/site-packages/ws4py/websocket.py", line 427, in run
if not self.once():
File "/usr/lib/python3.5/site-packages/ws4py/websocket.py", line 305, in once
if not self.process(b):
File "/usr/lib/python3.5/site-packages/ws4py/websocket.py", line 377, in process
self.received_message(s.message)
File "/home/julian/prog/record/logger/discord/client.py", line 133, in received_message
self.dispatch('socket_update', event, data)
File "/home/julian/prog/record/logger/discord/client.py", line 537, in dispatch
getattr(self, handle_method, _null_event)(*args, **kwargs)
File "/home/julian/prog/record/logger/discord/client.py", line 545, in handle_socket_update
getattr(self.connection, method)(data)
File "/home/julian/prog/record/logger/discord/client.py", line 311, in handle_guild_member_remove
server.members.remove(member)
ValueError: list.remove(x): x not in list
This was encountered on commit 5efddaf of the develop branch.
VOICE_STATE_UPDATE
GUILD_ROLE_DELETE
GUILD_ROLE_CREATE
GUILD_ROLE_UPDATE
Examples:
{
"s": 265,
"op": 0,
"d": {
"channel_id": "81826890993639424",
"token": "3a7c9908604b42d6",
"self_mute": false,
"user_id": "79285195756273664",
"mute": false,
"self_deaf": false,
"suppress": false,
"guild_id": "81826890972667904",
"deaf": false,
"session_id": "a9ae84990118100fc45b1579b0ae02fd"
},
"t": "VOICE_STATE_UPDATE"
}
GUILD_ROLE_CREATE data.
{
"guild_id": "80056038593662976",
"role": {
"name": "new role",
"color": 0,
"hoist": false,
"position": 14,
"id": "103972673217892352",
"permissions": 36953089
}
}
GUILD_ROLE_DELETE data
{
"guild_id": "80056038593662976",
"role_id": "103972673217892352"
}
GUILD_ROLE_UPDATE data
{
"guild_id": "80056038593662976",
"role": {
"name": "test role",
"color": 0,
"hoist": false,
"position": 4,
"id": "87687492047761408",
"permissions": 36953089
}
}
A parallel for permissions for. No need for a breaking change -- it can be an alias of sorts.
Discord can apparently send duplicate CHANNEL_DELETEs.
This causes us to crash. : )
WebSocket Event: {'op': 0, 's': 1930069, 'd': {'last_message_id': '118018179669819392', 'position': 12, 'name': 'memeverse', 'permission_overwrites': [{'deny': 131072, 'id': '107053649628258304', 'allow': 0, 'type': 'role'}], 'id': '115560288178143238', 'topic': 'All the memes', 'is_private': False, 'guild_id': '107053649628258304', 'type': 'text'}, 't': 'CHANNEL_DELETE'}
WebSocket Event: {'op': 0, 's': 1930070, 'd': {'last_message_id': '118018179669819392', 'position': 12, 'name': 'memeverse', 'permission_overwrites': [{'deny': 131072, 'id': '107053649628258304', 'allow': 0, 'type': 'role'}], 'id': '115560288178143238', 'topic': 'All the memes', 'is_private': False, 'guild_id': '107053649628258304', 'type': 'text'}, 't': 'CHANNEL_DELETE'}
self.dispatch('socket_update', event, data)
File "/var/lib/spoo/venv/lib/python3.4/site-packages/discord/client.py", line 550, in dispatch
getattr(self, handle_method, _null_event)(*args, **kwargs)
File "/var/lib/spoo/venv/lib/python3.4/site-packages/discord/client.py", line 558, in handle_socket_update
getattr(self.connection, method)(data)
File "/var/lib/spoo/venv/lib/python3.4/site-packages/discord/client.py", line 276, in handle_channel_delete
server.channels.remove(channel)
ValueError: list.remove(x): x not in list
Something to add to my todo list for a later date.
Stan says:
Just so you guys know probably within a week there will be a major real-time system change to Discord.
the /gateway call will need the auth token because gateways will be assigned around a consistent hash ring
If you conncet to the wrong gateway it will send you a redirect opcode with the URL to the correct one
But the easiest way to be ready for this is to just send the auth token to /api/gateway and then you dont need to worry about it
But the redirect opcode can be also fired if the servers rebalance
but doubt that will be happening for a bit after the upgrade
its special cause gateways support resuming a session id
instead of identify you send a resume
with the previous session id
and it keeps going on the new node
This way we can seamless move people between gateways during DDoS or just scale up ๐
also works for timeouts (aka cloudflare issue)
opcode is 7
and the data is just
{"url": "new websocket url here"}
If you want to support resuming a session you need to keep the session_id in your websocket instance.. and also keep track of the 's' variable aka seq on events (keep last one)
and when you try reconnect after a DC or a redirect
send opcode 6 with {'session_id': session_id, 'seq': seq}
instead of identify
every message will have a seq
's'
keep the last one
At start of the the function received_message the variable msg
includes the embeds
data but after msg
is processed into a dict here embeds
is empty. I assume Python is probably at fault here for not converting embeds
(an array of JSON objects) to a list of dicts.
Something to help people make basic or even complex bots in a nice self-contained manner.
Roadmap in no particular order:
help
command that could be customised.
Formatter
to change the output of help.Hi,
I have the "Quick Example" code from the README, and I want to add a message when the bot is ready, in the on_ready()
function.
how do I specify the message be made on the #general
channel?
As title says, add support for Audio API like https://github.com/RogueException/Discord.Net has.
I'm trying to run this script with the example
Login goes fine, client.accept_invite goes fine.
But once the bot is added to a server(manual or with script, serverowner/admin rights or not) I get this error/quit when I run bot.py
Traceback (most recent call last):
File "C:\Users\someone\Desktop\discordbot\bot.py", line 31, in <module>
client.run()
File "C:\Python34\lib\site-packages\discord.py-0.9.0-py3.4.egg\discord\client.py", line 542, in run
File "C:\Python34\lib\site-packages\ws4py-0.3.4-py3.4.egg\ws4py\websocket.py", line 427, in run
File "C:\Python34\lib\site-packages\ws4py-0.3.4-py3.4.egg\ws4py\websocket.py", line 305, in once
File "C:\Python34\lib\site-packages\ws4py-0.3.4-py3.4.egg\ws4py\websocket.py", line 377, in process
File "C:\Python34\lib\site-packages\discord.py-0.9.0-py3.4.egg\discord\client.py", line 128, in received_message
File "C:\Python34\lib\site-packages\discord.py-0.9.0-py3.4.egg\discord\client.py", line 519, in dispatch
File "C:\Python34\lib\site-packages\discord.py-0.9.0-py3.4.egg\discord\client.py", line 527, in handle_socket_update
File "C:\Python34\lib\site-packages\discord.py-0.9.0-py3.4.egg\discord\client.py", line 160, in handle_ready
File "C:\Python34\lib\site-packages\discord.py-0.9.0-py3.4.egg\discord\client.py", line 150, in _add_server
File "C:\Python34\lib\site-packages\discord.py-0.9.0-py3.4.egg\discord\server.py", line 77, in __init__
File "C:\Python34\lib\site-packages\discord.py-0.9.0-py3.4.egg\discord\server.py", line 122, in _from_data
KeyError: 'game_id'
From a quick code and documentation search, there's no functionality for handling images sent, or sending images. Would this be hard to implement? There doesn't even seem to be functionality for downloading raw image data as a string. At least this functionality would be helpful, because:
import discord
from PIL import Image
from StringIO import StringIO
client = discord.Client()
client.login('user','password')
def on_message(message):
buff = StringIO()
buff.write(message.content)
try:
im = Image.open(buff)
isImage=True
except:
text = message.content
isImage=False
if isImage:
im.save("img.jpg")
else:
print text
Setting it up like this would be an easy way to download images. Uploading images might work similarly.
Traceback (most recent call last):
File "bot.py", line 321, in
client.run()
File "/usr/local/lib/python2.7/dist-packages/discord/client.py", line 550, in run
self.ws.run()
File "/usr/local/lib/python2.7/dist-packages/ws4py/websocket.py", line 427, in run
if not self.once():
File "/usr/local/lib/python2.7/dist-packages/ws4py/websocket.py", line 305, in once
if not self.process(b):
File "/usr/local/lib/python2.7/dist-packages/ws4py/websocket.py", line 377, in process
self.received_message(s.message)
File "/usr/local/lib/python2.7/dist-packages/discord/client.py", line 129, in received_message
self.dispatch('socket_update', event, data)
File "/usr/local/lib/python2.7/dist-packages/discord/client.py", line 527, in dispatch
getattr(self, handle_method, utils._null_event)(_args, *_kwargs)
File "/usr/local/lib/python2.7/dist-packages/discord/client.py", line 535, in handle_socket_update
getattr(self.connection, method)(data)
File "/usr/local/lib/python2.7/dist-packages/discord/client.py", line 262, in handle_guild_member_add
member = Member(server=server, deaf=False, mute=False, **data)
TypeError: type object got multiple values for keyword argument 'mute'
Apparently there's a delete-message-days=n
parameter in the bans endpoint. n
is capped at 7.
One of the biggest problems people usually talk about with the library is how the library is inherently blocking, either through the websocket itself or the events themselves. These issues are not inherently related to the library being async or not but a consequence of not having a threading model set up for these things.
That aside, an often mentioned thing people want from the library is for it to be more async. I won't divulge on the fact whether those people actually know the pros and cons but I will list them below. I hope to use this issue as a RFC to see if it's truly worth considering.
These lists are non-exhaustive.
yield from
(or await
in Python 3.5+) to actually invoke it.
asyncio
errors.asyncio
event loop.discord.Client
is heavily affected since the data classes just hold and parse data.discord.Client
is a large chunk of the library and rewriting is a very annoying task.asyncio
module found in pip
.discord.Client
will allow me to clean-up the code significantly.bytes
vs str
vs unicode
is one of the biggest compatibility hurdles that I put up with and removing it is a good thing.asyncio
? Why not Twister or gevent or my favourite library here?asyncio
comes built-in and is the future of asynchronous programming in Python.
The language itself now comes with full support for the stuff in asyncio
module such as coroutines.
You can write async def
blocks, async for
loops, and async with
statements. The support for
asynchronous programming in Python is essentially all based on the core concepts made in asyncio
.
Another pro is that I can use libraries that are developed with asyncio
in mind such as aiohttp
and have little external dependencies on the user.
Performance of these libraries is irrelevant. Python as a language is already "slow" and seeking
a lot of bleeding edge speed for the async library will probably not outweigh the benefits of
having to use a standardised library.
I am willing to reconsider other options but for now, I am strictly approaching this design by only
considering asyncio
and nothing else.
The purpose of this RFC is to gauge library user interests and asking if these changes are worth it
going forward. If you have anything to add please comment below. I'll be reading all the comments
here and taking them seriously.
You can also use this thread to vote on the issue.
Of course, here's a link to the library if you're curious of how it is and the Discord API server where discussion will also take place.
It's possible that messages are reordered such that a MESSAGE_CREATE event comes before the corresponding CHANNEL_CREATE for the private chat. This causes the code to crash with an AssertionError.
File "bot.py", line 316, in <module>
charset='utf8mb4',
File "/home/julian/prog/record/logger/discord/client.py", line 518, in run
self.ws.run()
File "/usr/lib/python3.5/site-packages/ws4py/websocket.py", line 427, in run
if not self.once():
File "/usr/lib/python3.5/site-packages/ws4py/websocket.py", line 305, in once
if not self.process(b):
File "/usr/lib/python3.5/site-packages/ws4py/websocket.py", line 377, in process
self.received_message(s.message)
File "/home/julian/prog/record/logger/discord/client.py", line 128, in received_message
self.dispatch('socket_update', event, data)
File "/home/julian/prog/record/logger/discord/client.py", line 505, in dispatch
getattr(self, handle_method, _null_event)(*args, **kwargs)
File "/home/julian/prog/record/logger/discord/client.py", line 513, in handle_socket_update
getattr(self.connection, method)(data)
File "/home/julian/prog/record/logger/discord/client.py", line 211, in handle_message_create
message = Message(channel=channel, **data)
File "/home/julian/prog/record/logger/discord/message.py", line 89, in __init__
self._upgrade_to_member()
File "/home/julian/prog/record/logger/discord/message.py", line 92, in _upgrade_to_member
assert self.channel is not None
AssertionError
WebSocket Context (not much to see, it's just a message with an unknown channel id)
The format seems to be.. <:emoji_name:emoji_id>
. I suppose transforming these into :emoji_name:
is a good call.
Running echo.py from the examples directory. When I type a message into a channel, the bot repeats the message as expected, but doesn't stop repeating it! Adding debug statements suggests that on_message only gets called once, so it seems like send_message is repeatedly sending without ever returning, but I can't see anything in the code that would try to retransmit like this. (I checked both here at HEAD and the code actually installed on my machine)
Any idea what's going on?
I'm using discord.py 0.6.3 (from 'pip install discord.py')
So like the title says I am not sure if there is a function that I could import a Voice Channel name and it outputs the ID for me.
This is for Joining a voice channel when someone uses a command and they specify a Voice Channel name for the bot to Join.
If a Voice Channel of a name specified does not exist it must show a error.
The logging module already supports this in the formatting so repeating it twice is unnecessary.
Message.author at the moment is a User
instance because it is possible for the message to be a private message in which Member
does not make sense. However, it would be useful to receive a Member
if it is possible and then delegate to User
if it isn't possible as it would allow you to receive more information about the message author without having to loop through the member list yourself.
Running the expression
'\n'.join(['**Server** {}\n{}'.format(s.name, '\n'.join(
['"{}"'.format(r.name) for r in s.roles if r.is_everyone()]
)) for s in self.servers])
to list up all @everyone
roles in all servers yielded
Server Technic
Server Logger Test
"@everyone"
Server /r/Dota2
"@everyone"
"cant post links"
Server Discord Developers
Server Discord API
"@everyone"
Which is obviously not correct. Replacing r.is_everyone()
with r.id == s.id
correctly listed up all @everyone
roles. I suggest changing the logic behind Role.is_everyone()
to check if the role id is equal to the server id to fix this.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.