Skip to content

Instantly share code, notes, and snippets.

@132ikl
Last active July 28, 2022 09:54
Show Gist options
  • Save 132ikl/95f8d97cdd44fbe815ffb48c802bb07e to your computer and use it in GitHub Desktop.
Save 132ikl/95f8d97cdd44fbe815ffb48c802bb07e to your computer and use it in GitHub Desktop.
Weenie Hut General Messaging Protocol

What is Weenie Hut General Messaging Protocol (WHGMP)?

WHGMP is a message protocol which uses 2 Discord bots and 9 channels.

(pssst... click here to see a more detailed project, with the main bot in addition to the messaging protocol)

How does it work?

WHGMP uses the read/unread badge* in a channel to represent a bit (unread = 1, read = 0). By using 8 channels, one byte can be stored.

The sender waits for a message from the user, then begins to send messages to the data channels. After storing a single byte, a message is sent to the "clock" channel, letting the receiver know to check the read/unread status. Based off of that, a single byte is constructed. When a null-byte is received, the resulting string is printed.

*: Technically, it uses the ID of the last message sent in the channel. Discord stores this separately from the actual last message in the channel though, which is why you can see an unread badge even if the message was deleted.

The name originates from the Discord server this "protocol" was inspired by. One fateful night the server became a Weenie Hut General themed server (don't ask), and only the message "weenie hut general" was allowed to be sent in any channel (similar to the cup server, but with less loopholes). Naturally, I begin theorizing ways to communicate despite only being able to send the message "weenie hut general". This is the result of that.

Okay, so how fast is it?

17 seconds to send hello world.

LICENSE

CC0. If you actually want or need to use this for some reason, God help you.

# channel IDs to use as data bits
DATA_CHANNELS = [
XXXXXXXXXXXXXXXXXX,
XXXXXXXXXXXXXXXXXX,
XXXXXXXXXXXXXXXXXX,
XXXXXXXXXXXXXXXXXX,
XXXXXXXXXXXXXXXXXX,
XXXXXXXXXXXXXXXXXX,
XXXXXXXXXXXXXXXXXX,
XXXXXXXXXXXXXXXXXX,
]
# channel ID to use as message complete bit
CLOCK_CHANNEL = XXXXXXXXXXXXXXXXXX
from codecs import decode
from discord import Client
from channels import CLOCK_CHANNEL, DATA_CHANNELS
class WHGReceiver(Client):
last_ids = None
string = ""
async def get_channels(self):
return [await self.fetch_channel(channel_id) for channel_id in DATA_CHANNELS]
async def on_ready(self):
print("Logged on as {0}!".format(self.user))
self.last_ids = [
channel.last_message_id for channel in await self.get_channels()
]
async def on_message(self, message):
if message.channel.id == CLOCK_CHANNEL:
byte = ""
last_ids = [
channel.last_message_id for channel in await self.get_channels()
]
for ids in zip(last_ids, self.last_ids):
if ids[0] == ids[1]:
byte += "0"
else:
byte += "1"
# binary to hex
byte = hex(int(byte, 2))[2:]
# hex to utf-8, ensure least 2 places
byte = decode(byte.zfill(2), "hex")
# utf-8 to string
byte = decode(byte, "utf-8")
if byte == "\x00":
print(self.string)
self.string = ""
else:
self.string += byte
self.last_ids = last_ids
client = WHGReceiver()
client.run("YOUR_TOKEN_HERE")
from asyncio import run_coroutine_threadsafe, sleep
from codecs import encode
from io import BytesIO
from threading import Thread
from discord import Client
from channels import CLOCK_CHANNEL, DATA_CHANNELS
buffer = BytesIO()
buffer.seek(0)
class WHGSender(Client):
def __init__(self, buffer):
self.buffer = buffer
super().__init__()
async def get_channels(self):
return [await self.fetch_channel(channel_id) for channel_id in DATA_CHANNELS]
async def on_ready(self):
print("Logged on as {0}!".format(self.user))
async def send_message(self):
buffer.seek(0)
channels = await self.get_channels()
clock = await self.fetch_channel(CLOCK_CHANNEL)
while byte := buffer.read(1):
byte = bin(byte[0])[2:]
for i in zip(byte.zfill(8), channels):
if i[0] == "1":
await i[1].send(content="x")
await clock.send(content="x")
await sleep(0.5)
buffer.truncate(0)
buffer.seek(0)
self.sending = False
def trigger_send(self):
self.sending = True
run_coroutine_threadsafe(self.send_message(), client.loop)
while self.sending:
pass
def user_input_thread(buffer, client):
while not client.is_ready():
pass
while True:
message = input("Type message to send: ") + "\x00"
message = encode(message, "utf-8")
buffer.write(message)
client.trigger_send()
client = WHGSender(buffer)
thread = Thread(target=user_input_thread, args=(buffer, client))
thread.daemon = True
thread.start()
client.run("YOUR_TOKEN_HERE")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment