noket 4 Posted November 4, 2023 Share Posted November 4, 2023 (edited) Hello! Thanks to @Lukeand @hthgihwaymonkfor helping me troubleshoot some API difficulties in another thread (sessions are tough yo). In short, this code enables the following workflow: A user can favorite a trailer and get the movie added to the server without intervention by an admin. How it works: A user favorites a movie (requires the Trailers plugin), which triggers a webhook. The webhook calls on a localhost flask server. The flask server does some API calls to add the movie to Radarr and search for it. Emby pushes a popup notification to the user's client confirming whether it worked, or whether the movie is already being monitored (or couldn't be found). System/Software Requirements: Python, PIP (arrapi, flask). Works under the assumption that Radarr and Emby are running on the same host. Setting Requirements: Within Emby, Passwords must be disabled for users on localhost. There's probably a way to get around this using the admin api key, but I'm not going to fuss with it. Monk was able to get it working with the server api key, as seen here if you want to mess with it. Also, you also have to point a webhook to the flask server at URL http://127.0.0.1:5443/webhook. Make sure the "Add to favorites" option is checked. Need to have the Trailers plugin installed on Emby Limitations: It sends push notifications by plaintext username, instead of UserID. People with the same name are going to get random notifications. Again, I could probably fuss to fix this, but I only have 4 users and they don't have the same name. Installation: Drop the below code into a python file (your_file_name_here.py) and save it. Modify the emby_api_key, radarr_api_key, emby_base_url, and radarr_url values as appropriate. Running it: screen -dmS flask screen -r flask python3 your_file_name_here.py from flask import Flask, request from arrapi import RadarrAPI,exceptions import json import requests #https://pypi.org/project/requests/ import time from datetime import datetime, timezone from dateutil.parser import parse as timeparse emby_api_key = "emby api key" radarr_api_key = "radarr api key" static_dict_x_emby_token = {"X-Emby-Token":emby_api_key} emby_base_url = "http://127.0.0.1:EMBY_PORT/emby/" radarr_url = "http://127.0.0.1:RADARR_PORT/radarr" app = Flask(__name__) @app.route('/', methods=['POST']) def index(): return '<h1>Flask Receiver App is Up!</h1>',200 @app.route('/webhook', methods=['POST']) def webhook(): if request.method == 'POST': form_data = request.form["data"] data = json.loads(form_data) #get the type of item that was favorited, and the user who did it favorite_type = data['Item']['Type'] user_name = data['User']['Name'] #only handle trailers if favorite_type == "Trailer": radarr = RadarrAPI(url=radarr_url,apikey=radarr_api_key) root_folder_path = None for folder in radarr.root_folder(): root_folder_path = folder quality_profile_custom = None for profile in radarr.quality_profile(): quality_profile_custom = profile #find the url for tmdb external_urls = data['Item']['ExternalUrls'] movie_tmdb_id = "" for url in external_urls: if url['Name'] == "TheMovieDb": #extract the ID from the url movie_tmdb_id = url["Url"][url["Url"].index("movie/")+6:] #get the movie movie = radarr.get_movie(tmdb_id=int(movie_tmdb_id)) #sometimes the radarr api call fails, loop until it succeeds continue_loop = True while continue_loop == True: try: #best case scenario, works on first try. notifies user in emby. time.sleep(0.5) movie.add(root_folder=root_folder_path,quality_profile=quality_profile_custom,minimum_availability="announced") push_message(username=user_name,header="Emby Movie Download Service",message="Success! "+movie.title+" was added and, if available, will be downloaded soon!") continue_loop = False except exceptions.Exists: #movie is already monitored in radarr print("The movie already exists in Radarr - "+movie.folder) push_message(username=user_name,header="Emby Movie Download Service",message=movie.title+" is already being watched in the database. Once it's available, it'll be downloaded!") continue_loop = False except exceptions.Invalid: #couldn't find the tmdb print("The TMDB id was invalid or couldn't be found - "+movie_tmdb_id) push_message(username=user_name,header="Emby Movie Download Service",message="We couldn't find that movie with TMDB ID "+movie_tmdb_id+". Sorry!") continue_loop = False except exceptions.ArrException as e: #unknown exception, retry print("Exception encountered (retrying) - "+str(e)) finally: #suffer None return 'Webhook notification received', 202 else: return 'POST Method not supported', 405 """Pushes a message for all sessions for a single user, where the session was active within the last 5 seconds. This method expects a header for the popup, the message for the popup, and an optional delay. If no delay is given, the message is persistent. """ def push_message(username:str,header:str,message:str,delay_secs:int=-1): predata = {"Pw":""} user_sessions = [] #get all session sessions = requests.get( url=emby_base_url+"Sessions", headers=static_dict_x_emby_token ).json() #find any sessions for the user that were active within the last 5 seconds. Store the sessions in user_sessions for var in sessions: if var.get("UserName") is not None and var.get("UserId") is not None: if username == var.get("UserName"): activity_time = timeparse(timestr=var["LastActivityDate"],yearfirst=True) current_time = datetime.now(timezone.utc) time_difference = current_time-activity_time if time_difference.seconds < 5: user_sessions.append(var) #iterate through user_sessions and push the message to each session for session in user_sessions: user_authentication = requests.post( url=emby_base_url+"Users/"+session["UserId"]+"/Authenticate", headers=static_dict_x_emby_token, data=predata ).json() #provide the user's access token message_header = {"X-Emby-Token":user_authentication["AccessToken"]} message_params = {"Id":session["Id"],"Text":message,"Header":header,"TimeoutMs":delay_secs*1000} if message_params["TimeoutMs"] == -1000: del message_params["TimeoutMs"] requests.post( url=emby_base_url+"Sessions/"+session["Id"]+"/Message", headers=message_header, params=message_params ) app.run(host='127.0.0.1', port=5443, debug=False) Edited November 4, 2023 by noket missed a thing again 2 Link to comment Share on other sites More sharing options...
Luke 37094 Posted November 4, 2023 Share Posted November 4, 2023 Thanks for sharing. 2 Link to comment Share on other sites More sharing options...
gihayes 34 Posted November 4, 2023 Share Posted November 4, 2023 I use Ombi, but this is cool. No need to exit the Emby to request stuff. 1 Link to comment Share on other sites More sharing options...
softworkz 3338 Posted November 4, 2023 Share Posted November 4, 2023 2 hours ago, gihayes said: I use Ombi, but this is cool. No need to exit the Emby to request stuff. Doesn't Ombi provide the same feature? (liking to request an item) Link to comment Share on other sites More sharing options...
noket 4 Posted November 4, 2023 Author Share Posted November 4, 2023 Maybe Didn't know about Ombi. Seems like cool software, probably a bit overkill for my use case - I just wanted to add movies when someone hits favorite. 1 Link to comment Share on other sites More sharing options...
softworkz 3338 Posted November 4, 2023 Share Posted November 4, 2023 50 minutes ago, noket said: Maybe Didn't know about Ombi. Seems like cool software, probably a bit overkill for my use case - I just wanted to add movies when someone hits favorite. Yes, Ombi is a kind of swiss-army-knife in this area. Thanks a lot for sharing your solution! 1 Link to comment Share on other sites More sharing options...
gihayes 34 Posted November 4, 2023 Share Posted November 4, 2023 1 hour ago, softworkz said: Doesn't Ombi provide the same feature? (liking to request an item) You can't request from within Emby. You have to go to Ombi to request. You can link to Emby from Ombi tho. I put the link to Ombi on my Emby login page. I like Ombi cause it can handle any Movie, TV, or Music request and also notifies the user when the request has been added to Emby. Link to comment Share on other sites More sharing options...
softworkz 3338 Posted November 4, 2023 Share Posted November 4, 2023 I could swear there was some integration with Emby where you could see available items in Emby and request them by hitting "Like" button. But maybe it was an add-on to Ombi. Link to comment Share on other sites More sharing options...
TeamB 2353 Posted November 4, 2023 Share Posted November 4, 2023 the liking the trailer to get the movie is a very smart way to do this, good work. you should look at turning this into a plugin. you may not be able to add it to the official emby plugin catalogue due to reasons, but if you create a plugin people will be able to drop it in the plugin dir to use it. good work. 1 1 Link to comment Share on other sites More sharing options...
bakes82 90 Posted November 6, 2023 Share Posted November 6, 2023 Overseer/Ombi would be better than direct Sonarr/Radarr integration as you could limit the number of requests and a user could track their own requests if you associate the request to a user in overseer/ombi, plus what if you run multi ARR for 4k/1080p etc Plus its only one api instead of 2. 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now