|
@@ -1,36 +1,28 @@
|
|
|
-#!/var/www/html/webhooks/.venv/bin/python
|
|
|
# File name: Hooks.py
|
|
|
# Date created: 09/16/2022
|
|
|
-# Date last modified: 10/15/2022
|
|
|
-# Python Version: 3.9.2
|
|
|
-# Copyright © 2022 DeadTOm
|
|
|
+# Date last modified: 2/10/2025
|
|
|
+# Python Version: 3.11.2
|
|
|
+# Copyright © 2025 DeadTOm
|
|
|
# TODO: Make routes for various chat and video links
|
|
|
|
|
|
try:
|
|
|
- from names import m_name
|
|
|
from config import *
|
|
|
- from auth import *
|
|
|
- from DTChatbot import *
|
|
|
from flask import Flask, jsonify, current_app, request
|
|
|
import requests
|
|
|
import logging
|
|
|
import time
|
|
|
import socket
|
|
|
- from mcstatus import JavaServer
|
|
|
+ import slixmpp
|
|
|
+ import sys
|
|
|
except Exception as import_error: # Log any errors loading modules, and try to keep running
|
|
|
- fail_log = open('/var/www/html/webhooks.log', 'a')
|
|
|
+ fail_log = open(owncast_logfile, 'a')
|
|
|
fail_log.write(f'------{import_error}------\n')
|
|
|
fail_log.close()
|
|
|
|
|
|
-logging.basicConfig(filename='/var/www/html/webhooks.log', level=logging.INFO)
|
|
|
-
|
|
|
-current_names = [] # Initialize empty list to hold current names
|
|
|
+logging.basicConfig(filename=owncast_logfile, level=logging.INFO)
|
|
|
|
|
|
testing = 0 # Are we testing? 1 for testing. 0 for live.
|
|
|
|
|
|
-get_m_info = requests.get('https://fosstodon.org/api/v1/accounts/verify_credentials', headers={'Authorization': m_api_key, 'Accept': 'application/json'}) # Get Mastodon account information
|
|
|
-get_m_info = get_m_info.json() # Jsonify the response
|
|
|
-
|
|
|
app = Flask(__name__)
|
|
|
|
|
|
|
|
@@ -42,66 +34,30 @@ def get_now(): # This creates and returns a time stamp
|
|
|
logging.info(f'\n\n\n\n{get_now()} - Webhook called.\n')
|
|
|
|
|
|
|
|
|
-def streaming_m_name(): # Change Mastodon name to show we're streaming
|
|
|
- get_m_info = requests.get('https://fosstodon.org/api/v1/accounts/verify_credentials', headers={'Authorization': m_api_key, 'Accept': 'application/json'}) # Get Mastodon account information
|
|
|
- get_m_info = get_m_info.json() # Jsonify the response
|
|
|
- current_m_name = f'm_name = \'{get_m_info["display_name"]}\'' # Create Mastodon list entry
|
|
|
- current_names.append(current_m_name) # Append to list of current names
|
|
|
- logging.info(f'{get_now()} - Current Mastodon name is \"{get_m_info["display_name"]}\".')
|
|
|
+class SendMsgBot(slixmpp.ClientXMPP):
|
|
|
+ def __init__(self, jid, password, recipient, message):
|
|
|
+ slixmpp.ClientXMPP.__init__(self, jid, password)
|
|
|
|
|
|
- set_m_name = requests.patch('https://fosstodon.org/api/v1/accounts/update_credentials', params={'display_name': m_streaming_name}, headers={'Authorization': m_api_key, 'Accept': 'application/json'}) # Set Mastodon display name
|
|
|
- set_m_name = set_m_name.json() # Jsonify the response
|
|
|
+ self.recipient = recipient
|
|
|
+ self.msg = message
|
|
|
|
|
|
- logging.info(f'{get_now()} - Mastodon name is now \"{set_m_name["display_name"]}\".')
|
|
|
+ self.add_event_handler("session_start", self.start)
|
|
|
|
|
|
+ async def start(self, event):
|
|
|
+ self.send_presence()
|
|
|
+ await self.get_roster()
|
|
|
|
|
|
-def reg_m_name(): # Change Mastodon name to regular name
|
|
|
- set_m_name = requests.patch('https://fosstodon.org/api/v1/accounts/update_credentials', params={'display_name': m_name}, headers={'Authorization': m_api_key, 'Accept': 'application/json'}) # Set Mastodon display name
|
|
|
- set_m_name = set_m_name.json() # Jsonify the response
|
|
|
+ self.send_message(mto=self.recipient, mbody=self.msg, mtype='chat')
|
|
|
|
|
|
- logging.info(f'{get_now()} - Mastodon name is now \"{set_m_name["display_name"]}\".')
|
|
|
+ self.disconnect()
|
|
|
|
|
|
|
|
|
-def write_current_names(): # Write current names to names.py
|
|
|
- logging.info(f'{get_now()} - Storing {current_names}.')
|
|
|
- try:
|
|
|
- file = open("/var/www/html/webhooks/names.py", "w")
|
|
|
- for name in current_names:
|
|
|
- file.write(f'{name}\n')
|
|
|
- file.close()
|
|
|
- except Exception as write_error:
|
|
|
- logging.info(f'{get_now()} - {write_error}')
|
|
|
-
|
|
|
-
|
|
|
-def mc_chat(mc_msg): # Send chat message to Minecraft chat
|
|
|
- logging.info(f'{get_now()} - Checking Minecraft server for players.')
|
|
|
- mc_server = JavaServer.lookup('mc.deadtom.me:25565')
|
|
|
- query = mc_server.query() # Query Minecraft server for players
|
|
|
- cur_players = query.players.names
|
|
|
- if '_DeadTOm_' in cur_players: # If I'm on the server, send message
|
|
|
- logging.info(f'{get_now()} - DeadTOm is on the server, sending message.')
|
|
|
- logging.info(f'{get_now()} - Connecting...')
|
|
|
- sock_host = 'mc.deadtom.me'
|
|
|
- sock_port = 6791
|
|
|
- try:
|
|
|
- mySocket = socket.socket()
|
|
|
- mySocket.connect((sock_host, sock_port))
|
|
|
- time.sleep(1)
|
|
|
- logging.info(f'{get_now()} - Connected. Sending {mc_msg}...')
|
|
|
- mySocket.send(mc_msg.encode())
|
|
|
- logging.info(f'{get_now()} - sent.')
|
|
|
- mySocket.close()
|
|
|
- except ConnectionRefusedError as error:
|
|
|
- logging.info(f'{get_now()} - Unable to contact {sock_host} - {error}.')
|
|
|
- mySocket.close()
|
|
|
- except TimeoutError as error:
|
|
|
- logging.info(f'{get_now()} - Unable to contact {sock_host} - {error}.')
|
|
|
- mySocket.close()
|
|
|
- except OSError as error:
|
|
|
- logging.info(f'{get_now()} - Unable to contact {sock_host} - {error}.')
|
|
|
- mySocket.close()
|
|
|
- else: # If I'm not on the server, don't send the message
|
|
|
- logging.info(f'{get_now()} - DeadTOm is not on the server, so not sending message.')
|
|
|
+def xmpp_chat(ownchat_msg):
|
|
|
+ xmpp = SendMsgBot(jid, password, to, ownchat_msg)
|
|
|
+ xmpp.register_plugin('xep_0030') # Service Discovery
|
|
|
+ xmpp.register_plugin('xep_0199') # XMPP Ping
|
|
|
+ xmpp.connect()
|
|
|
+ xmpp.process(forever=False)
|
|
|
|
|
|
|
|
|
def set_hashtags(title): # Sets up hash tags to be appended to social media
|
|
@@ -114,70 +70,26 @@ def set_hashtags(title): # Sets up hash tags to be appended to social media
|
|
|
if tag in check_title:
|
|
|
print(f'Found {tag}, adding {tag_dict[tag]} to hashtags.')
|
|
|
tags = f'{tags}{tag_dict[tag]} '
|
|
|
- tags = f'{tags}#Owncast #NSFW' # Adding NSFW tag, just for good measure
|
|
|
+ tags = f'{tags}#Owncast'
|
|
|
logging.info(f'{get_now()} - Adding {tags} to title.')
|
|
|
return tags
|
|
|
|
|
|
|
|
|
-def social_post(msg, discmsg): # Post to Mastodon
|
|
|
- # Send to Mastodon
|
|
|
- logging.info(f'{get_now()} - Posting to Mastodon.')
|
|
|
- response = requests.post(m_api_url,
|
|
|
- params={'status': msg},
|
|
|
- headers={'Authorization': m_api_key,
|
|
|
- 'visibility': 'public',
|
|
|
- 'Accept': 'application/json'})
|
|
|
- json_response = response.json()
|
|
|
- for line in json_response:
|
|
|
- logging.debug(f'{get_now()} - API returned: {line}: {json_response[line]}')
|
|
|
-
|
|
|
- # Send to Discord
|
|
|
- # for all params, see https://discordapp.com/developers/docs/resources/webhook#execute-webhook
|
|
|
- data = {
|
|
|
- 'content': discmsg
|
|
|
- }
|
|
|
- talkback = requests.post(discordwebhookurl, json=data)
|
|
|
- if 200 <= talkback.status_code < 300:
|
|
|
- logging.info(f'{get_now()} - Discord message sent {talkback.status_code}')
|
|
|
- else:
|
|
|
- logging.info(
|
|
|
- f'{get_now()} - Discord message not sent with {talkback.status_code}, response:\n{talkback.json()}')
|
|
|
-
|
|
|
-
|
|
|
-@app.route('/stream_started/', methods=["POST"])
|
|
|
-def start():
|
|
|
- logging.info(f'{get_now()} - stream_started request')
|
|
|
+@app.route('/user_left/', methods=["POST"])
|
|
|
+def left():
|
|
|
+ logging.info(f'{get_now()} - user_left request')
|
|
|
raw_data = request.get_json(force=True) # Get the raw data
|
|
|
event_data = raw_data['eventData']
|
|
|
- stream_title = event_data['streamTitle']
|
|
|
- hashtags = set_hashtags(stream_title.lower())
|
|
|
- msg = f'I\'m streaming on Owncast, at https://owncast.deadtom.me. {stream_title} {hashtags}'
|
|
|
- logging.debug(f'{get_now()} - Constructed Mastodon/Twitter message: {msg}')
|
|
|
- discmsg = f'DeadTOm is streaming on Owncast, at https://owncast.deadtom.me. {stream_title}'
|
|
|
- if testing != 1: # If we're testing, don't actually send out notification
|
|
|
- streaming_m_name()
|
|
|
- social_post(msg, discmsg)
|
|
|
- else:
|
|
|
- logging.info(f'-----------------------\n\n'
|
|
|
- f'{get_now()} - Currently running in test mode. We are streaming, but no notifications are being sent to social media.'
|
|
|
- f'\n\n---------------------------------')
|
|
|
-
|
|
|
- return jsonify({"Data": raw_data, })
|
|
|
-
|
|
|
-
|
|
|
-@app.route('/stream_stopped/', methods=["POST"])
|
|
|
-def stop():
|
|
|
- logging.info(f'{get_now()} - stream_stopped request')
|
|
|
- raw_data = request.get_json(force=True) # Get the raw data
|
|
|
- event_data = raw_data['eventData']
|
|
|
- stream_title = event_data['streamTitle']
|
|
|
- hashtags = set_hashtags(stream_title.lower()) # Make title lower case, for comparison with list of tags
|
|
|
- msg = f'All done streaming, for now. Maybe catch me next time on Owncast, at https://owncast.deadtom.me.\n\n{hashtags}'
|
|
|
- discmsg = f'DeadTOm is done streaming.'
|
|
|
- if testing != 1: # If we're testing, don't actually send out notification
|
|
|
- reg_m_name()
|
|
|
- social_post(msg, discmsg)
|
|
|
-
|
|
|
+ logging.info(f'{get_now()} - {raw_data}')
|
|
|
+ response = requests.get(f'{api_url}/api/status')
|
|
|
+ response = response.json()
|
|
|
+ if response['online'] is True: # Check if we are currently streaming, if so, send notification
|
|
|
+ chatter_name = event_data['user']['displayName']
|
|
|
+ ownchat_msg = f'{chatter_name} left the chat.'
|
|
|
+ logging.info(f'{get_now()} - {ownchat_msg}')
|
|
|
+ xmpp_chat(ownchat_msg)
|
|
|
+ else: # If not currently streaming, do nothing.
|
|
|
+ logging.info(f'{get_now()} - We are not streaming, so not sending XMPP message.')
|
|
|
return jsonify({"Data": raw_data, })
|
|
|
|
|
|
|
|
@@ -189,9 +101,8 @@ def joined():
|
|
|
chatter_name = event_data['user']['displayName']
|
|
|
ownchat_msg = f'{chatter_name} joined the chat.'
|
|
|
logging.info(f'{get_now()} - {ownchat_msg}')
|
|
|
- mc_chat(ownchat_msg)
|
|
|
- logging.info(f'{get_now()} - Sent to Minecraft server.')
|
|
|
-
|
|
|
+ logging.info(f'{get_now()} - {raw_data}')
|
|
|
+ xmpp_chat(ownchat_msg)
|
|
|
return jsonify({"Data": raw_data, })
|
|
|
|
|
|
|
|
@@ -207,38 +118,22 @@ def changed():
|
|
|
ownchat_msg = f'{chatter_old_name} changed their name to {chatter_new_name}'
|
|
|
logging.debug(f'{get_now()} - {type}\n{raw_data}')
|
|
|
logging.info(f'{get_now()} - {ownchat_msg}')
|
|
|
- mc_chat(ownchat_msg)
|
|
|
- logging.info(f'{get_now()} - Sent to Minecraft server.')
|
|
|
-
|
|
|
+ xmpp_chat(ownchat_msg)
|
|
|
return jsonify({"Data": raw_data, })
|
|
|
|
|
|
|
|
|
@app.route('/message_sent/', methods=["POST"])
|
|
|
def sent():
|
|
|
+ logging.info(f'----------------------------------------------------------------------------')
|
|
|
logging.info(f'{get_now()} - message_sent request')
|
|
|
raw_data = request.get_json(force=True) # Get the raw data
|
|
|
event_data = raw_data['eventData']
|
|
|
chatter_name = event_data['user']['displayName']
|
|
|
+ chatter_id = event_data['user']['id']
|
|
|
chat_msg = event_data['rawBody']
|
|
|
- ownchat_msg = f'{chatter_name} on Owncast says: {chat_msg}'
|
|
|
+ ownchat_msg = f'{chatter_name}: {chat_msg}'
|
|
|
logging.info(f'{get_now()} - Chat message: \"{ownchat_msg}\".')
|
|
|
- mc_chat(ownchat_msg)
|
|
|
- logging.info(f'{get_now()} - Sent to Minecraft server.')
|
|
|
-
|
|
|
- return jsonify({"Data": raw_data, })
|
|
|
-
|
|
|
-
|
|
|
-@app.route('/chatbot/', methods=["POST"])
|
|
|
-def send_chatbot():
|
|
|
- logging.info(f'{get_now()} - message_sent request')
|
|
|
- raw_data = request.get_json(force=True) # Get the raw data
|
|
|
- event_data = raw_data['eventData']
|
|
|
- chatter_name = event_data['user']['displayName']
|
|
|
- chat_msg = event_data['rawBody']
|
|
|
- bot_msg = f'{chatter_name}, {chat_msg}'
|
|
|
- DTChatbot.chat_bot(bot_msg)
|
|
|
- logging.info(f'{get_now()} - Sent to chat bot.')
|
|
|
-
|
|
|
+ xmpp_chat(ownchat_msg)
|
|
|
return jsonify({"Data": raw_data, })
|
|
|
|
|
|
|