January 22, 2024
Discord : Fetch Discord Messages Using Discord Websockets
Discord provides a powerful gateway for real-time communication and interaction within communities. By leveraging Discord’s websockets…
By Mayank Joshi
1 min read
Discord provides a powerful gateway for real-time communication and interaction within communities. By leveraging Discord's websockets, developers can create bots that not only listen for messages but also fetch and process them in real-time. In this guide, we'll explore how to use Python and the websockets library to achieve this.
Prerequisites
Before we begin, make sure you have the following:
- Python installed on your machine.
- A Discord bot token. If you don't have a bot yet, you can create one on the Discord Developer Portal.
Import Libraries
import websockets
import websockets.exceptionsimport websockets
import websockets.exceptionsEstablishing Connection to Discord Websockets
The websockets library is used to establish a connection to Discord's gateway. The discord_ws_url variable contains the URL for the gateway, and the websockets.connect method is utilized to create a connection.
discord_ws_url = "wss://gateway.discord.gg/?v=10&encoding-json"
async def listner():
while True:
try:
async with websockets.connect(discord_ws_url) as ws:
await identify(ws)
await on_message(ws)
except websockets.exceptions.ConnectionClosed as e:
logging.error(f"WebSocket connection closed unexpectedly: {e}. Reconnecting...")
await asyncio.sleep(5)
continuediscord_ws_url = "wss://gateway.discord.gg/?v=10&encoding-json"
async def listner():
while True:
try:
async with websockets.connect(discord_ws_url) as ws:
await identify(ws)
await on_message(ws)
except websockets.exceptions.ConnectionClosed as e:
logging.error(f"WebSocket connection closed unexpectedly: {e}. Reconnecting...")
await asyncio.sleep(5)
continueIn the listner function:
websockets.connect(discord_ws_url)establishes a connection to Discord's gateway.async with websockets.connectensures proper resource management by automatically closing the connection when thewithblock is exited.
Identifying the Bot to Discord
Identifying the bot to Discord is a crucial step in the connection process. This involves sending an identification payload, including the bot token, to let Discord know about the bot's presence.
async def identify(ws):
print("Identify")
identify_payload = {
"op": 2,
"d": {
"token": token,
"properties": {"$os": "windows", "$browser": "chrome", "$device": "pc"},
},
}
await ws.send(json.dumps(identify_payload))
logging.info("Identification sent.")async def identify(ws):
print("Identify")
identify_payload = {
"op": 2,
"d": {
"token": token,
"properties": {"$os": "windows", "$browser": "chrome", "$device": "pc"},
},
}
await ws.send(json.dumps(identify_payload))
logging.info("Identification sent.")In the identify function:
- The identify_payload dictionary contains the necessary information for bot identification.
- The op field in the payload is set to 2 to indicate an identify operation.
- await ws.send(json.dumps(identify_payload)) sends the identification payload to Discord.
Handling Discord Gateway Opcodes
Discord uses opcodes (operation codes) to specify the type of operation being performed. Different opcodes indicate various events or actions.
async def on_message(ws):
print("Message Call")
last_sequence = None
while True:
event = json.loads(await ws.recv())
logging.info(f"Event received: {event}")
op_code = event.get("op", None)
if op_code == 10:
# Handle opcode 10 (Hello)
interval = event["d"]["heartbeat_interval"] / 1000
asyncio.create_task(heartbeat(ws, interval, last_sequence))
elif op_code == 0:
# Handle opcode 0 (Dispatch)
last_sequence = event.get("s", None)
event_type = event.get("t")
if event_type == "MESSAGE_CREATE":
# Handle the MESSAGE_CREATE event
# You Can get metadeta of a message in event["d"]
print(event["d"]["content"])
elif op_code == 9:
# Handle opcode 9 (Invalid Session)
logging.info("Invalid session. Starting a new session...")
await identify(ws)async def on_message(ws):
print("Message Call")
last_sequence = None
while True:
event = json.loads(await ws.recv())
logging.info(f"Event received: {event}")
op_code = event.get("op", None)
if op_code == 10:
# Handle opcode 10 (Hello)
interval = event["d"]["heartbeat_interval"] / 1000
asyncio.create_task(heartbeat(ws, interval, last_sequence))
elif op_code == 0:
# Handle opcode 0 (Dispatch)
last_sequence = event.get("s", None)
event_type = event.get("t")
if event_type == "MESSAGE_CREATE":
# Handle the MESSAGE_CREATE event
# You Can get metadeta of a message in event["d"]
print(event["d"]["content"])
elif op_code == 9:
# Handle opcode 9 (Invalid Session)
logging.info("Invalid session. Starting a new session...")
await identify(ws)In the on_message function:
- op_code = event.get("op", None) extracts the opcode from the received event.
- Different sections handle specific opcodes:
- Opcode 10 (Hello) initiates the heartbeat mechanism.
- Opcode 0 (Dispatch) handles dispatched events, such as MESSAGE_CREATE.
- Opcode 9 (Invalid Session) prompts the bot to start a new session. Understanding these opcodes is crucial for building a robust Discord bot that can handle various events and interactions on the platform.