Files
Membarr/app/bot/cogs/app.py

480 lines
25 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from pickle import FALSE
import app.bot.helper.jellyfinhelper as jelly
from app.bot.helper.textformat import bcolors
import discord
from discord.ext import commands
from discord import app_commands
import asyncio
from plexapi.myplex import MyPlexAccount
from plexapi.server import PlexServer
import app.bot.helper.db as db
import app.bot.helper.plexhelper as plexhelper
import app.bot.helper.jellyfinhelper as jelly
import texttable
from app.bot.helper.message import *
from app.bot.helper.confighelper import *
CONFIG_PATH = 'app/config/config.ini'
BOT_SECTION = 'bot_envs'
plex_configured = True
jellyfin_configured = True
config = configparser.ConfigParser()
config.read(CONFIG_PATH)
plex_token_configured = True
try:
PLEX_TOKEN = config.get(BOT_SECTION, 'plex_token')
PLEX_BASE_URL = config.get(BOT_SECTION, 'plex_base_url')
except:
print("Сведения о токене аутентификации Plex не найдены.")
plex_token_configured = False
# 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("Информация для входа в Plex не найдена")
if not plex_token_configured:
print("Не удалось загрузить конфигурацию plex")
plex_configured = False
# Get Plex roles config
try:
plex_roles = config.get(BOT_SECTION, 'plex_roles')
except:
plex_roles = None
if plex_roles:
plex_roles = list(plex_roles.split(','))
else:
plex_roles = []
# Get Plex libs config
try:
Plex_LIBS = config.get(BOT_SECTION, 'plex_libs')
except:
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:
jellyfin_configured = False
# Get Jellyfin roles config
try:
jellyfin_roles = config.get(BOT_SECTION, 'jellyfin_roles')
except:
jellyfin_roles = None
if jellyfin_roles:
jellyfin_roles = list(jellyfin_roles.split(','))
else:
jellyfin_roles = []
# Get Jellyfin libs config
try:
jellyfin_libs = config.get(BOT_SECTION, 'jellyfin_libs')
except:
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:
USE_JELLYFIN = False
try:
USE_PLEX = config.get(BOT_SECTION, "plex_enabled")
USE_PLEX = USE_PLEX.lower() == "true"
except:
USE_PLEX = False
try:
JELLYFIN_EXTERNAL_URL = config.get(BOT_SECTION, "jellyfin_external_url")
if not JELLYFIN_EXTERNAL_URL:
JELLYFIN_EXTERNAL_URL = JELLYFIN_SERVER_URL
except:
JELLYFIN_EXTERNAL_URL = JELLYFIN_SERVER_URL
print("Не удалось получить внешний URL-адрес Jellyfin. По умолчанию используется URL-адрес сервера.")
try:
DISCORD_SERVER_PERM = config.get(BOT_SECTION, "discord_perm")
except:
DISCORD_SERVER_PERM = None
print("Не удалось получить id роли для управления ботом. Возможна любая дичь.")
if USE_PLEX and plex_configured:
try:
print("Подключение к Plex......")
if plex_token_configured and PLEX_TOKEN and PLEX_BASE_URL:
print("Использование токена аутентификации Plex")
plex = PlexServer(PLEX_BASE_URL, PLEX_TOKEN)
else:
print("Использование данных для входа в Plex")
account = MyPlexAccount(PLEXUSER, PLEXPASS)
plex = account.resource(PLEX_SERVER_NAME).connect() # returns a PlexServer instance
print('Зашёл в Plex!')
except Exception as e:
# probably rate limited.
print('Ошибка при входе в plex. Пожалуйста, проверьте данные аутентификации Plex. Если вы в последнее время перезапускали бота несколько раз, скорее всего, это связано с ограничением скорости в Plex API. Повторите попытку через 10 минут.')
print(f'Error: {e}')
else:
print(f"Plex {'выключен' if not USE_PLEX else 'не настроен'}. Пропуск входа в Plex.")
class app(commands.Cog):
# App command groups
plex_commands = app_commands.Group(name="plex", description="Команды Membarr Plex")
jellyfin_commands = app_commands.Group(name="jellyfin", description="Команды Membarr Jellyfin")
membarr_commands = app_commands.Group(name="membarr", description="Membarr общие команды")
def __init__(self, bot):
self.bot = bot
@commands.Cog.listener()
async def on_ready(self):
print('------')
print("{:^41}".format(f"MEMBARR V {MEMBARR_VERSION}"))
print(f'Made by Yoruio https://github.com/Yoruio/\n')
print(f'Forked from Invitarr https://github.com/Sleepingpirates/Invitarr')
print(f'Named by lordfransie')
print(f'Logged in as {self.bot.user} (ID: {self.bot.user.id})')
print('------')
# TODO: Make these debug statements work. roles are currently empty arrays if no roles assigned.
if plex_roles is None:
print('Настройте роли Plex, чтобы включить автоматическое приглашение в Plex после назначения роли.')
if jellyfin_roles is None:
print('Настройте роли Jellyfin, чтобы включить автоматическое приглашение в Jellyfin после назначения роли.')
async def getemail(self, after):
email = None
await embedinfo(after,'Добро пожаловать в '+ PLEX_SERVER_NAME +'. Пожалуйста, ответьте на свой адрес электронной почты, который будет добавлен на сервер Plex!')
await embedinfo(after,'Если вы не ответите в течение 24 часов, запрос будет отменен, и администратору сервера придется добавить вас вручную.')
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 = "Указанный вами адрес электронной почты недействителен. В ответе укажите адрес электронной почты, который вы использовали при регистрации в Plex."
await embederror(after, message)
continue
except asyncio.TimeoutError:
message = "Время вышло. Пожалуйста, свяжитесь напрямую с администратором сервера."
await embederror(after, message)
return None
async def getusername(self, after):
username = None
await embedinfo(after, f"Добро пожаловать в Jellyfin! Пожалуйста, укажите в ответе свое имя пользователя, которое будет добавлено на сервер Jellyfin!")
await embedinfo(after, f"Если вы не ответите в течение 24 часов, запрос будет отменен, и администратору сервера придется добавить вас вручную.")
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 = "Это имя пользователя уже занято. Пожалуйста, выберите другое имя пользователя."
await embederror(after, message)
continue
except asyncio.TimeoutError:
message = "Время вышло. Пожалуйста, свяжитесь напрямую с администратором сервера."
print("Время ожидания запроса пользователя Jellyfin истекло")
await embederror(after, message)
return None
except Exception as e:
await embederror(after, "Что-то пошло не так. Пожалуйста, попробуйте еще раз с другим именем пользователя.")
print (e)
username = None
async def addtoplex(self, email, response):
if(plexhelper.verifyemail(email)):
if plexhelper.plexadd(plex,email,Plex_LIBS):
await embedinfo(response, 'Этот адрес электронной почты был добавлен в plex')
return True
else:
await embederror(response, 'Произошла ошибка при добавлении этого адреса электронной почты. Проверьте журналы.')
return False
else:
await embederror(response, 'Неверный адрес электронной почты.')
return False
async def removefromplex(self, email, response):
if(plexhelper.verifyemail(email)):
if plexhelper.plexremove(plex,email):
await embedinfo(response, 'Этот адрес электронной почты был удален из plex.')
return True
else:
await embederror(response, 'Произошла ошибка при удалении этого адреса электронной почты. Проверьте журналы.')
return False
else:
await embederror(response, 'Неверный адрес электронной почты.')
return False
async def addtojellyfin(self, username, password, response):
if not jelly.verify_username(JELLYFIN_SERVER_URL, JELLYFIN_API_KEY, username):
await embederror(response, f'Учетная запись с именем пользователя {username} уже существует.')
return False
if jelly.add_user(JELLYFIN_SERVER_URL, JELLYFIN_API_KEY, username, password, jellyfin_libs):
return True
else:
await embederror(response, 'Произошла ошибка при добавлении этого пользователя в Jellyfin. Проверьте журналы для получения дополнительной информации.')
return False
async def removefromjellyfin(self, username, response):
if jelly.verify_username(JELLYFIN_SERVER_URL, JELLYFIN_API_KEY, username):
await embederror(response, f'Не удалось найти учетную запись с именем пользователя {username}.')
return
if jelly.remove_user(JELLYFIN_SERVER_URL, JELLYFIN_API_KEY, username):
await embedinfo(response, f'Пользователь {username} успешно удален из Jellyfin.')
return True
else:
await embederror(response, f'Произошла ошибка при удалении этого пользователя из Jellyfin. Проверьте журналы для получения дополнительной информации.')
return False
@commands.Cog.listener()
async def on_member_update(self, before, after):
if plex_roles is None and jellyfin_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 embedinfo(after, "Понятно, в ближайшее время мы добавим ваш адрес электронной почты в plex!")
if plexhelper.plexadd(plex,email,Plex_LIBS):
db.save_user_email(str(after.id), email)
await asyncio.sleep(5)
await embedinfo(after, 'Вас добавили в Plex! Войдите в plex и примите приглашение!')
else:
await embedinfo(after, 'Произошла ошибка при добавлении этого адреса электронной почты. Напишите администраторам сервера.')
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("Удален адрес электронной почты Plex {} из базы данных.".format(after.name))
#await secure.send(plexname + ' ' + after.mention + ' was removed from plex')
else:
print("Невозможно удалить Plex у этого пользователя.")
await embedinfo(after, "Вас удалили из Plex")
except Exception as e:
print(e)
print("{} Невозможно удалить этого пользователя из plex.".format(email))
plex_processed = True
break
if plex_processed:
break
role = None
# 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):
print("Добавлена ​​роль Jellyfin")
username = await self.getusername(after)
print("Имя пользователя получено от пользователя")
if username is not None:
await embedinfo(after, "Поодождите, в ближайшее время мы создадим вашу учетную запись Jellyfin!")
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 embedcustom(after, "Вы добавлены в Jellyfin!", {'Username': username, 'Password': f"||{password}||"})
await embedinfo(after, f"Перейдите по адресу {JELLYFIN_EXTERNAL_URL}, чтобы войти!")
else:
await embedinfo(after, 'Произошла ошибка при добавлении этого пользователя в Jellyfin. Напишите администраторам сервера.')
jellyfin_processed = True
break
# Jellyfin role was removed
elif role is not None and (role not in after.roles and role in before.roles):
print("Роль Jellyfin удалена")
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("Удален Jellyfin из {}".format(after.name))
#await secure.send(plexname + ' ' + after.mention + ' was removed from plex')
else:
print("Невозможно удалить Jellyfin у этого пользователя.")
await embedinfo(after, "Вас удалили из Jellyfin")
except Exception as e:
print(e)
print("{} Невозможно удалить этого пользователя из Jellyfin.".format(username))
jellyfin_processed = True
break
if jellyfin_processed:
break
@commands.Cog.listener()
async def on_member_remove(self, member):
if USE_PLEX and plex_configured:
email = db.get_useremail(member.id)
plexhelper.plexremove(plex,email)
if USE_JELLYFIN and jellyfin_configured:
jellyfin_username = db.get_jellyfin_username(member.id)
jelly.remove_user(JELLYFIN_SERVER_URL, JELLYFIN_API_KEY, jellyfin_username)
deleted = db.delete_user(member.id)
if deleted:
print("Удален {} из базы данных, поскольку пользователь покинул сервер Discord.".format(email))
@app_commands.checks.has_role(DISCORD_SERVER_PERM)
@plex_commands.command(name="invite", description="Пригласить пользователя в Plex")
async def plexinvite(self, interaction: discord.Interaction, email: str):
await self.addtoplex(email, interaction.response)
@app_commands.checks.has_role(DISCORD_SERVER_PERM)
@plex_commands.command(name="remove", description="Удаление пользователя из Plex")
async def plexremove(self, interaction: discord.Interaction, email: str):
await self.removefromplex(email, interaction.response)
@app_commands.checks.has_role(DISCORD_SERVER_PERM)
@jellyfin_commands.command(name="invite", description="Пригласить пользователя в Jellyfin")
async def jellyfininvite(self, interaction: discord.Interaction, username: str):
password = jelly.generate_password(16)
if await self.addtojellyfin(username, password, interaction.response):
await embedcustom(interaction.response, "Пользователь Jellyfin создан!", {'Username': username, 'Password': f"||{password}||"})
@app_commands.checks.has_role(DISCORD_SERVER_PERM)
@jellyfin_commands.command(name="remove", description="Удаление пользователя из Jellyfin")
async def jellyfinremove(self, interaction: discord.Interaction, username: str):
await self.removefromjellyfin(username, interaction.response)
@app_commands.checks.has_role(DISCORD_SERVER_PERM)
@membarr_commands.command(name="dbadd", description="Добавьте пользователя в базу данных Membarr")
async def dbadd(self, interaction: discord.Interaction, member: discord.Member, email: str = "", jellyfin_username: str = ""):
email = email.strip()
jellyfin_username = jellyfin_username.strip()
# Check email if provided
if email and not plexhelper.verifyemail(email):
await embederror(interaction.response, "Неверный адрес электронной почты.")
return
try:
db.save_user_all(str(member.id), email, jellyfin_username)
await embedinfo(interaction.response,'Пользователь добавлен в базу данных.')
except Exception as e:
await embedinfo(interaction.response, 'Произошла ошибка при добавлении этого пользователя в базу данных. Проверьте журналы Membarr для получения дополнительной информации.')
print(e)
@app_commands.checks.has_role(DISCORD_SERVER_PERM)
@membarr_commands.command(name="dbls", description="Посмотреть базу данных Memarr")
async def dbls(self, interaction: discord.Interaction):
embed = discord.Embed(title='База данных Memarr.')
all = db.read_all()
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))
total = str(len(all))
if(len(all)>25):
f = open("db.txt", "w")
f.write(table.draw())
f.close()
await interaction.response.send_message("База данных слишком велика! Итого: {total}".format(total = total),file=discord.File('db.txt'), ephemeral=True)
else:
await interaction.response.send_message(embed = embed, ephemeral=True)
@app_commands.checks.has_role(DISCORD_SERVER_PERM)
@membarr_commands.command(name="dbrm", description="Удалить пользователя из базы данных Membarr")
async def dbrm(self, interaction: discord.Interaction, position: int):
embed = discord.Embed(title='База данных Memarr.')
all = db.read_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)
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("{} удален из базы данных.".format(username))
await embedinfo(interaction.response,"{} удален из базы данных.".format(username))
else:
await embederror(interaction.response,"Невозможно удалить этого пользователя из базы данных.")
except Exception as e:
print(e)
async def setup(bot):
await bot.add_cog(app(bot))