Merge pull request #12 from Yoruio/experimental

Experimental
This commit is contained in:
Roy Du
2022-07-16 15:04:52 -06:00
committed by GitHub
9 changed files with 135 additions and 34 deletions

View File

@@ -41,8 +41,6 @@ This command is used to remove a record from the Db. Use /membarr dbls to determ
2. Inside the Community Applications app store, search for Invitarr.
3. Click the Install Button.
4. On the following Add Container screen, Change repository to yoruio/invitarr:latest
> **Note**
> Membarr uses a slightly different client table than Invitarr, so existing app.db files will need to be deleted (this will also delete your users). See [Migration](#migration-from-invitarr) for migration info
5. Add discord bot token.
6. Click apply
7. Finish setting up using [Setup Commands](#after-bot-has-started)
@@ -93,8 +91,8 @@ This command disables the Plex integration (currently only disables auto-add / a
# Jellyfin Setup Commands:
```
/jellyfinsettings setup <server url> <api key>
This command is used to setup the Jellyfin server
/jellyfinsettings setup <server url> <api key> <optional: external server url (default: server url)>
This command is used to setup the Jellyfin server. The external server URL is the URL that is sent to users to log into your Jellyfin server.
/jellyfinsettings addrole <@role>
These role(s) will be used as the role(s) to automatically invite user to Jellyfin
/jellyfinsettings removerole <@role>
@@ -108,7 +106,10 @@ This command disables the Jellyfin integration (currently only disables auto-add
```
# Migration from Invitarr
Membarr uses a slightly different database table than Invitarr. To migrate users, you will need a sqlite database browser like DB Browser. Add a column to the sqlite table called "jellyfin_username", and make the "email" column nullable. Or, delete your existing app.db table and start fresh.
Membarr uses a slightly different database table than Invitarr. Membarr will automatically update the Invitarr db table to the current Membarr table format, but the new table will no longer be compatible with Invitarr, so backup your app.db before running Membarr!
# Migration to Invitarr
As mentioned in [Migration from Invitarr](#Migration-From-Invitarr), Membarr has a slightly different db table than Invitarr. To Switch back to Invitarr, you will have to manually change the table format back. Open app.db in a sqlite cli tool or browser like DB Browser, then remove the "jellyfin_username" column, and make the "email" column non-nullable.
# Other stuff
**Enable Intents else bot will not Dm users after they get the role.**

View File

@@ -1,5 +1,6 @@
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
@@ -27,7 +28,6 @@ try:
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
@@ -91,9 +91,12 @@ except:
USE_PLEX = False
try:
synced = not (float(config.get(BOT_SECTION, "sync_version")) < MEMBARR_VERSION)
JELLYFIN_EXTERNAL_URL = config.get(BOT_SECTION, "jellyfin_external_url")
if not JELLYFIN_EXTERNAL_URL:
JELLYFIN_EXTERNAL_URL = JELLYFIN_SERVER_URL
except:
synced = False
JELLYFIN_EXTERNAL_URL = JELLYFIN_SERVER_URL
print("Could not get Jellyfin external url. Defaulting to server url.")
if USE_PLEX and plex_configured:
try:
@@ -120,9 +123,11 @@ class app(commands.Cog):
@commands.Cog.listener()
async def on_ready(self):
print('Made by Yoruio https://github.com/Yoruio/')
print('Forked from Invitarr https://github.com/Sleepingpirates/Invitarr')
print('Named by lordfransie')
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('------')
@@ -299,7 +304,7 @@ class app(commands.Cog):
db.save_user_jellyfin(str(after.id), username)
await asyncio.sleep(5)
await embedcustom(after, "You have been added to Jellyfin!", {'Username': username, 'Password': f"||{password}||"})
await embedinfo(after, f"Go to {JELLYFIN_SERVER_URL} to log in!")
await embedinfo(after, f"Go to {JELLYFIN_EXTERNAL_URL} to log in!")
else:
await embedinfo(after, 'There was an error adding this user to Jellyfin. Message Server Admin.')
jellyfin_processed = True
@@ -447,4 +452,4 @@ class app(commands.Cog):
print(e)
async def setup(bot):
await bot.add_cog(app(bot))
await bot.add_cog(app(bot))

View File

@@ -12,7 +12,7 @@ config = configparser.ConfigParser()
CONFIG_KEYS = ['username', 'password', 'discord_bot_token', 'plex_user', 'plex_pass',
'plex_roles', 'plex_server_name', 'plex_libs', 'owner_id', 'channel_id',
'auto_remove_user', 'jellyfin_api_key', 'jellyfin_server_url', 'jellyfin_roles',
'jellyfin_libs', 'plex_enabled', 'jellyfin_enabled', 'sync_version']
'jellyfin_libs', 'plex_enabled', 'jellyfin_enabled', 'jellyfin_external_url']
# settings
Discord_bot_token = ""
@@ -96,6 +96,14 @@ except:
print("Could not load Jellyfin config")
jellyfin_configured = 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("Could not get Jellyfin external url. Defaulting to server url.")
# Get Jellyfin roles config
try:
jellyfin_roles = config.get(BOT_SECTION, 'jellyfin_roles')
@@ -133,12 +141,6 @@ except:
print("Could not get Plex enable config. Defaulting to False")
USE_PLEX = False
try:
synced = not (float(config.get(BOT_SECTION, "sync_version")) < MEMBARR_VERSION)
except:
print("Could not find previously synced version. Setting synced to false.")
synced = False
def get_config():
"""
Function to return current config

View File

@@ -1,6 +1,9 @@
import sqlite3
from app.bot.helper.dbupdater import check_table_version, update_table
DB_URL = 'app/config/app.db'
DB_TABLE = 'clients'
def create_connection(db_file):
""" create a database connection to a SQLite database """
@@ -26,7 +29,7 @@ def checkTableExists(dbcon, tablename):
conn = create_connection(DB_URL)
# Checking if table exists
if checkTableExists(conn, 'clients'):
if checkTableExists(conn, DB_TABLE):
print('Table exists.')
else:
conn.execute(
@@ -38,6 +41,8 @@ else:
PRIMARY KEY("id" AUTOINCREMENT)
);''')
update_table(conn, DB_TABLE)
def save_user_email(username, email):
if username and email:
conn.execute(f"""

View File

@@ -0,0 +1,65 @@
import sqlite3
CURRENT_VERSION = 'Membarr V1.1'
table_history = {
'Invitarr V1.0': [
(0, 'id', 'INTEGER', 1, None, 1),
(1, 'discord_username', 'TEXT', 1, None, 0),
(2, 'email', 'TEXT', 1, None, 0)
],
'Membarr V1.1': [
(0, 'id', 'INTEGER', 1, None, 1),
(1, 'discord_username', 'TEXT', 1, None, 0),
(2, 'email', 'TEXT', 0, None, 0),
(3, 'jellyfin_username', 'TEXT', 0, None, 0)
]
}
def check_table_version(conn, tablename):
dbcur = conn.cursor()
dbcur.execute(f"PRAGMA table_info({tablename})")
table_format = dbcur.fetchall()
for app_version in table_history:
if table_history[app_version] == table_format:
return app_version
raise ValueError("Could not identify database table version.")
def update_table(conn, tablename):
version = check_table_version(conn, tablename)
print('------')
print(f'DB table version: {version}')
if version == CURRENT_VERSION:
print('DB table up to date!')
print('------')
return
# Table NOT up to date.
# Update to Membarr V1.1 table
if version == 'Invitarr V1.0':
print("Upgrading DB table from Invitarr v1.0 to Membarr V1.1")
# Create temp table
conn.execute(
'''CREATE TABLE "membarr_temp_upgrade_table" (
"id" INTEGER NOT NULL UNIQUE,
"discord_username" TEXT NOT NULL UNIQUE,
"email" TEXT,
"jellyfin_username" TEXT,
PRIMARY KEY("id" AUTOINCREMENT)
);''')
conn.execute(f'''
INSERT INTO membarr_temp_upgrade_table(id, discord_username, email)
SELECT id, discord_username, email
FROM {tablename};
''')
conn.execute(f'''
DROP TABLE {tablename};
''')
conn.execute(f'''
ALTER TABLE membarr_temp_upgrade_table RENAME TO {tablename}
''')
conn.commit()
version = 'Membarr V1.1'
print('------')

View File

@@ -164,12 +164,12 @@ def get_config(jellyfin_url, jellyfin_api_key):
url = f"{jellyfin_url}/System/Configuration"
querystring = {"api_key":jellyfin_api_key}
response = requests.request("GET", url, params=querystring)
response = requests.request("GET", url, params=querystring, timeout=5)
return response.json()
def get_status(jellyfin_url, jellyfin_api_key):
url = f"{jellyfin_url}/System/Configuration"
querystring = {"api_key":jellyfin_api_key}
response = requests.request("GET", url, params=querystring)
response = requests.request("GET", url, params=querystring, timeout=5)
return response.status_code

View File

@@ -18,11 +18,11 @@ async def embedcustom(recipient, title, fields, ephemeral=True):
async def send_info(recipient, message, ephemeral=True):
if isinstance(recipient, discord.InteractionResponse):
await recipient.send_message(message, ephemeral=ephemeral)
elif isinstance(recipient, discord.User) or isinstance(recipient, discord.member.Member):
elif isinstance(recipient, discord.User) or isinstance(recipient, discord.member.Member) or isinstance(recipient, discord.Webhook):
await recipient.send(message)
async def send_embed(recipient, embed, ephemeral=True):
if isinstance(recipient, discord.User) or isinstance(recipient, discord.member.Member):
if isinstance(recipient, discord.User) or isinstance(recipient, discord.member.Member) or isinstance(recipient, discord.Webhook):
await recipient.send(embed=embed)
elif isinstance(recipient, discord.InteractionResponse):
await recipient.send_message(embed=embed, ephemeral = ephemeral)

View File

@@ -0,0 +1,14 @@
from multiprocessing import AuthenticationError
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKCYAN = '\033[96m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
AUTHOR = '\033[1;45;96m'

27
run.py
View File

@@ -11,14 +11,14 @@ from app.bot.helper.confighelper import MEMBARR_VERSION, switch, Discord_bot_tok
import app.bot.helper.confighelper as confighelper
import app.bot.helper.jellyfinhelper as jelly
from app.bot.helper.message import *
from requests import ConnectTimeout
maxroles = 10
if switch == 0:
print("Missing Config.")
sys.exit()
print(f"V {MEMBARR_VERSION}")
class Bot(commands.Bot):
def __init__(self) -> None:
print("Initializing Discord bot")
@@ -154,7 +154,8 @@ async def jellyrolels(interaction: discord.Interaction):
@jellyfin_commands.command(name="setup", description="Setup Jellyfin integration")
@app_commands.checks.has_permissions(administrator=True)
async def setupjelly(interaction: discord.Interaction, server_url: str, api_key: str):
async def setupjelly(interaction: discord.Interaction, server_url: str, api_key: str, external_url: str = None):
await interaction.response.defer()
# get rid of training slashes
server_url = server_url.rstrip('/')
@@ -164,28 +165,36 @@ async def setupjelly(interaction: discord.Interaction, server_url: str, api_key:
pass
elif server_status == 401:
# Unauthorized
await embederror(interaction.response, "API key provided is invalid")
await embederror(interaction.followup, "API key provided is invalid")
return
elif server_status == 403:
# Forbidden
await embederror(interaction.response, "API key provided does not have permissions")
await embederror(interaction.followup, "API key provided does not have permissions")
return
elif server_status == 404:
# page not found
await embederror(interaction.response, "Server endpoint provided was not found")
await embederror(interaction.followup, "Server endpoint provided was not found")
return
else:
await embederror(interaction.response, "Unknown error occurred while connecting to server. Check Membarr logs.")
await embederror(interaction.followup, "Unknown error occurred while connecting to Jellyfin. Check Membarr logs.")
except ConnectTimeout as e:
await embederror(interaction.followup, "Connection to server timed out. Check that Jellyfin is online and reachable.")
return
except Exception as e:
print("Exception while testing Jellyfin connection")
print(type(e).__name__)
print(e)
await embederror(interaction.response, "Could not connect to server. Check logs for more details.")
await embederror(interaction.followup, "Unknown exception while connecting to Jellyfin. Check Membarr logs")
return
confighelper.change_config("jellyfin_server_url", str(server_url))
confighelper.change_config("jellyfin_api_key", str(api_key))
if external_url is not None:
confighelper.change_config("jellyfin_external_url", str(external_url))
else:
confighelper.change_config("jellyfin_external_url", "")
print("Jellyfin server URL and API key updated. Restarting bot.")
await interaction.response.send_message("Jellyfin server URL and API key updated. Restarting bot.", ephemeral=True)
await interaction.followup.send("Jellyfin server URL and API key updated. Restarting bot.", ephemeral=True)
await reload()
print("Bot has been restarted. Give it a few seconds.")