Skip to content

Instantly share code, notes, and snippets.

@marios8543
Last active July 14, 2019 11:36
Show Gist options
  • Save marios8543/a9a8755de55eea59ef5bacfa5b9c996f to your computer and use it in GitHub Desktop.
Save marios8543/a9a8755de55eea59ef5bacfa5b9c996f to your computer and use it in GitHub Desktop.
from Discord.uwebsockets import client
from machine import Timer
from ujson import loads,dumps
from urequests import post
import uzlib
import sys
ZLIB_SUFFIX = "ÿÿ"
class Client:
def __init__(self,prefix="esp!"):
self.commands = {}
self.events = {}
self.on_message = None
self.prefix = prefix
self.websocket = None
self.heartbeat_timer = Timer(-1)
self.sequence = 0
self.session_id = None
self.token = None
self.running = True
def add_command(self,func):
if func.__name__ in self.commands:
return
self.commands[func.__name__] = func
def add_event(self,func):
if func.__name__ not in self.events:
self.events[func.__name__] = [func]
else:
self.events[func.__name__].append(func)
def on_message_event(self,func):
self.on_message = func
def send(self,channel,content):
res = post("https://discordapp.com/api/v6/channels/{}/messages".format(channel),json={'content':content},headers={'Authorization':'Bot {}'.format(self.token),'Content-Type':'application/json'})
if res.status_code==200:
print("Sent message to {} successfully".format(channel))
else:
print("{} Failed to send message ({})".format(res.status_code,res.text))
res.close()
def start(self,token):
while self.running:
self.websocket = client.connect('wss://gateway.discord.gg?encoding=json&v=6')
hrt = loads(self.websocket.recv())
self.heartbeat_timer.init(period=hrt['d']['heartbeat_interval'],mode=Timer.PERIODIC,callback=lambda t: self.websocket.send(dumps({'op':1,'d':None if self.sequence==0 else self.sequence})))
print("Received hello. Starting heartbeat every {}ms".format(hrt['d']['heartbeat_interval']))
if not self.session_id:
print("No session id to resume. Sending identify.")
self.websocket.send(dumps({
'op':2,
'd':{
'token':token,
'properties':{
"$os": "linux",
"$browser": "disco",
"$device": "disco"
}
}
}))
else:
print("Resuming...")
self.websocket.send(dumps({
'op':6,
'd':{
'token':token,
'session_id':self.session_id,
'seq':self.sequence
}
}))
self.token = token
print("Receiving messages")
while self.running:
try:
re = self.websocket.recv()
if not re:
print("Received empty message. Reconnecting to websocket")
break
if len(re) < 4 or re[-4:] != ZLIB_SUFFIX:
re = loads(re)
else:
re = loads(uzlib.decompress(re).decode('utf-8'))
self.sequence+=1
if len(str(re['op']))==4:
print("Disconnected from the gateway with opcode {}. Attempting reconnect".format(re['op']))
break
elif re['op']==0 and re['t']=='READY':
self.session_id = re['d']['session_id']
print("Fetched session id ({})".format(self.session_id))
elif re['op']==0 and re['t']=='MESSAGE_CREATE':
msg = Message(re['d'])
print("Received new message on channel {}".format(msg.channel_id))
if msg.content.startswith(self.prefix):
com = msg.content.split(" ")[0][len(self.prefix):]
if com in self.commands:
try:
self.commands[com](msg)
except Exception as e:
print("An exception occured in command {}".format(com))
sys.print_exception(e)
if re['t'] in self.events:
for i in self.events[re['t']]:
try:
i(re['d'])
except Exception as e:
print("An exception occured in event {}".format(re['t']))
sys.print_exception(e)
if self.on_message:
self.on_message(msg)
except Exception as e:
sys.print_exception(e)
continue
self.heartbeat_timer.deinit()
class User:
def __init__(self,payload):
self.id = payload['id']
self.name = payload['username']
self.discriminator = payload['discriminator']
class Message:
def __init__(self,payload):
self.id = payload['id']
self.channel_id = payload['channel_id']
self.author = User(payload['author'])
self.content = payload['content']
self.type = payload['type']
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment