Tolerant 70 Posted January 27 Share Posted January 27 (edited) import os import discord from discord.ext import tasks, commands import requests from io import BytesIO # Discord bot token and Emby server details discord_bot_token = os.getenv('NOWPLAYING_DISCORD_BOT_TOKEN') emby_server_ip = '192.168.4.101' emby_server_port = '8096' api_key = os.getenv('EMBY_API_BOT_KEY') channel_id = 1234567890 # The channel ID where the bot will post # Initialize Discord bot with intents intents = discord.Intents.default() intents.messages = True intents.guilds = True intents.members = True intents.message_content = True # Necessary for reading message content intents.reactions = True # If you want to track reactions intents.emojis_and_stickers = False # If you want to track emojis and stickers intents.integrations = True # If you want to track integrations intents.webhooks = True # If you want to track webhooks intents.invites = False # If you want to track invites intents.voice_states = False # If you want to track voice state changes intents.presences = True # If you want to track user presences (e.g., online status) intents.typing = False # Typically not needed, can be spammy bot = commands.Bot(command_prefix='/', intents=intents) # Variables to keep track of the last item played last_item_id = None @bot.event async def on_ready(): global last_item_id print(f'{bot.user.name} has connected to Discord!') channel = bot.get_channel(channel_id) existing_threads = channel.threads thread = discord.utils.get(existing_threads, name="Now Playing Updates") if thread is None: thread = await channel.create_thread(name="Now Playing Updates", type=discord.ChannelType.private_thread) # Fetch the last message in the thread messages = await thread.history(limit=1).flatten() bot.last_now_playing_message = messages[0] if messages else None bot.now_playing_thread = thread now_playing_check.start() @tasks.loop(seconds=30) async def now_playing_check(): global last_item_id url = f'http://{emby_server_ip}:{emby_server_port}/Sessions' headers = {'X-Emby-Token': api_key} response = requests.get(url, headers=headers) if response.status_code == 200: now_playing_data = response.json() for session in now_playing_data: if 'NowPlayingItem' in session: item = session['NowPlayingItem'] item_id = item.get('Id') media_type = item.get('Type') title = item.get('Name') if item_id and item_id != last_item_id: last_item_id = item_id if media_type == 'Episode': embed, file = await handle_episode(bot, item, emby_server_ip, emby_server_port, api_key) elif media_type == 'Movie': embed, file = await handle_movie(bot, item, emby_server_ip, emby_server_port, api_key, item_id) else: embed, file = None, None if embed and file: # Delete the previous message if it exists if bot.last_now_playing_message: await bot.last_now_playing_message.delete() # Send a new message bot.last_now_playing_message = await bot.now_playing_thread.send(embed=embed, file=file) break else: if response.status_code == 404: print("Now Playing information not found: HTTP 404 - The requested data was not found.") else: print(f"Failed to retrieve 'Now Playing' information from Emby. Status Code: {response.status_code}") async def handle_episode(bot, item, emby_server_ip, emby_server_port, api_key): series_title = item.get('SeriesName', 'Unknown Series') title = item.get('Name') episode_number = item.get('IndexNumber', 'Unknown Episode') season_number = item.get('ParentIndexNumber', None) # Retrieve the season number if available item_id = item.get('Id') # Retrieve the item_id image_url = f'http://{emby_server_ip}:{emby_server_port}/emby/Items/{item_id}/Images/Primary?api_key={api_key}' image_response = requests.get(image_url) if image_response.status_code == 200: image_data = BytesIO(image_response.content) image_data.seek(0) file = discord.File(fp=image_data, filename='now_playing_image.jpg') embed_title = f"{series_title}\n(S{season_number:02d}E{episode_number:02d}) {title}" embed = discord.Embed(title=embed_title, color=discord.Color.blue()) # Fetch and include episode overview if available overview = item.get('Overview', 'No overview available') embed.add_field(name="Overview", value=overview, inline=False) embed.set_image(url="attachment://now_playing_image.jpg") if bot.last_now_playing_message: await bot.last_now_playing_message.edit(embed=embed, file=file) else: bot.last_now_playing_message = await bot.now_playing_thread.send(embed=embed, file=file) else: if image_response.status_code == 404: print("Image not found: HTTP 404 - The requested image was not found.") else: print(f"Failed to download image from {image_url}. Status Code: {image_response.status_code}") return None, None async def handle_movie(bot, item, emby_server_ip, emby_server_port, api_key, item_id): title = item.get('Name') year = item.get('ProductionYear', 'Unknown Year') size_bytes = item.get('Size', 0) size_gb = round(size_bytes / (1024 ** 3), 2) genres = ', '.join(item.get('Genres', ['Unknown Genre'])) overview = item.get('Overview', 'No overview available') # Construct the image URL with the item_id image_url = f'http://{emby_server_ip}:{emby_server_port}/emby/Items/{item_id}/Images/Primary?api_key={api_key}' image_response = requests.get(image_url) if image_response.status_code == 200: image_data = BytesIO(image_response.content) image_data.seek(0) file = discord.File(fp=image_data, filename='now_playing_image.jpg') embed = discord.Embed(title=f"{title} ({year})", description=f"**Size:** {size_gb} GB\n**Genres:** {genres}\n**Overview:** {overview}") embed.set_image(url="attachment://now_playing_image.jpg") return embed, file else: if image_response.status_code == 404: print("Image not found: HTTP 404 - The requested image was not found.") else: print(f"Failed to download image from {image_url}. Status Code: {image_response.status_code}") return None, None bot.run(discord_bot_token) Edited January 27 by Tolerant Script updated Link to comment Share on other sites More sharing options...
Tolerant 70 Posted January 27 Author Share Posted January 27 What is the call I need to get back all the associated details about what shows up with nowplaying? I can't get GPT to figure it out cause there is no easy source of examples to draw from and just endless pages of API docs, too much to have it make sense of without telling me to give it what I want it to find. Ugg! I want to be able to see what's playing and show the image and also only show it for specific libraries. Help. Link to comment Share on other sites More sharing options...
Luke 37099 Posted January 27 Share Posted January 27 Hi, have you explored our api docs? https://dev.emby.media/ Link to comment Share on other sites More sharing options...
Tolerant 70 Posted January 27 Author Share Posted January 27 (edited) Yes I have tried in vain to make sense of it but it just does not compute.. I just need to know if I get a file id from now playing.. which I can do.. how to send that back to get the rest of the info for that file? For example.. I can get this from the "response" and the tags returned and the basics I can figure out. BUT.. I cannot for the life of me query with a file id and get back more associated data that I want. Or figure out how to give enough of it to GPT for it to figure it out. I do now have it mostly working except I can't really go beyond what I have shown and I would rather see the actual Series poster not a episode main image. Edited January 27 by Tolerant Link to comment Share on other sites More sharing options...
Tolerant 70 Posted January 28 Author Share Posted January 28 Since I can't seem to find any help to do it right I was able to work around it and use the path to the item to locally get the folder.jpg for the item, not the way I wanted to do it but it works, I guess. I would still love to know how to do this correctly. Link to comment Share on other sites More sharing options...
adminExitium 173 Posted January 28 Share Posted January 28 If the Type is Episode in the returned response, then use the SeriesId field and if it's Movie, use the Id field. The API path for fetching the primary image is /emby/Items/<ID>/Images/Primary. 1 Link to comment Share on other sites More sharing options...
Tolerant 70 Posted January 28 Author Share Posted January 28 Atm GPT is struggling with audio Requesting audio information from: http://192.168.4.101:8096/Items/19192 I really wish you guys just had something explaining this instead of just a list of parameters in the API cause it is really useless if someone does not understand how to put them together, and you don't show that. Link to comment Share on other sites More sharing options...
Luke 37099 Posted January 28 Share Posted January 28 Have you taken a look at the built-in swagger docs? Link to comment Share on other sites More sharing options...
Tolerant 70 Posted January 29 Author Share Posted January 29 ROFL.. Yes?! A bunch of non connected stuff.. that just gives you slash stuff.. and no examples anywhere.. that make any freaking sense. I have even figured out the local API call to see the server info etc.. but the docs are such a mess Even GPT cannot make heads or tails of this stuff and I am ready to scream. Can you PLEASE JUST GIVE ME SOME EXAMPLES OF WORKING CALLS I CAN MODIFY?!?!? FOR EXAMPLE IF I AM LISTENING TO A SONG .. AND WANT TO SEE THE DETAILS IN DISCORD?!?! OR .. MOVIE.. or MUSICVIDEO.. or EPISODE.. See where i am going with this?!?! IT's freaking impossible and all you seem to tell people is you have API docs.. but no one ever seems to help and give an example of how to use them or figure them out?!?! Link to comment Share on other sites More sharing options...
Tolerant 70 Posted January 29 Author Share Posted January 29 Loving it. Link to comment Share on other sites More sharing options...
Luke 37099 Posted January 29 Share Posted January 29 45 minutes ago, Tolerant said: Loving it. Try using swagger when you have the web app running on either localhost or https. Link to comment Share on other sites More sharing options...
Tolerant 70 Posted January 29 Author Share Posted January 29 1 hour ago, Luke said: Try using swagger when you have the web app running on either localhost or https. Can you please just answer some basic questions to get me started?!? SOME examples would REALLY be nice. Link to comment Share on other sites More sharing options...
Tolerant 70 Posted January 29 Author Share Posted January 29 I HAVE been to the WEB Docs, I have seen the few examples, the "CLIENT" page which links to a setup.py that does NOT exist.. and someones project I found on github for a script to put stuff into CSV and some other py project that does not work.. I just want to post whats playing with the right info to discord via a bot.. that seems like SUCH an easy thing, but I cannot find ANY working examples on the entire internet. I paid for lifetime so I was hoping MAYBE you would share a few tips to help but all you keep saying is "read docs" and I have told you I don't understand them. Maybe it's cause I am disabled or old or dumb, I don't know but I don't get it and i can't figure this out without help so I am here ASKING FOR HELP. Link to comment Share on other sites More sharing options...
adminExitium 173 Posted January 29 Share Posted January 29 7 hours ago, Tolerant said: http://192.168.4.101:8096/Items/19192 Try http://192.168.4.101:8096/Items?Ids=19192 instead. This should give you most of the necessary info but if you still need more you need to fetch it in the context of a user like (after authenticating as the same user): http://192.168.4.101:8096/Users/<UserId>/Items/19192 Link to comment Share on other sites More sharing options...
Tolerant 70 Posted January 29 Author Share Posted January 29 (edited) This is by NO means 100% or how I would choose to do it exactly, BUT until someone takes an interest other than me it works for me. There are a couple things that would need to be changed such as the local network path to music images for example, and setting the OS ENV for keys etc. BUT anyone is welcome to improve or use it if they desire. I hope someone finds it at least helpful from an example standpoint of how to get started. Discord NOW Playing BOT, posting to a thread in a "newmovies" channel. Adjust or edit as needed. Enjoy. NOWPLAYING Discord Bot NOWPLAYING is a Discord bot designed to display real-time now playing information from an Emby server in a designated Discord channel. It allows users to see the details of the media currently being played on the Emby server, enhancing the community's media sharing and viewing experience. Features Real-time updates of media playback from Emby server. Displays detailed information including titles, artists, albums, and images. Supports various media types including movies, episodes, audio, and music videos. Configurable to monitor specific user activities and ignore others. Automated messages for "Nothing Playing" scenarios. https://github.com/Tolerable/NOWPLAYING Edited January 29 by Tolerant 1 Link to comment Share on other sites More sharing options...
Tolerant 70 Posted January 29 Author Share Posted January 29 Still needs more work, but It seems good enough for Episodes, Movies, Music and MusicVideos. I have not made sure it will never have an error or work with every single condition as I only put a couple days into telling GPT to keep fixing errors and change things, but eventually I got this far. Anyone is encouraged to branch it or suggest edits etc. 1 Link to comment Share on other sites More sharing options...
Tolerant 70 Posted January 30 Author Share Posted January 30 Ok.. NOW it updates the BOT's STATUS message to show the now playing item, such as Artist - Title (Year), and the Images for Audio And Music Videos are also served along with their info. So now it handles Episodes, Movies, Music, MusicVideos, so far. Not perfect, expect some bugs, but.. it's something! 1 Link to comment Share on other sites More sharing options...
Luke 37099 Posted February 1 Share Posted February 1 Very cool. Thanks for sharing. Link to comment Share on other sites More sharing options...
Tolerant 70 Posted February 2 Author Share Posted February 2 (edited) Made some updates, it is still a bit rough but closer to what I had envisioned now. Edited February 2 by Tolerant 1 Link to comment Share on other sites More sharing options...
Tolerant 70 Posted February 2 Author Share Posted February 2 Darn it hate not being able to edit posts here later, lol. Still a work in progress. Obviously the look is set by the selections in Emby itself and there is no other good square selection for audio in this plugin, sadly. But I did manage to improve the layout some more and added the year as well. The script is not exactly plug and play yet, but getting closer bit by bit. Link to comment Share on other sites More sharing options...
bakes82 90 Posted February 3 Share Posted February 3 Does this seriously poll the sessions every 30 seconds and then deletes messages from discord and re-adds them lol? Why not use a webhook for the events and then get the “minor” details you’re missing.. I also thought there was already a discord plugin that did this also. Link to comment Share on other sites More sharing options...
Tolerant 70 Posted February 3 Author Share Posted February 3 (edited) It does keep checking yes. And there may be another way out there, I just know I wanted a way to do it and did not find enough information. No one has to use it! It's for my own fun and learning, but I felt I should share because Emby gives me so much back. Maybe I will find a better way to do it, but.. it works and Discord does not charge by the message or tokens, yet. Btw, I have no idea how to code. GPT writes my scripts and I just keep working at it until we get it right. So I am sure this is a horrible script. I would suggest someone really smart rework it and branch the project with a MUCH better version. WINK WINK! HAHA! Edited February 3 by Tolerant 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