From 43f0204a68bdf812e6b1d2bf589255b6ba9e87bc Mon Sep 17 00:00:00 2001 From: j4nk Date: Sun, 16 Feb 2025 00:42:42 -0500 Subject: [PATCH] Initial commit. Movies work, TV and music do not --- .gitignore | 5 + bot.py | 215 +++++++++++++++++++++++++++++++++++++++++++ config.conf.template | 8 ++ jellyfin_logo.png | Bin 0 -> 25935 bytes 4 files changed, 228 insertions(+) create mode 100644 .gitignore create mode 100644 bot.py create mode 100644 config.conf.template create mode 100644 jellyfin_logo.png diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bd3d491 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +config.conf +*.jpg +*~ +#* +bartonfink.png \ No newline at end of file diff --git a/bot.py b/bot.py new file mode 100644 index 0000000..436f9df --- /dev/null +++ b/bot.py @@ -0,0 +1,215 @@ +import asyncio +import logging +import slixmpp +import requests +import json +import datetime +import time +import configparser +import os +import threading +from jellyfin_apiclient_python import JellyfinClient +import uuid + +def json_to_key_value_string(json_data): + # Parse JSON data + data = json.loads(json_data) + + # Initialize an empty list to store key-value pairs + result_lines = [] + + # Recursively process the JSON data + def process_item(item, prefix=''): + if isinstance(item, dict): + for key, value in item.items(): + if isinstance(value, (dict, list)): + process_item(value, f"{prefix}{key}.") + else: + result_lines.append(f"{prefix}{key}: {value}") + elif isinstance(item, list): + for i, value in enumerate(item): + process_item(value, f"{prefix}[{i}].") + + process_item(data) + + return "\n".join(result_lines) + +class QBBot(slixmpp.ClientXMPP): + def __init__(self, jid, password, room, nick, api_url, api_username, api_password): + slixmpp.ClientXMPP.__init__(self, jid, password) + + self.room = room + self.nick = nick + + + # Initialize Jellyfin caller + self.jf_api = None + self.jf_api_url = api_url + self.jf_api_username = api_username + self.jf_api_password = api_password + self.jf_api_credentials = None + self.jf_api_init() + self.jf_api_login() + + + + self.add_event_handler("session_start", self.session_start) + self.add_event_handler("message", self.message) + # The groupchat_message event is triggered whenever a message + # stanza is received from any chat room. If you also also + # register a handler for the 'message' event, MUC messages + # will be processed by both handlers. + self.add_event_handler("groupchat_message", self.muc_message) + + # If you wanted more functionality, here's how to register plugins: + # self.register_plugin('xep_0030') # Service Discovery + # self.register_plugin('xep_0199') # XMPP Ping + + # Here's how to access plugins once you've registered them: + # self['xep_0030'].add_feature('echo_demo') + + def jf_api_init(self): + if self.jf_api is not None: + print("Warning: API already initialized, doing nothing") + return + + self.jf_api = JellyfinClient() + self.jf_api.config.app('xmpp-jellyfin-bot', '0.0.1', 'xmpp-jellyfin-bot', uuid.getnode()) + self.jf_api.config.data["auth.ssl"] = False + + def jf_api_login(self): + if self.jf_api_credentials is None: + self.jf_api.auth.connect_to_address(self.jf_api_url) + self.jf_api.auth.login(self.jf_api_url, self.jf_api_username, self.jf_api_password) + self.jf_api_credentials = self.jf_api.auth.credentials.get_credentials() + + else: + self.jf_api.authenticate({"Servers": [self.jf_api_credentials]}, discover=False) + + + + + async def session_start(self, event): + await self.get_roster() + self.send_presence() + self.plugin['xep_0045'].join_muc(self.room, self.nick) + avatar_file = "./bartonfink.png" + try: + avatar_file = open(avatar_file, 'rb') + except IOError: + logging.error("Could not find avatar file") + return self.disconnect() + + avatar = avatar_file.read() + avatar_type = 'image/png' + avatar_id = self['xep_0084'].generate_id(avatar) + avatar_bytes = len(avatar) + avatar_file.close() + + used_xep84 = False + + logging.info('Publish XEP-0084 avatar data') + result = await self['xep_0084'].publish_avatar(avatar) + if isinstance(result, slixmpp.exceptions.XMPPError): + logging.warning('Could not publish XEP-0084 avatar') + else: + used_xep84 = True + + logging.info('Update vCard with avatar') + result = await self['xep_0153'].set_avatar(avatar=avatar, mtype=avatar_type) + if isinstance(result, slixmpp.exceptions.XMPPError): + print('Could not set vCard avatar') + + if used_xep84: + logging.info('Advertise XEP-0084 avatar metadata') + result = await self['xep_0084'].publish_avatar_metadata([ + {'id': avatar_id, + 'type': avatar_type, + 'bytes': avatar_bytes} + # We could advertise multiple avatars to provide + # options in image type, source (HTTP vs pubsub), + # size, etc. + # {'id': ....} + ]) + if isinstance(result, slixmpp.exceptions.XMPPError): + logging.warning('Could not publish XEP-0084 metadata') + + logging.info('Wait for presence updates to propagate...') + #self.schedule('end', 5, self.disconnect, kwargs={'wait': True}) + + # Most get_*/set_* methods from plugins use Iq stanzas, which + # are sent asynchronously. You can almost always provide a + # callback that will be executed when the reply is received. + + def message(self, msg): + if msg['type'] in ('chat', 'normal'): + msg.reply("I was not designed to take direct messages, please use me in a MUC").send() + + def muc_message(self, msg): + # TODO + if msg['mucnick'] != self.nick and msg['body'].startswith(self.nick): + message = "```\n" + tokens = msg['body'].split() + match tokens[1]: + case "help": + message += "XMPP bot to query a Jellyfin server for content\n" + message += "Please use this bot first if you want to download something but are not sure if it's on the server\n" + message += "Commands\n" + message += "help: Displays this help\n" + message += "search CATEGORY SEARCH_QUERY: Search CATEGORY for SEARCH_QUERY on the Jellyfin server\n" + case "search": + category = tokens[2] + category = category.lower() + if category not in ["movie", "tv", "music"]: + message += "Error: invalid category " + tokens[2] + else: + search_query = " ".join(tokens[3:]) + query = self.jf_api.jellyfin.search_media_items(term=search_query, media=category) + items = query['Items'] + items = [i for i in items if i['MediaType'] != "Unknown"] + if len(items) == 0: + message += f"{search_query} not found in category {category}" + match category: + case "movie": + for i in items: + message += f"{i['Name']}, {i['ProductionYear']}, {i['OfficialRating'] if 'OfficialRating' in i else "unknown rating"}, {i['Container']}\n" + + message += "```" + + self.send_message(mto=msg['from'].bare, + mbody=message, + mtype='groupchat') + + return 0 + + +if __name__ == '__main__': + # Ideally use optparse or argparse to get JID, + # password, and log level. + + logging.basicConfig(level=logging.INFO, + format='%(levelname)-8s %(message)s') + + config = configparser.ConfigParser() + if not os.path.exists("./config.conf"): + logging.error("Could not find ./config.conf, please ensure it exists") + exit + + config.read('config.conf') + config_default = config['DEFAULT'] + xmpp = QBBot(config_default['jf_jid'].strip('\"'), + config_default['jf_pass'].strip('\"'), + config_default['jf_muc'].strip('\"'), + config_default['jf_nick'].strip('\"'), + config_default['api_url'].strip('\"'), + config_default['api_user'].strip('\"'), + config_default['api_pass'].strip('\"')) + + + xmpp.register_plugin('xep_0030') # Service Discovery + xmpp.register_plugin('xep_0045') # Multi-User Chat + xmpp.register_plugin('xep_0199') # XMPP Ping + xmpp.register_plugin('xep_0084') # vCard avatar + xmpp.register_plugin('xep_0153') # Something required for vCard + xmpp.connect() + xmpp.process() diff --git a/config.conf.template b/config.conf.template new file mode 100644 index 0000000..25f01a2 --- /dev/null +++ b/config.conf.template @@ -0,0 +1,8 @@ +[DEFAULT] +qb_jid = # JID for the bot +qb_pass = # Password for the bot +qb_muc = # MUC the bot should connect to +qb_nick = # Nickname for the bot in the MUC +api_url = # URL for the qbittorrent api we are connecting to +api_user = # Username for the qbittorrent api +api_pass = # Password for the qbittorent api \ No newline at end of file diff --git a/jellyfin_logo.png b/jellyfin_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c6372726bfd9800df2d07496d395295e48e372b8 GIT binary patch literal 25935 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