Hehe, hvis noen vil grave seg inn i hullet så kommer koden her!
Laget fra hovedeksempelet på:
https://github.com/sbtinstruments/asyncio-mqtt
og så brukt slegge for å få inn Discord via:
https://discordpy.readthedocs.io/en/latest/api.html
Har ikke klart å forene async-event-loopene til disse to bibliotekene, så jeg har juksa litt. Men det ser ut til å funke på tross av noen warnings.
Kjører denne som en service på Ubuntu-serveren.
import asyncio
from contextlib import AsyncExitStack, asynccontextmanager
from random import randrange
import threading
import time
import asyncio_mqtt
import discord
DISCORD_TOKEN = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
DISCORD_GUILD = "OpenHab"
DISCORD_CHANNEL = "openhab"
MQTT_SERVER = "xxxxxx.xxx"
DISCORD_CLIENT = discord.Client()
async def mqtt2discord():
disc_login = DISCORD_CLIENT.login(DISCORD_TOKEN)
await disc_login
disc_starter = DISCORD_CLIENT.start(DISCORD_TOKEN)
disc_task = asyncio.ensure_future(disc_starter)
time.sleep(2) # Klarer ikke vente på futuren på annet vis.. :(
mqtt_client = asyncio_mqtt.Client(MQTT_SERVER)
await mqtt_client.connect()
# (får en unclosed client session på første await, den
# kommer vel fra den andre tråden som kjører start() )
await push_discord("OpenHAB-Discord integration ready!")
async with AsyncExitStack() as stack:
# Keep track of the asyncio tasks that we create, so that
# we can cancel them on exit
tasks = set()
stack.push_async_callback(cancel_tasks, tasks)
topic_filters = ("discordmessage/send",)
for topic_filter in topic_filters:
manager = mqtt_client.filtered_messages(topic_filter)
messages = await stack.enter_async_context(manager)
template = f'[topic_filter="{topic_filter}"] {{}}'
task = asyncio.create_task(push_many_to_discord(messages))
tasks.add(task)
# Subscribe to topic(s)
await mqtt_client.subscribe("#")
await asyncio.gather(*tasks)
async def push_many_to_discord(mqtt_messages):
async for mqtt_message in mqtt_messages:
await push_discord(mqtt_message.payload.decode())
async def push_discord(msg):
guild = discord.utils.get(DISCORD_CLIENT.guilds, name=DISCORD_GUILD)
if guild is not None:
channel = discord.utils.get(guild.channels, name=DISCORD_CHANNEL)
if channel is not None:
await channel.send(str(msg))
else:
print("channel was None")
else:
print("guild was None")
async def cancel_tasks(tasks):
for task in tasks:
if task.done():
continue
task.cancel()
try:
await task
except asyncio.CancelledError:
pass
async def main():
# Run the advanced_example indefinitely. Reconnect automatically
# if the connection is lost.
reconnect_interval = 3 # [seconds]
while True:
try:
await mqtt2discord()
except asyncio_mqtt.MqttError as error:
print(f'Error "{error}". Reconnecting in {reconnect_interval} seconds.')
finally:
await asyncio.sleep(reconnect_interval)
asyncio.run(main())