- Finsihed Jellyfin integration with auto-add and auto-remove - Integration toggle in config task: none
463 lines
20 KiB
Python
463 lines
20 KiB
Python
from pickle import FALSE
|
|
import app.bot.helper.jellyfinhelper as jelly
|
|
import discord
|
|
from discord.ext import commands
|
|
import asyncio
|
|
from plexapi.myplex import MyPlexAccount
|
|
from discord import Webhook, AsyncWebhookAdapter
|
|
import app.bot.helper.db as db
|
|
import app.bot.helper.plexhelper as plexhelper
|
|
import app.bot.helper.jellyfinhelper as jelly
|
|
import texttable
|
|
import os
|
|
from os import path
|
|
import configparser
|
|
CONFIG_PATH = 'app/config/config.ini'
|
|
BOT_SECTION = 'bot_envs'
|
|
|
|
# settings
|
|
plex_roles = None
|
|
PLEXUSER = ""
|
|
PLEXPASS = ""
|
|
PLEX_SERVER_NAME = ""
|
|
Plex_LIBS = None
|
|
|
|
plex_configured = True
|
|
jellyfin_configured = True
|
|
|
|
if(path.exists(CONFIG_PATH)):
|
|
config = configparser.ConfigParser()
|
|
config.read(CONFIG_PATH)
|
|
|
|
# Get Plex config
|
|
try:
|
|
PLEXUSER = config.get(BOT_SECTION, 'plex_user')
|
|
PLEXPASS = config.get(BOT_SECTION, 'plex_pass')
|
|
PLEX_SERVER_NAME = config.get(BOT_SECTION, 'plex_server_name')
|
|
except:
|
|
print("Could not load plex config")
|
|
plex_configured = False
|
|
|
|
# Get Plex roles config
|
|
try:
|
|
plex_roles = config.get(BOT_SECTION, 'plex_roles')
|
|
except:
|
|
print("Could not get Plex roles config")
|
|
plex_roles = None
|
|
if plex_roles is not None:
|
|
plex_roles = list(plex_roles.split(','))
|
|
else:
|
|
plex_roles = []
|
|
|
|
# Get Plex libs config
|
|
try:
|
|
Plex_LIBS = config.get(BOT_SECTION, 'plex_libs')
|
|
except:
|
|
print("Could not get Plex libs config. Defaulting to all libraries.")
|
|
Plex_LIBS = None
|
|
if Plex_LIBS is None:
|
|
Plex_LIBS = ["all"]
|
|
else:
|
|
Plex_LIBS = list(Plex_LIBS.split(','))
|
|
|
|
# Get Jellyfin config
|
|
try:
|
|
JELLYFIN_SERVER_URL = config.get(BOT_SECTION, 'jellyfin_server_url')
|
|
JELLYFIN_API_KEY = config.get(BOT_SECTION, "jellyfin_api_key")
|
|
except:
|
|
print("Could not load Jellyfin config")
|
|
jellyfin_configured = False
|
|
|
|
# Get Jellyfin roles config
|
|
try:
|
|
jellyfin_roles = config.get(BOT_SECTION, 'jellyfin_roles')
|
|
except:
|
|
print("Could not get Jellyfin roles config")
|
|
jellyfin_roles = None
|
|
if jellyfin_roles is not None:
|
|
jellyfin_roles = list(jellyfin_roles.split(','))
|
|
else:
|
|
jellyfin_roles = []
|
|
|
|
# Get Jellyfin libs config
|
|
try:
|
|
jellyfin_libs = config.get(BOT_SECTION, 'jellyfin_libs')
|
|
except:
|
|
print("Could not get Jellyfin libs config. Defaulting to all libraries.")
|
|
jellyfin_libs = None
|
|
if jellyfin_libs is None:
|
|
jellyfin_libs = ["all"]
|
|
else:
|
|
jellyfin_libs = list(jellyfin_libs.split(','))
|
|
|
|
# Get Enable config
|
|
try:
|
|
USE_JELLYFIN = config.get(BOT_SECTION, 'jellyfin_enabled')
|
|
USE_JELLYFIN = USE_JELLYFIN.lower() == "true"
|
|
except:
|
|
print("Could not get Jellyfin enable config. Defaulting to False")
|
|
USE_JELLYFIN = False
|
|
|
|
try:
|
|
USE_PLEX = config.get(BOT_SECTION, "plex_enabled")
|
|
USE_PLEX = USE_PLEX.lower() == "true"
|
|
except:
|
|
print("Could not get Plex enable config. Defaulting to False")
|
|
USE_PLEX = False
|
|
|
|
|
|
if USE_PLEX and plex_configured:
|
|
try:
|
|
account = MyPlexAccount(PLEXUSER, PLEXPASS)
|
|
plex = account.resource(PLEX_SERVER_NAME).connect() # returns a PlexServer instance
|
|
print('Logged into plex!')
|
|
except Exception as e:
|
|
print('Error with plex login. Please check username and password and Plex server name or setup plex in the bot.')
|
|
print(f'Error: {e}')
|
|
else:
|
|
print(f"Plex {'disabled' if not USE_PLEX else 'not configured'}. Skipping Plex login.")
|
|
|
|
|
|
class app(commands.Cog):
|
|
|
|
def __init__(self, bot):
|
|
self.bot = bot
|
|
|
|
@commands.Cog.listener()
|
|
async def on_ready(self):
|
|
print('Made by Sleepingpirate https://github.com/Sleepingpirates/')
|
|
print('Jellyfin implementation by Yoruio https://github.com/Yoruio/')
|
|
print(f'Logged in as {self.bot.user} (ID: {self.bot.user.id})')
|
|
print('------')
|
|
if plex_roles is None:
|
|
print('Configure Plex roles to enable auto invite to Plex after a role is assigned.')
|
|
|
|
async def embederror(self, author, message):
|
|
embed1 = discord.Embed(title="ERROR",description=message, color=0xf50000)
|
|
await author.send(embed=embed1)
|
|
|
|
async def embedinfo(self, author, message):
|
|
embed1 = discord.Embed(title=message, color=0x00F500)
|
|
await author.send(embed=embed1)
|
|
|
|
async def embedcustom(self, recipient, title, fields):
|
|
embed = discord.Embed(title=title)
|
|
for k in fields:
|
|
embed.add_field(name=str(k), value=str(fields[k]), inline=True)
|
|
await recipient.send(embed=embed)
|
|
|
|
async def getemail(self, after):
|
|
email = None
|
|
await self.embedinfo(after,'Welcome To '+ PLEX_SERVER_NAME +'. Just reply with your email so we can add you to Plex!')
|
|
await self.embedinfo(after,'I will wait 24 hours for your message, if you do not send it by then I will cancel the command.')
|
|
while(email == None):
|
|
def check(m):
|
|
return m.author == after and not m.guild
|
|
try:
|
|
email = await self.bot.wait_for('message', timeout=86400, check=check)
|
|
if(plexhelper.verifyemail(str(email.content))):
|
|
return str(email.content)
|
|
else:
|
|
email = None
|
|
message = "Invalid email. Please just type in your email and nothing else."
|
|
await self.embederror(after, message)
|
|
continue
|
|
except asyncio.TimeoutError:
|
|
message = "Timed Out. Message Server Admin with your email so They Can Add You Manually."
|
|
await self.embederror(after, message)
|
|
return None
|
|
|
|
async def getusername(self, after):
|
|
username = None
|
|
await self.embedinfo(after, f"Welcome To Jellyfin! Just reply with a username for Jellyfin so we can add you!")
|
|
await self.embedinfo(after, f"I will wait 24 hours for your message, if you do not send it by then I will cancel the command.")
|
|
while (username is None):
|
|
def check(m):
|
|
return m.author == after and not m.guild
|
|
try:
|
|
username = await self.bot.wait_for('message', timeout=86400, check=check)
|
|
if(jelly.verify_username(JELLYFIN_SERVER_URL, JELLYFIN_API_KEY, str(username.content))):
|
|
return str(username.content)
|
|
else:
|
|
username = None
|
|
message = "This username is already choosen. Please select another Username."
|
|
await self.embederror(after, message)
|
|
continue
|
|
except asyncio.TimeoutError:
|
|
message = "Timed Out. Message Server Admin with your preferred username so They Can Add You Manually."
|
|
await self.embederror(after, message)
|
|
return None
|
|
except Exception as e:
|
|
await self.embederror(after, "Something went wrong. Please try again with another username.")
|
|
print (e)
|
|
username = None
|
|
|
|
|
|
async def addtoplex(self, email, channel):
|
|
if(plexhelper.verifyemail(email)):
|
|
if plexhelper.plexadd(plex,email,Plex_LIBS):
|
|
await self.embedinfo(channel, 'This email address has been added to plex')
|
|
return True
|
|
else:
|
|
await self.embederror(channel, 'There was an error adding this email address. Check logs.')
|
|
return False
|
|
else:
|
|
await self.embederror(channel, 'Invalid email.')
|
|
return False
|
|
|
|
async def removefromplex(self, email, channel):
|
|
if(plexhelper.verifyemail(email)):
|
|
if plexhelper.plexremove(plex,email):
|
|
await self.embedinfo(channel, 'This email address has been removed from plex.')
|
|
return True
|
|
else:
|
|
await self.embederror(channel, 'There was an error removing this email address. Check logs.')
|
|
return False
|
|
else:
|
|
await self.embederror(channel, 'Invalid email.')
|
|
return False
|
|
|
|
async def addtojellyfin(self, username, password, channel):
|
|
if not jelly.verify_username(JELLYFIN_SERVER_URL, JELLYFIN_API_KEY, username):
|
|
await self.embederror(channel, f'An account with username {username} already exists.')
|
|
return
|
|
|
|
if jelly.add_user(JELLYFIN_SERVER_URL, JELLYFIN_API_KEY, username, password, jellyfin_libs):
|
|
await self.embedinfo(channel, 'User successfully added to Jellyfin')
|
|
return True
|
|
else:
|
|
await self.embederror(channel, 'There was an error adding this user to Jellyfin. Check logs for more info.')
|
|
return False
|
|
|
|
async def removefromjellyfin(self, username, channel):
|
|
if jelly.verify_username(JELLYFIN_SERVER_URL, JELLYFIN_API_KEY, username):
|
|
await self.embederror(channel, f'Could not find account with username {username}.')
|
|
return
|
|
|
|
if jelly.remove_user(JELLYFIN_SERVER_URL, JELLYFIN_API_KEY, username):
|
|
await self.embedinfo(channel, f'Successfully removed user {username} from Jellyfin.')
|
|
return True
|
|
else:
|
|
await self.embederror(channel, f'There was an error removing this user from Jellyfin. Check logs for more info.')
|
|
return False
|
|
|
|
@commands.Cog.listener()
|
|
async def on_member_update(self, before, after):
|
|
if plex_roles is None:
|
|
return
|
|
roles_in_guild = after.guild.roles
|
|
role = None
|
|
|
|
plex_processed = False
|
|
jellyfin_processed = False
|
|
|
|
# Check Plex roles
|
|
if plex_configured and USE_PLEX:
|
|
for role_for_app in plex_roles:
|
|
for role_in_guild in roles_in_guild:
|
|
if role_in_guild.name == role_for_app:
|
|
role = role_in_guild
|
|
|
|
# Plex role was added
|
|
if role is not None and (role in after.roles and role not in before.roles):
|
|
email = await self.getemail(after)
|
|
if email is not None:
|
|
await self.embedinfo(after, "Got it we will be adding your email to plex shortly!")
|
|
if plexhelper.plexadd(plex,email,Plex_LIBS):
|
|
db.save_user_email(str(after.id), email)
|
|
await asyncio.sleep(5)
|
|
await self.embedinfo(after, 'You have Been Added To Plex! Login to plex and accept the invite!')
|
|
else:
|
|
await self.embedinfo(after, 'There was an error adding this email address. Message Server Admin.')
|
|
plex_processed = True
|
|
break
|
|
|
|
# Plex role was removed
|
|
elif role is not None and (role not in after.roles and role in before.roles):
|
|
try:
|
|
user_id = after.id
|
|
email = db.get_useremail(user_id)
|
|
plexhelper.plexremove(plex,email)
|
|
deleted = db.remove_email(user_id)
|
|
if deleted:
|
|
print("Removed Plex email {} from db".format(after.name))
|
|
#await secure.send(plexname + ' ' + after.mention + ' was removed from plex')
|
|
else:
|
|
print("Cannot remove Plex from this user.")
|
|
await self.embedinfo(after, "You have been removed from Plex")
|
|
except Exception as e:
|
|
print(e)
|
|
print("{} Cannot remove this user from plex.".format(email))
|
|
plex_processed = True
|
|
break
|
|
if plex_processed:
|
|
break
|
|
|
|
# Check Jellyfin roles
|
|
if jellyfin_configured and USE_JELLYFIN:
|
|
for role_for_app in jellyfin_roles:
|
|
for role_in_guild in roles_in_guild:
|
|
if role_in_guild.name == role_for_app:
|
|
role = role_in_guild
|
|
|
|
# Jellyfin role was added
|
|
if role is not None and (role in after.roles and role not in before.roles):
|
|
username = await self.getusername(after)
|
|
if username is not None:
|
|
await self.embedinfo(after, "Got it we will be creating your Jellyfin account shortly!")
|
|
password = jelly.generate_password(16)
|
|
if jelly.add_user(JELLYFIN_SERVER_URL, JELLYFIN_API_KEY, username, password, jellyfin_libs):
|
|
db.save_user_jellyfin(str(after.id), username)
|
|
await asyncio.sleep(5)
|
|
await self.embedcustom(after, "You have been added to Jellyfin!", {'Username': username, 'Password': f"||{password}||"})
|
|
await self.embedinfo(after, f"Go to {JELLYFIN_SERVER_URL} to log in!")
|
|
else:
|
|
await self.embedinfo(after, 'There was an error adding this user to Jellyfin. Message Server Admin.')
|
|
jellyfin_processed = True
|
|
break
|
|
|
|
# Jellyfin role was removed
|
|
elif role is not None and (role not in after.roles and role in before.roles):
|
|
try:
|
|
user_id = after.id
|
|
username = db.get_jellyfin_username(user_id)
|
|
jelly.remove_user(JELLYFIN_SERVER_URL, JELLYFIN_API_KEY, username)
|
|
deleted = db.remove_jellyfin(user_id)
|
|
if deleted:
|
|
print("Removed Jellyfin from {}".format(after.name))
|
|
#await secure.send(plexname + ' ' + after.mention + ' was removed from plex')
|
|
else:
|
|
print("Cannot remove Jellyfin from this user")
|
|
await self.embedinfo(after, "You have been removed from Jellyfin")
|
|
except Exception as e:
|
|
print(e)
|
|
print("{} Cannot remove this user from Jellyfin.".format(username))
|
|
jellyfin_processed = True
|
|
break
|
|
if jellyfin_processed:
|
|
break
|
|
|
|
@commands.Cog.listener()
|
|
async def on_member_remove(self, member):
|
|
email = db.get_useremail(member.id)
|
|
plexhelper.plexremove(plex,email)
|
|
deleted = db.delete_user(member.id)
|
|
if deleted:
|
|
print("Removed {} from db because user left discord server.".format(email))
|
|
|
|
@commands.has_permissions(administrator=True)
|
|
@commands.command(aliases=['plexadd'])
|
|
async def plexinvite(self, ctx, email):
|
|
await self.addtoplex(email, ctx.channel)
|
|
|
|
@commands.has_permissions(administrator=True)
|
|
@commands.command(aliases=['plexrm'])
|
|
async def plexremove(self, ctx, email):
|
|
await self.removefromplex(email, ctx.channel)
|
|
|
|
@commands.has_permissions(administrator=True)
|
|
@commands.command(aliases=['jellyadd'])
|
|
async def jellyfininvite(self, ctx, username):
|
|
password = jelly.generate_password(16)
|
|
if await self.addtojellyfin(username, password, ctx.channel):
|
|
await self.embedcustom(ctx.author, "Jellyfin user created!", {'Username': username, 'Password': f"||{password}||"})
|
|
|
|
@commands.has_permissions(administrator=True)
|
|
@commands.command(aliases=['jellyrm'])
|
|
async def jellyfinremove(self, ctx, username):
|
|
await self.removefromjellyfin(username, ctx.channel)
|
|
|
|
@commands.has_permissions(administrator=True)
|
|
@commands.command()
|
|
async def dbadd(self, ctx, member: discord.Member, email, jellyfin_username):
|
|
email = email.strip()
|
|
jellyfin_username = jellyfin_username.strip()
|
|
await self.embedinfo(ctx.channel, f"username: {member.name} email: {email} jellyfin: {jellyfin_username}")
|
|
#await self.addtoplex(email, ctx.channel)
|
|
|
|
# Check email if provided
|
|
if email and not plexhelper.verifyemail(email):
|
|
await self.embederror(ctx.channel, "Invalid email.")
|
|
return
|
|
|
|
try:
|
|
db.save_user_all(str(member.id), email, jellyfin_username)
|
|
await self.embedinfo(ctx.channel,'User was added to the database.')
|
|
except Exception as e:
|
|
await self.embedinfo(ctx.channel, 'There was an error adding this user to database.')
|
|
print(e)
|
|
|
|
@commands.has_permissions(administrator=True)
|
|
@commands.command()
|
|
async def dbls(self, ctx):
|
|
|
|
embed = discord.Embed(title='Invitarr Database.')
|
|
all = db.read_useremail()
|
|
table = texttable.Texttable()
|
|
table.set_cols_dtype(["t", "t", "t", "t"])
|
|
table.set_cols_align(["c", "c", "c", "c"])
|
|
header = ("#", "Name", "Email", "Jellyfin")
|
|
table.add_row(header)
|
|
print(all)
|
|
for index, peoples in enumerate(all):
|
|
index = index + 1
|
|
id = int(peoples[1])
|
|
dbuser = self.bot.get_user(id)
|
|
dbemail = peoples[2] if peoples[2] else "No Plex"
|
|
dbjellyfin = peoples[3] if peoples[3] else "No Jellyfin"
|
|
try:
|
|
username = dbuser.name
|
|
except:
|
|
username = "User Not Found."
|
|
embed.add_field(name=f"**{index}. {username}**", value=dbemail+'\n'+dbjellyfin+'\n', inline=False)
|
|
table.add_row((index, username, dbemail, dbjellyfin))
|
|
|
|
total = str(len(all))
|
|
if(len(all)>25):
|
|
f = open("db.txt", "w")
|
|
f.write(table.draw())
|
|
f.close()
|
|
await ctx.channel.send("Database too large! Total: {total}".format(total = total),file=discord.File('db.txt'))
|
|
else:
|
|
await ctx.channel.send(embed = embed)
|
|
|
|
|
|
@commands.has_permissions(administrator=True)
|
|
@commands.command()
|
|
async def dbrm(self, ctx, position):
|
|
embed = discord.Embed(title='Invitarr Database.')
|
|
all = db.read_useremail()
|
|
table = texttable.Texttable()
|
|
table.set_cols_dtype(["t", "t", "t", "t"])
|
|
table.set_cols_align(["c", "c", "c", "c"])
|
|
header = ("#", "Name", "Email", "Jellyfin")
|
|
table.add_row(header)
|
|
for index, peoples in enumerate(all):
|
|
index = index + 1
|
|
id = int(peoples[1])
|
|
dbuser = self.bot.get_user(id)
|
|
dbemail = peoples[2] if peoples[2] else "No Plex"
|
|
dbjellyfin = peoples[3] if peoples[3] else "No Jellyfin"
|
|
try:
|
|
username = dbuser.name
|
|
except:
|
|
username = "User Not Found."
|
|
embed.add_field(name=f"**{index}. {username}**", value=dbemail+'\n'+dbjellyfin+'\n', inline=False)
|
|
table.add_row((index, username, dbemail, dbjellyfin))
|
|
|
|
try:
|
|
position = int(position) - 1
|
|
id = all[position][1]
|
|
discord_user = await self.bot.fetch_user(id)
|
|
username = discord_user.name
|
|
deleted = db.delete_user(id)
|
|
if deleted:
|
|
print("Removed {} from db".format(username))
|
|
await self.embedinfo(ctx.channel,"Removed {} from db".format(username))
|
|
else:
|
|
await self.embederror(ctx.channel,"Cannot remove this user from db.")
|
|
except Exception as e:
|
|
print(e)
|
|
|
|
def setup(bot):
|
|
bot.add_cog(app(bot)) |