Skip to content

Instantly share code, notes, and snippets.

@defnull
Last active April 21, 2023 18:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save defnull/8231ec8633781f621c59e8945256f028 to your computer and use it in GitHub Desktop.
Save defnull/8231ec8633781f621c59e8945256f028 to your computer and use it in GitHub Desktop.
Admin tool to send chat messags to running BBB meetings
#!/usr/bin/env python3
import sys, json, subprocess, time, argparse
"""
Admin tool to send chat messages to running BBB meetings by directly injecting events into the REDIS channel.
This can be used for example to broadcast a maintenance warning message before shuttinng down a server.
Tested with BBB 2.5
Copyright 2022 Marcel Hellkamp
License: MIT
"""
def main():
parser = argparse.ArgumentParser(description='Send system messages to public chats of existing meetings.')
parser.add_argument('--user', default="SYSTEM", help='User name (default: SYSTEM)')
parser.add_argument('--meeting', default="ALL", help='Meeting ID (default: all meetings)')
parser.add_argument('text', help='Message to send')
args = parser.parse_args()
if args.meeting == 'ALL':
meetings = find_all_meetings()
else:
meetings = [args.meeting]
for meeting in meetings:
send_chat(meeting, args.text, args.user)
def get_secret():
with open('/etc/bigbluebutton/bbb-web.properties', 'r') as fp:
for line in fp:
if line.startswith('securitySalt'):
return line.partition("=")[2].strip()
def find_all_meetings():
import xml.etree.ElementTree as ET
import urllib.request
import urllib.parse
import hashlib
secret = get_secret()
command = "getMeetings"
checksum = hashlib.sha1((command+secret).encode('utf8')).hexdigest()
url = f"http://localhost:8090/bigbluebutton/api/{command}?checksum={checksum}"
with urllib.request.urlopen(url) as f:
xml = f.read().decode('utf8')
root = ET.fromstring(xml)
for meeting in root.findall('./meetings/meeting/internalMeetingID'):
yield meeting.text
def send_chat(meeting, text, user):
print(meeting)
ts = int(time.time() * 1000)
event = {
"envelope": {
"name":"GroupChatMessageBroadcastEvtMsg",
"routing": {
"msgType": "BROADCAST_TO_MEETING",
"meetingId": meeting,
"userId": "SYSTEM"
},
"timestamp": ts
},
"core":{
"header":{
"name": "GroupChatMessageBroadcastEvtMsg",
"meetingId": meeting,
"userId": "SYSTEM"
},
"body":{
"chatId": "MAIN-PUBLIC-GROUP-CHAT",
"msg":{
"id": f"{ts}-fake",
"timestamp": ts,
"correlationId":"SYSTEM",
"sender":{
"id": "SYSTEM",
"name": user,
"role": "MODERATOR"
},
"chatEmphasizedText": True,
"message": text
}
}
}
}
subprocess.run(["redis-cli", "PUBLISH", "from-akka-apps-redis-channel", json.dumps(event)], stdout=subprocess.DEVNULL)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment