From caad0a84e3081cea41d50a601952956aadb9b4fb Mon Sep 17 00:00:00 2001 From: hockeygoalie35 Date: Mon, 25 Dec 2023 23:40:00 -0500 Subject: [PATCH 01/14] Added ARL Checking script optional flags for Telegram connectivity. Fixed some typos. --- lidarr/extended.conf | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lidarr/extended.conf b/lidarr/extended.conf index 49157eb..88b0b5e 100644 --- a/lidarr/extended.conf +++ b/lidarr/extended.conf @@ -44,14 +44,14 @@ tidalClientTestDownloadId="166356219" # A known good tidal track id that is use # QUALITY audioLyricType="both" # both or explicit or clean :: both, is explicit preferred matching, explicit is explicit releases only matching and clean is clean releases only matching -audioFormat="native" # native or alac or mp3 or aac or opus :: native is the native download client file type, selected by the matching audio bitrate -audioBitrate="lossless" # master or lossless or high or low or ### :: master = MQA/lossless flac files, lossless = flac files, high = 320K, low = 128k/96k, ### = the output bitrate of converted lossless files to selected audioFormat that is not native, example: 192... +audioFormat="native" # native or alac or mp3 or aac or opus :: native is the native download client file type, selected by the matching audio bit-rate +audioBitrate="lossless" # master or lossless or high or low or ### :: master = MQA/lossless flac files, lossless = flac files, high = 320K, low = 128k/96k, ### = the output bit-rate of converted lossless files to selected audioFormat that is not native, example: 192... requireQuality="false" # true = enabled :: Downloads will be checked for quality and require to have the requested file format & quality # POST PROCESSING enableBeetsTagging="true" # true = enabled :: Downloads will be processed and tagged by Beets beetsMatchPercentage="90" # 1-100 :: Set this to the minimum percentage required for Beets to match the downloaded album to a musicbrainz release :: Lower percentage is less restrictive -enableReplaygainTags="true" # true = enabled :: Downloads will be tagged with Replaygain Metadata +enableReplaygainTags="true" # true = enabled :: Downloads will be tagged with ReplayGain Metadata # ADD ARTIST AUTOMATION addDeezerTopArtists="false" # true = enabled :: Enabling this will enable the extended script to automatically add artists that are on the Deezer Top Artist Chart to your existing Lidarr instance @@ -63,9 +63,15 @@ numberOfRelatedArtistsToAddPerArtist="1" # 1-20 :: This will limit the number of ##### VIDEO SCRIPT addFeaturedVideoArtists="false" # true = enabled :: WARNING !!! WARNING !!! Enabling this can cause an endless loop of additional artists.... Enabling this will enable the extended Video script to automatically add Music Video Featured Artists to your existing Lidarr artists from IMVDB -videoFormat="bv[width>=1920]+ba" # ONLY CHANGE if you know what your doing, for guidence, please see yt-dlp documentation. -youtubeSubtitleLanguage="en" # Desired Language Code :: For guidence, please see yt-dlp documentation. +videoFormat="bv[width>=1920]+ba" # ONLY CHANGE if you know what your doing, for guidance, please see yt-dlp documentation. +youtubeSubtitleLanguage="en" # Desired Language Code :: For guidance, please see yt-dlp documentation. ##### PLEX NOTIFY SCRIPT plexUrl="" # ONLY used if PlexNotify.bash is used, example: http://x.x.x.x:32400 plexToken="" # ONLY used if PlexNotify.bash is used + +##### DEEZER ARL UPDATE SCRIPT OPTIONALS +telegramBotEnable="false" +telegramBotToken="" # Get token from BotFather during bot creation. If you use a notify channel for Lidarr, you can probably use the same bot, as this script only takes temporary control. +telegramUserChatID="" # Get your userid by chatting: t.me/userinfobot + From b309569d3479bfe3a79de44baf9f551262d33476 Mon Sep 17 00:00:00 2001 From: hockeygoalie35 Date: Tue, 6 Feb 2024 21:05:58 -0500 Subject: [PATCH 02/14] Initial Commit. setup is currently pointing to my fork. --- lidarr/ARLChecker | 8 + lidarr/python/ARLChecker.py | 324 ++++++++++++++++++++++++++++++++++++ lidarr/setup.bash | 10 ++ 3 files changed, 342 insertions(+) create mode 100644 lidarr/ARLChecker create mode 100644 lidarr/python/ARLChecker.py diff --git a/lidarr/ARLChecker b/lidarr/ARLChecker new file mode 100644 index 0000000..1ce1906 --- /dev/null +++ b/lidarr/ARLChecker @@ -0,0 +1,8 @@ +#!/usr/bin/with-contenv bash +scriptVersion="0.1" +scriptName="ARLChecker" + +echo Starting ARL Token Check... +python /custom-services.d/python/ARLChecker.py -c +echo ARL Token Check Complete. Sleeping for 24hrs... +sleep 24h \ No newline at end of file diff --git a/lidarr/python/ARLChecker.py b/lidarr/python/ARLChecker.py new file mode 100644 index 0000000..91a2ca8 --- /dev/null +++ b/lidarr/python/ARLChecker.py @@ -0,0 +1,324 @@ +import re +from pathlib import Path +from dataclasses import dataclass +from requests import Session +from argparse import ArgumentParser +from sys import argv +from colorama import Fore, init +from telegram import Update +from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler +import logging +import os + +logging.basicConfig( + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + level=logging.INFO +) +logger = logging.getLogger(__name__) + + + +#Initialize colorama +init(autoreset=True) + +USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/110.0' + + +# Deezer Login Exception messages +CONNECTION_ERROR = 'Could not connect! Service down, API changed, wrong credentials or code-related issue.' +APP_ID_ERROR = 'Could not obtain App-Id! Service down or API changed.' +AUTH_ERROR = 'Could not login! Credentials wrong or non-existent account!' +PARSE_ERROR = 'Could not parse JSON!' + + + +@dataclass +class Plan: + name: str + expires: str + active: bool + download: bool + lossless: bool + explicit: bool + + +@dataclass +class Account: + id: int + token: str + country: str + plan: Plan + + +class AuthError(Exception): + pass + + +class ParseError(Exception): + pass + + +class ServiceError(Exception): + pass + + +class DeezerPlatformProvider: + NAME = 'Deezer' + + BASE_URL = 'http://www.deezer.com' + API_PATH = '/ajax/gw-light.php' + SESSION_DATA = { + 'api_token': 'null', + 'api_version': '1.0', + 'input': '3', + 'method': 'deezer.getUserData' + } + + def __init__(self): + super().__init__() + self.session = Session() + self.session.headers.update({'User-Agent': USER_AGENT}) + + def login(self, username, secret): + try: + res = self.session.post( + self.BASE_URL + self.API_PATH, + cookies={'arl': secret}, + data=self.SESSION_DATA + ) + res.raise_for_status() + except Exception as error: + raise ConnectionError(CONNECTION_ERROR) + + self.session.cookies.clear() + + try: + res = res.json() + except Exception as error: + raise ParseError(PARSE_ERROR) + + if 'error' in res and res['error']: + raise ServiceError(res["error"]) + + res = res['results'] + + if res['USER']['USER_ID'] == 0: + raise AuthError(AUTH_ERROR) + + return Account(username, secret, res['COUNTRY'], Plan( + res['OFFER_NAME'], + 'Unknown', + True, + True, + res['USER']['OPTIONS']['web_sound_quality']['lossless'], + res['USER']['EXPLICIT_CONTENT_LEVEL'] + )) + + +class LidarrExtendedAPI: + # sets new token to extended.conf + def __init__(self, new_arl_token): + workingDir = Path(os.getcwd()) + print(workingDir) + #self.parentDir = str(workingDir.parents[1]) + self.parentDir = str(workingDir.parents[3]) # TODO: Enable when pushing + print(self.parentDir) + self.extendedConfDir = self.parentDir + '/config/extended.conf' + self.newARLToken = new_arl_token + self.arlToken = None + self.arlLineText = None + self.arlLineIndex = None + self.fileText = None + self.enable_telegram_bot = False + self.telegram_bot_running = False + self.telegram_bot_token = None + self.telegram_user_chat_id = None + self.bot = None + self.parse_extended_conf() + + + + def parse_extended_conf(self): + deezer_active = False + self.arlToken = None + arl_token_match = None + #re_search_pattern = r'"([A-Za-z0-9_\./\\-]*)"' + re_search_pattern = r'"([^"]*)"' + try: # Try to open extended.conf and read all text into a var. + with open(self.extendedConfDir, 'r', encoding='utf-8') as file: + self.fileText = file.readlines() + file.close() + except: + logger.error(f"Could not find {self.extendedConfDir}") + exit(1) + # Ensure Deezer is enabled and ARL token is populated + for line in self.fileText: + if 'dlClientSource="deezer"' in line or 'dlClientSource="both"' in line: + deezer_active = True + if 'arlToken=' in line: + self.arlLineText = line + self.arlLineIndex = self.fileText.index(self.arlLineText) + arl_token_match = re.search(re_search_pattern, line) + break + + # ARL Token wrong flag error handling. + if arl_token_match is None: + logger.error("ARL Token not found in extended.conf. Exiting") + exit(1) + elif deezer_active is False: + logger.error("Deezer not set as an active downloader in extended.conf. Exiting") + file.close() + exit(1) + self.arlToken = arl_token_match[0] + logger.info('ARL Found in extended.conf') + + for line in self.fileText: + if 'telegramBotEnable=' in line: + self.enable_telegram_bot = re.search(re_search_pattern, line)[0].replace('"', '').lower() in 'true' + if 'telegramBotToken=' in line: + self.telegram_bot_token = re.search(re_search_pattern, line)[0].replace('"', '') + if 'telegramUserChatID=' in line: + self.telegram_user_chat_id = re.search(re_search_pattern, line)[0].replace('"', '') + + + if self.enable_telegram_bot: + logger.info('Telegram bot is enabled.') + if self.telegram_bot_token is None or self.telegram_user_chat_id is None: + logger.error('Telegram bot token or user chat ID not set in extended.conf. Exiting') + exit(1) + else: + logger.info('Telegram bot is disabled. Set the flag in extended.conf to enable.') + + # Uses DeezerPlatformProvider to check if the token is valid + def check_token(self, token=None): + if token is None: + print('Invalid ARL Token Entry') + return False + try: + deezer_check = DeezerPlatformProvider() + account = deezer_check.login('', token.replace('"','')) + if account.plan: + print('Deezer Account Found.') + print(f'Plan: {account.plan.name}', end=' | ') + print(f'Expiration: {account.plan.expires}', end=' | ') + print(f'Active: {Fore.GREEN+"Y" if account.plan.active else "N"}', end=' | ') + print(f'Download: {Fore.GREEN+"Y" if account.plan.download else Fore.RED+"N"}', end=' | ') + print(f'Lossless: {Fore.GREEN+"Y" if account.plan.lossless else Fore.RED+"N"}', end=' | ') + print(f'Explicit: {Fore.GREEN+"Y" if account.plan.explicit else Fore.RED+"N"}') + return True + except Exception as e: + print(e) + + if self.telegram_bot_running: + return False + if self.enable_telegram_bot: + logger.info('Starting Telegram bot') + self.telegram_bot_running = True + self.start_telegram_bot() + exit(420) + # TODO: fix this + + def set_new_token(self): # Re-writes extended.conf with previously read-in text, replacing w/ new ARL + self.fileText[self.arlLineIndex] = self.arlLineText.replace(self.arlToken, self.newARLToken) + with open(self.extendedConfDir, 'w', encoding='utf-8') as file: + file.writelines(self.fileText) + file.close() + logger.info("New ARL token written to extended.conf") + + # After new token is set, clean up notfound and failed downloads to bypass the default 30 day wait + def clear_not_found(self): + paths = [self.parentDir + '/config/extended/logs/notfound',self.parentDir+'/config/extended/logs/downloaded/failed/deezer'] + for path in paths: + for file in os.listdir(path): + file_to_delete = os.path.join(path,file) + os.remove(file_to_delete) + + def start_telegram_bot(self): + self.bot = TelegramBotControl(self,self.telegram_bot_token,self.telegram_user_chat_id) + + +class TelegramBotControl: + def __init__(self, parent,telegram_bot_token,telegram_user_chat_id): + + async def send_expired_token_notification(application): + await application.bot.sendMessage(chat_id=self.telegram_chat_id,text='---\U0001F6A8WARNING\U0001F6A8-----\nARL TOKEN EXPIRED\n Update Token by running "/set_token "\n You can find a new ARL at:\nhttps://rentry.org/firehawk52#deezer-arls',disable_web_page_preview=True) + # TODO: Get Chat ID/ test on new bot + + self.parent = parent + self.telegram_bot_token = telegram_bot_token + self.telegram_chat_id = telegram_user_chat_id + # start bot control + self.application = ApplicationBuilder().token(self.telegram_bot_token).post_init(send_expired_token_notification).build() + token_handler = CommandHandler('set_token', self.set_token) + self.application.add_handler(token_handler) + self.application.run_polling(allowed_updates=Update.ALL_TYPES) + + + + + async def set_token(self, update, context: ContextTypes.DEFAULT_TYPE): + try: + new_token = update.message.text.split('/set_token ')[1] + if new_token == '': + raise Exception + except: + await update.message.reply_text('Invalid Entry... please try again.') + return + print(new_token) + logger.info("Testing ARL Token Validity...") + token_validity = self.parent.check_token(new_token) + if token_validity: + await context.bot.send_message(chat_id=update.effective_chat.id, text="ARL valid, applying...") + self.parent.newARLToken = '"'+new_token+'"' + self.parent.set_new_token() + self.parent.arlToken = self.parent.newARLToken + # TODO Fix this garbage - move functionality out of telegram stuff + await context.bot.send_message(chat_id=update.effective_chat.id, text="Checking configuration") + # reparse extended.conf + self.parent.parse_extended_conf() + token_validity = self.parent.check_token(self.parent.arlToken) + if token_validity: + await context.bot.send_message(chat_id=update.effective_chat.id, text="ARL Updated! \U0001F44D") + try: + await self.application.stop_running() + except Exception: + pass + + else:# If Token invalid + await update.message.reply_text(text="Token expired or inactive. try another token.") + return + +def main(arlToken = None): + parser = ArgumentParser(prog='Account Checker', description='Check if Deezer ARL Token is valid') + parser.add_argument('-c', '--check', help='Check if current ARL Token is active/valid',required=False, default=False, action='store_true') + parser.add_argument('-n', '--new', help='Set new ARL Token',type = str, required=False, default=False) + + if not argv[1:]: + parser.print_help() + parser.exit() + + args = parser.parse_args() + arlToken_instance = LidarrExtendedAPI(arlToken) + + if args.check is True: + if arlToken_instance.arlToken == '': + print("ARL Token not set. re-run with -n flag") + exit(1) + arlToken_instance.check_token(arlToken_instance.arlToken) + + + elif args.new: + if args.new == '': + print("Please pass new ARL token as an argument") + exit(96) + + arlToken_instance.newARLToken = '"'+args.new+'"' + arlToken_instance.set_new_token() + + else: + parser.print_help() + + + +if __name__ == '__main__': + main('dasdasd') diff --git a/lidarr/setup.bash b/lidarr/setup.bash index 305e577..87df26f 100644 --- a/lidarr/setup.bash +++ b/lidarr/setup.bash @@ -51,6 +51,7 @@ python3 -m pip install --upgrade pip && \ pip3 install -r ${SMA_PATH}/setup/requirements.txt mkdir -p /custom-services.d + echo "Download QueueCleaner service..." curl https://raw.githubusercontent.com/RandomNinjaAtk/arr-scripts/main/universal/services/QueueCleaner -o /custom-services.d/QueueCleaner echo "Done" @@ -77,6 +78,15 @@ echo "Done" echo "Download UnmappedFilesCleaner service..." curl https://raw.githubusercontent.com/RandomNinjaAtk/arr-scripts/main/lidarr/UnmappedFilesCleaner.bash -o /custom-services.d/UnmappedFilesCleaner +echo "Done" + +mkdir -p /custom-services.d/python +echo "Download ARLChecker service..." +curl https://github.com/hockeygoalie35/arr-scripts/tree/main/lidarr/python/ARLChecker.py -o /custom-services.d/python/ARLChecker.py +curl https://github.com/hockeygoalie35/arr-scripts/tree/main/lidarr/ARLChecker -o /custom-services.d/ARLChecker + + + echo "Done" mkdir -p /config/extended From f5302b78348c2aa897c0eb7d4dfac558019d4a9a Mon Sep 17 00:00:00 2001 From: hockeygoalie35 Date: Tue, 6 Feb 2024 22:59:13 -0500 Subject: [PATCH 03/14] Refactor. Set all messages including errors to logging Set logging formatting to match Audio script Add additional commands to telegram bot temporarily set sleep time to 1m for debugging purposes --- lidarr/ARLChecker | 2 +- lidarr/python/ARLChecker.py | 98 ++++++++++++++++++++++++++----------- 2 files changed, 70 insertions(+), 30 deletions(-) diff --git a/lidarr/ARLChecker b/lidarr/ARLChecker index 1ce1906..6ee96b6 100644 --- a/lidarr/ARLChecker +++ b/lidarr/ARLChecker @@ -5,4 +5,4 @@ scriptName="ARLChecker" echo Starting ARL Token Check... python /custom-services.d/python/ARLChecker.py -c echo ARL Token Check Complete. Sleeping for 24hrs... -sleep 24h \ No newline at end of file +sleep 1m \ No newline at end of file diff --git a/lidarr/python/ARLChecker.py b/lidarr/python/ARLChecker.py index 91a2ca8..5389e9d 100644 --- a/lidarr/python/ARLChecker.py +++ b/lidarr/python/ARLChecker.py @@ -10,28 +10,25 @@ from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler import logging import os + +VERSION = 0.1 + +# Logging Setup logging.basicConfig( - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + format=f'%(asctime)s :: ARLChecker :: {VERSION} :: %(levelname)s :: %(message)s', + datefmt='%Y-%m-%d %H:%M:%S', level=logging.INFO ) logger = logging.getLogger(__name__) -#Initialize colorama +# Initialize colorama init(autoreset=True) +# Web agent used to access Deezer USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/110.0' - -# Deezer Login Exception messages -CONNECTION_ERROR = 'Could not connect! Service down, API changed, wrong credentials or code-related issue.' -APP_ID_ERROR = 'Could not obtain App-Id! Service down or API changed.' -AUTH_ERROR = 'Could not login! Credentials wrong or non-existent account!' -PARSE_ERROR = 'Could not parse JSON!' - - - @dataclass class Plan: name: str @@ -88,22 +85,26 @@ class DeezerPlatformProvider: ) res.raise_for_status() except Exception as error: - raise ConnectionError(CONNECTION_ERROR) + logger.error(Fore.RED + 'Could not connect! Service down, API changed, wrong credentials or code-related issue.' + Fore.WHITE) + raise ConnectionError() self.session.cookies.clear() try: res = res.json() except Exception as error: - raise ParseError(PARSE_ERROR) + logger.error(Fore.RED + "Could not parse JSON response from DEEZER!" + Fore.WHITE) + raise ParseError() if 'error' in res and res['error']: - raise ServiceError(res["error"]) + logger.error(Fore.RED + "Deezer returned the following error:{}".format(res["error"]) + Fore.WHITE) + raise ServiceError() res = res['results'] if res['USER']['USER_ID'] == 0: - raise AuthError(AUTH_ERROR) + logger.error(Fore.RED+"ARL Token Expired. Update the token in extended.conf"+Fore.WHITE) + raise AuthError() return Account(username, secret, res['COUNTRY'], Plan( res['OFFER_NAME'], @@ -121,7 +122,7 @@ class LidarrExtendedAPI: workingDir = Path(os.getcwd()) print(workingDir) #self.parentDir = str(workingDir.parents[1]) - self.parentDir = str(workingDir.parents[3]) # TODO: Enable when pushing + self.parentDir = str(workingDir.parents[3]) print(self.parentDir) self.extendedConfDir = self.parentDir + '/config/extended.conf' self.newARLToken = new_arl_token @@ -133,6 +134,9 @@ class LidarrExtendedAPI: self.telegram_bot_running = False self.telegram_bot_token = None self.telegram_user_chat_id = None + self.telegramBotEnableLineText = None + self.telegramBotEnableLineIndex = None + self.bot = None self.parse_extended_conf() @@ -142,7 +146,6 @@ class LidarrExtendedAPI: deezer_active = False self.arlToken = None arl_token_match = None - #re_search_pattern = r'"([A-Za-z0-9_\./\\-]*)"' re_search_pattern = r'"([^"]*)"' try: # Try to open extended.conf and read all text into a var. with open(self.extendedConfDir, 'r', encoding='utf-8') as file: @@ -174,6 +177,8 @@ class LidarrExtendedAPI: for line in self.fileText: if 'telegramBotEnable=' in line: + self.telegramBotEnableLineText = line + self.telegramBotEnableLineIndex = self.fileText.index(self.telegramBotEnableLineText) self.enable_telegram_bot = re.search(re_search_pattern, line)[0].replace('"', '').lower() in 'true' if 'telegramBotToken=' in line: self.telegram_bot_token = re.search(re_search_pattern, line)[0].replace('"', '') @@ -191,6 +196,7 @@ class LidarrExtendedAPI: # Uses DeezerPlatformProvider to check if the token is valid def check_token(self, token=None): + logger.info('Checking ARL Token Validity...') if token is None: print('Invalid ARL Token Entry') return False @@ -198,13 +204,15 @@ class LidarrExtendedAPI: deezer_check = DeezerPlatformProvider() account = deezer_check.login('', token.replace('"','')) if account.plan: - print('Deezer Account Found.') - print(f'Plan: {account.plan.name}', end=' | ') - print(f'Expiration: {account.plan.expires}', end=' | ') - print(f'Active: {Fore.GREEN+"Y" if account.plan.active else "N"}', end=' | ') - print(f'Download: {Fore.GREEN+"Y" if account.plan.download else Fore.RED+"N"}', end=' | ') - print(f'Lossless: {Fore.GREEN+"Y" if account.plan.lossless else Fore.RED+"N"}', end=' | ') - print(f'Explicit: {Fore.GREEN+"Y" if account.plan.explicit else Fore.RED+"N"}') + logger.info(Fore.GREEN + f'Deezer Account Found.'+ Fore.WHITE) + logger.info('-------------------------------') + logger.info(f'Plan: {account.plan.name}') + logger.info(f'Expiration: {account.plan.expires}') + logger.info(f'Active: {Fore.GREEN+"Y" if account.plan.active else "N"}'+Fore.WHITE) + logger.info(f'Download: {Fore.GREEN+"Y" if account.plan.download else Fore.RED+"N"}'+Fore.WHITE) + logger.info(f'Lossless: {Fore.GREEN+"Y" if account.plan.lossless else Fore.RED+"N"}'+Fore.WHITE) + logger.info(f'Explicit: {Fore.GREEN+"Y" if account.plan.explicit else Fore.RED+"N"}'+Fore.WHITE) + logger.info('-------------------------------') return True except Exception as e: print(e) @@ -212,11 +220,10 @@ class LidarrExtendedAPI: if self.telegram_bot_running: return False if self.enable_telegram_bot: - logger.info('Starting Telegram bot') + logger.info('Starting Telegram bot...Check Telegram and follow instructions.') self.telegram_bot_running = True self.start_telegram_bot() exit(420) - # TODO: fix this def set_new_token(self): # Re-writes extended.conf with previously read-in text, replacing w/ new ARL self.fileText[self.arlLineIndex] = self.arlLineText.replace(self.arlToken, self.newARLToken) @@ -225,7 +232,7 @@ class LidarrExtendedAPI: file.close() logger.info("New ARL token written to extended.conf") - # After new token is set, clean up notfound and failed downloads to bypass the default 30 day wait + # After new token is set, clean up notfound and failed downloads to bypass the default 30 day wait def clear_not_found(self): paths = [self.parentDir + '/config/extended/logs/notfound',self.parentDir+'/config/extended/logs/downloaded/failed/deezer'] for path in paths: @@ -236,12 +243,22 @@ class LidarrExtendedAPI: def start_telegram_bot(self): self.bot = TelegramBotControl(self,self.telegram_bot_token,self.telegram_user_chat_id) + def disable_telegram_bot(self): + compiled = re.compile(re.escape('true'), re.IGNORECASE) + self.fileText[self.telegramBotEnableLineIndex] = compiled.sub('false', self.telegramBotEnableLineText) + with open(self.extendedConfDir, 'w', encoding='utf-8') as file: + file.writelines(self.fileText) + file.close() + logger.info("Telegram Bot Disabled.") + + + class TelegramBotControl: def __init__(self, parent,telegram_bot_token,telegram_user_chat_id): async def send_expired_token_notification(application): - await application.bot.sendMessage(chat_id=self.telegram_chat_id,text='---\U0001F6A8WARNING\U0001F6A8-----\nARL TOKEN EXPIRED\n Update Token by running "/set_token "\n You can find a new ARL at:\nhttps://rentry.org/firehawk52#deezer-arls',disable_web_page_preview=True) + await application.bot.sendMessage(chat_id=self.telegram_chat_id,text='---\U0001F6A8WARNING\U0001F6A8-----\nARL TOKEN EXPIRED\n Update Token by running "/set_token "\n You can find a new ARL at:\nhttps://rentry.org/firehawk52#deezer-arls\n\n\n Other Commands:\n/cancel - Cancel this session\n/disable - Disable Telegram Bot',disable_web_page_preview=True) # TODO: Get Chat ID/ test on new bot self.parent = parent @@ -250,12 +267,26 @@ class TelegramBotControl: # start bot control self.application = ApplicationBuilder().token(self.telegram_bot_token).post_init(send_expired_token_notification).build() token_handler = CommandHandler('set_token', self.set_token) + cancel_handler = CommandHandler('cancel', self.cancel) + disable_handler = CommandHandler('disable', self.disable_bot) self.application.add_handler(token_handler) + self.application.add_handler(cancel_handler) + self.application.add_handler(disable_handler) self.application.run_polling(allowed_updates=Update.ALL_TYPES) + async def disable_bot(self, update, context: ContextTypes.DEFAULT_TYPE): + self.parent.disable_telegram_bot() + await update.message.reply_text('Disabled Telegram Bot. \U0001F614\nIf you would like to re-enable,\nset telegramBotEnable to true\nin extended.conf') + self.application.stop_running() + async def cancel(self, update, context: ContextTypes.DEFAULT_TYPE): + await update.message.reply_text('Canceling...ARLToken is still expired.') + try: + self.application.stop_running() + except Exception: + pass async def set_token(self, update, context: ContextTypes.DEFAULT_TYPE): try: new_token = update.message.text.split('/set_token ')[1] @@ -304,7 +335,16 @@ def main(arlToken = None): if arlToken_instance.arlToken == '': print("ARL Token not set. re-run with -n flag") exit(1) - arlToken_instance.check_token(arlToken_instance.arlToken) + try: + arlToken_instance.check_token(arlToken_instance.arlToken) + except Exception as e: + if 'Chat not found' in str(e): + logger.error(Fore.RED + "Chat not found. Check your chat ID in extended.conf, or start a chat with your bot."+Fore.WHITE) + elif 'The token' in str(e): + logger.error(Fore.RED + "Check your Bot Token in extended.conf."+Fore.WHITE) + else: + print(e) + exit(1) elif args.new: From 8ce532e9f0b4ac3a3fa93cda6755bdfdea9e49bc Mon Sep 17 00:00:00 2001 From: hockeygoalie35 Date: Tue, 6 Feb 2024 23:09:46 -0500 Subject: [PATCH 04/14] Refactor. Set all messages including errors to logging Set logging formatting to match Audio script Add additional commands to telegram bot temporarily set sleep time to 1m for debugging purposes --- lidarr/setup.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lidarr/setup.bash b/lidarr/setup.bash index 87df26f..9bd0a26 100644 --- a/lidarr/setup.bash +++ b/lidarr/setup.bash @@ -82,8 +82,8 @@ echo "Done" mkdir -p /custom-services.d/python echo "Download ARLChecker service..." -curl https://github.com/hockeygoalie35/arr-scripts/tree/main/lidarr/python/ARLChecker.py -o /custom-services.d/python/ARLChecker.py -curl https://github.com/hockeygoalie35/arr-scripts/tree/main/lidarr/ARLChecker -o /custom-services.d/ARLChecker +curl https://raw.github.com/hockeygoalie35/arr-scripts/tree/main/lidarr/python/ARLChecker.py -o /custom-services.d/python/ARLChecker.py +curl https://raw.github.com/hockeygoalie35/arr-scripts/tree/main/lidarr/ARLChecker -o /custom-services.d/ARLChecker From 7fb21773e25e16a87c1cf3ed39c421e2a184e46b Mon Sep 17 00:00:00 2001 From: hockeygoalie35 Date: Tue, 6 Feb 2024 23:13:04 -0500 Subject: [PATCH 05/14] Update setup.bash typo --- lidarr/setup.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lidarr/setup.bash b/lidarr/setup.bash index 9bd0a26..d24c574 100644 --- a/lidarr/setup.bash +++ b/lidarr/setup.bash @@ -82,8 +82,8 @@ echo "Done" mkdir -p /custom-services.d/python echo "Download ARLChecker service..." -curl https://raw.github.com/hockeygoalie35/arr-scripts/tree/main/lidarr/python/ARLChecker.py -o /custom-services.d/python/ARLChecker.py -curl https://raw.github.com/hockeygoalie35/arr-scripts/tree/main/lidarr/ARLChecker -o /custom-services.d/ARLChecker +curl https://raw.githubusercontent.com/hockeygoalie35/arr-scripts/main/lidarr/python/ARLChecker.py -o /custom-services.d/python/ARLChecker.py +curl https://raw.githubusercontent.com/hockeygoalie35/arr-scripts/main/lidarr/ARLChecker -o /custom-services.d/ARLChecker From d8976c4682c70ed94b2dff9f1e33d73c55f6868e Mon Sep 17 00:00:00 2001 From: hockeygoalie35 Date: Tue, 6 Feb 2024 23:31:14 -0500 Subject: [PATCH 06/14] Catch token not set. --- lidarr/python/ARLChecker.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lidarr/python/ARLChecker.py b/lidarr/python/ARLChecker.py index 5389e9d..46d5c5c 100644 --- a/lidarr/python/ARLChecker.py +++ b/lidarr/python/ARLChecker.py @@ -197,6 +197,9 @@ class LidarrExtendedAPI: # Uses DeezerPlatformProvider to check if the token is valid def check_token(self, token=None): logger.info('Checking ARL Token Validity...') + if token == '""': + logger.info(Fore.YELLOW+"No ARL Token set in Extended.conf"+Fore.WHITE) + exit(0) if token is None: print('Invalid ARL Token Entry') return False From 32c8923955e82b953fa4c61a7c1dda5162a92276 Mon Sep 17 00:00:00 2001 From: hockeygoalie35 Date: Tue, 6 Feb 2024 23:36:09 -0500 Subject: [PATCH 07/14] Add colorama and python-telegram-bot to pip install --- lidarr/setup.bash | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lidarr/setup.bash b/lidarr/setup.bash index d24c574..e702440 100644 --- a/lidarr/setup.bash +++ b/lidarr/setup.bash @@ -30,6 +30,8 @@ pip install --upgrade --no-cache-dir \ pyxDamerauLevenshtein \ pyacoustid \ requests \ + colorama \ + python-telegram-bot \ pylast \ mutagen \ r128gain \ From 7cfd44f828d11cd036c6848808e21081fe4fa356 Mon Sep 17 00:00:00 2001 From: hockeygoalie35 Date: Wed, 7 Feb 2024 22:59:59 -0500 Subject: [PATCH 08/14] Add check interval in extended.conf. --- lidarr/ARLChecker | 7 +++++-- lidarr/extended.conf | 8 +++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lidarr/ARLChecker b/lidarr/ARLChecker index 6ee96b6..cc86c96 100644 --- a/lidarr/ARLChecker +++ b/lidarr/ARLChecker @@ -1,8 +1,11 @@ #!/usr/bin/with-contenv bash -scriptVersion="0.1" +scriptVersion="0.5" scriptName="ARLChecker" +### Import Settings +source /config/extended.conf + echo Starting ARL Token Check... python /custom-services.d/python/ARLChecker.py -c echo ARL Token Check Complete. Sleeping for 24hrs... -sleep 1m \ No newline at end of file +sleep "$arlUpdateInterval" \ No newline at end of file diff --git a/lidarr/extended.conf b/lidarr/extended.conf index 4dce11f..ed19b14 100644 --- a/lidarr/extended.conf +++ b/lidarr/extended.conf @@ -73,7 +73,9 @@ plexUrl="" # ONLY used if PlexNotify.bash is used, example: http://x.x.x.x:324 plexToken="" # ONLY used if PlexNotify.bash is used ##### DEEZER ARL UPDATE SCRIPT OPTIONALS -telegramBotEnable="false" -telegramBotToken="" # Get token from BotFather during bot creation. If you use a notify channel for Lidarr, you can probably use the same bot, as this script only takes temporary control. -telegramUserChatID="" # Get your userid by chatting: t.me/userinfobot +arlUpdateInterval='1m' # Interval to check ARL Validity (default 24 hours). Reboot container after changing. s = seconds, m = minutes, h = hours, d = days +telegramBotEnable="false" # Enable/Disable Telegram Bot to notify if ARL expires. Otherwise check text file in custom-services.d/python for status. +telegramBotToken="" # Get token from BotFather during bot creation. If you use a notify channel for Lidarr, you can probably use the same bot, as this script only takes temporary control. +telegramUserChatID="" # Get your userid by chatting: t.me/userinfobot + From d8ad588cbe829a138dca34e289b49572bf073f52 Mon Sep 17 00:00:00 2001 From: hockeygoalie35 Date: Wed, 7 Feb 2024 23:16:59 -0500 Subject: [PATCH 09/14] Add text status report fallback if user doesn't use Telegram bot. --- lidarr/ARLChecker | 2 +- lidarr/python/ARLChecker.py | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lidarr/ARLChecker b/lidarr/ARLChecker index cc86c96..2af94fe 100644 --- a/lidarr/ARLChecker +++ b/lidarr/ARLChecker @@ -1,5 +1,5 @@ #!/usr/bin/with-contenv bash -scriptVersion="0.5" +scriptVersion="0.1" scriptName="ARLChecker" ### Import Settings diff --git a/lidarr/python/ARLChecker.py b/lidarr/python/ARLChecker.py index 46d5c5c..eddf80a 100644 --- a/lidarr/python/ARLChecker.py +++ b/lidarr/python/ARLChecker.py @@ -9,6 +9,7 @@ from telegram import Update from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler import logging import os +from datetime import datetime VERSION = 0.1 @@ -199,6 +200,7 @@ class LidarrExtendedAPI: logger.info('Checking ARL Token Validity...') if token == '""': logger.info(Fore.YELLOW+"No ARL Token set in Extended.conf"+Fore.WHITE) + self.report_status("NOT SET") exit(0) if token is None: print('Invalid ARL Token Entry') @@ -216,10 +218,11 @@ class LidarrExtendedAPI: logger.info(f'Lossless: {Fore.GREEN+"Y" if account.plan.lossless else Fore.RED+"N"}'+Fore.WHITE) logger.info(f'Explicit: {Fore.GREEN+"Y" if account.plan.explicit else Fore.RED+"N"}'+Fore.WHITE) logger.info('-------------------------------') + self.report_status('VALID') return True except Exception as e: print(e) - + self.report_status('EXPIRED') if self.telegram_bot_running: return False if self.enable_telegram_bot: @@ -243,6 +246,12 @@ class LidarrExtendedAPI: file_to_delete = os.path.join(path,file) os.remove(file_to_delete) + def report_status(self, status): + f = open("ARLStatus.txt", "w") + now = datetime.strftime(datetime.now(),"%b-%d-%Y at %H:%M:%S") + f.write(f"{now}: ARL Token is {status}.{' Please update arlToken in extended.conf' if status=='EXPIRED' else ''}") + f.close() + def start_telegram_bot(self): self.bot = TelegramBotControl(self,self.telegram_bot_token,self.telegram_user_chat_id) @@ -322,6 +331,8 @@ class TelegramBotControl: await update.message.reply_text(text="Token expired or inactive. try another token.") return + + def main(arlToken = None): parser = ArgumentParser(prog='Account Checker', description='Check if Deezer ARL Token is valid') parser.add_argument('-c', '--check', help='Check if current ARL Token is active/valid',required=False, default=False, action='store_true') @@ -364,4 +375,4 @@ def main(arlToken = None): if __name__ == '__main__': - main('dasdasd') + main('FAKETOKEN') From 832e5a035e2c8437903a7408a672e6ae8a10ca5a Mon Sep 17 00:00:00 2001 From: hockeygoalie35 Date: Wed, 7 Feb 2024 23:30:09 -0500 Subject: [PATCH 10/14] Adjust text report path --- lidarr/python/ARLChecker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lidarr/python/ARLChecker.py b/lidarr/python/ARLChecker.py index eddf80a..48b6c5c 100644 --- a/lidarr/python/ARLChecker.py +++ b/lidarr/python/ARLChecker.py @@ -247,7 +247,7 @@ class LidarrExtendedAPI: os.remove(file_to_delete) def report_status(self, status): - f = open("ARLStatus.txt", "w") + f = open("/custom-services.d/python/ARLStatus.txt", "w") now = datetime.strftime(datetime.now(),"%b-%d-%Y at %H:%M:%S") f.write(f"{now}: ARL Token is {status}.{' Please update arlToken in extended.conf' if status=='EXPIRED' else ''}") f.close() From 536607f52398e9b9315295bae6b2a99e4bce3fab Mon Sep 17 00:00:00 2001 From: hockeygoalie35 Date: Wed, 7 Feb 2024 23:33:40 -0500 Subject: [PATCH 11/14] Finalize extended.conf new params. --- lidarr/extended.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lidarr/extended.conf b/lidarr/extended.conf index ed19b14..de5c755 100644 --- a/lidarr/extended.conf +++ b/lidarr/extended.conf @@ -73,7 +73,7 @@ plexUrl="" # ONLY used if PlexNotify.bash is used, example: http://x.x.x.x:324 plexToken="" # ONLY used if PlexNotify.bash is used ##### DEEZER ARL UPDATE SCRIPT OPTIONALS -arlUpdateInterval='1m' # Interval to check ARL Validity (default 24 hours). Reboot container after changing. s = seconds, m = minutes, h = hours, d = days +arlUpdateInterval='24h' # Interval to check ARL Validity (default 24 hours). Reboot container after changing. s = seconds, m = minutes, h = hours, d = days telegramBotEnable="false" # Enable/Disable Telegram Bot to notify if ARL expires. Otherwise check text file in custom-services.d/python for status. telegramBotToken="" # Get token from BotFather during bot creation. If you use a notify channel for Lidarr, you can probably use the same bot, as this script only takes temporary control. telegramUserChatID="" # Get your userid by chatting: t.me/userinfobot From 2e412c6ed16402a1d6738e412391b934ae243a85 Mon Sep 17 00:00:00 2001 From: hockeygoalie35 Date: Wed, 7 Feb 2024 23:34:44 -0500 Subject: [PATCH 12/14] Finalize. Set download path for ARLChecker from RandomNinaAtk's repo. --- lidarr/setup.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lidarr/setup.bash b/lidarr/setup.bash index e702440..e0696a9 100644 --- a/lidarr/setup.bash +++ b/lidarr/setup.bash @@ -84,8 +84,8 @@ echo "Done" mkdir -p /custom-services.d/python echo "Download ARLChecker service..." -curl https://raw.githubusercontent.com/hockeygoalie35/arr-scripts/main/lidarr/python/ARLChecker.py -o /custom-services.d/python/ARLChecker.py -curl https://raw.githubusercontent.com/hockeygoalie35/arr-scripts/main/lidarr/ARLChecker -o /custom-services.d/ARLChecker +curl https://raw.githubusercontent.com/RandomNinjaAtk/arr-scripts/main/lidarr/python/ARLChecker.py -o /custom-services.d/python/ARLChecker.py +curl https://raw.githubusercontent.com/RandomNinjaAtk/arr-scripts/main/lidarr/ARLChecker -o /custom-services.d/ARLChecker From dd8b9d59055b8b3825c2d099935fc479ab413fde Mon Sep 17 00:00:00 2001 From: hockeygoalie35 Date: Wed, 7 Feb 2024 23:39:48 -0500 Subject: [PATCH 13/14] Update readme.md to include ARLChecker --- lidarr/readme.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lidarr/readme.md b/lidarr/readme.md index 81c3bde..bc0eb96 100644 --- a/lidarr/readme.md +++ b/lidarr/readme.md @@ -78,6 +78,10 @@ This configuration does its best to update everything automatically, but with ho * Automatically removes downloads that have a "warning" or "failed" status that will not auto-import into Lidarr, which enables Lidarr to automatically re-search for the album * Unmapped Folder Cleaner Script * Automatically deletes folders that are not mapped in Lidarr +* ARLChecker Script + * Checks Deezer ARL set in extended.conf at set interval for validity + * Reports ARL status in text file + * Optional Telegram bot with ability to set token from the chat For more details, visit the [Wiki](https://github.com/RandomNinjaAtk/arr-scripts/wiki/Lidarr) From 777eda18a356240c6ba78da45e22d2a96e8ab678 Mon Sep 17 00:00:00 2001 From: hockeygoalie35 Date: Fri, 9 Feb 2024 21:20:32 -0500 Subject: [PATCH 14/14] Re-added missing Video Script Params. --- lidarr/extended.conf | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lidarr/extended.conf b/lidarr/extended.conf index de5c755..3df75ca 100644 --- a/lidarr/extended.conf +++ b/lidarr/extended.conf @@ -65,14 +65,15 @@ autoArtistAdderMonitored="true" # true or false :: If true, artists tha ##### VIDEO SCRIPT addFeaturedVideoArtists="false" # true = enabled :: WARNING !!! WARNING !!! Enabling this can cause an endless loop of additional artists.... Enabling this will enable the extended Video script to automatically add Music Video Featured Artists to your existing Lidarr artists from IMVDB -videoFormat="bv[width>=1920]+ba" # ONLY CHANGE if you know what your doing, for guidance, please see yt-dlp documentation. -youtubeSubtitleLanguage="en" # Desired Language Code :: For guidance, please see yt-dlp documentation. +videoFormat="bv[width>=1920]+ba" # ONLY CHANGE if you know what your doing, for guidence, please see yt-dlp documentation. +youtubeSubtitleLanguage="en" # Desired Language Code :: For guidence, please see yt-dlp documentation. +disableImvd="false" # true = enabled :: Use this to disable IMVDB as a source, will result in only tidal videos ##### PLEX NOTIFY SCRIPT plexUrl="" # ONLY used if PlexNotify.bash is used, example: http://x.x.x.x:32400 plexToken="" # ONLY used if PlexNotify.bash is used -##### DEEZER ARL UPDATE SCRIPT OPTIONALS +##### DEEZER ARLCHECKER arlUpdateInterval='24h' # Interval to check ARL Validity (default 24 hours). Reboot container after changing. s = seconds, m = minutes, h = hours, d = days telegramBotEnable="false" # Enable/Disable Telegram Bot to notify if ARL expires. Otherwise check text file in custom-services.d/python for status. telegramBotToken="" # Get token from BotFather during bot creation. If you use a notify channel for Lidarr, you can probably use the same bot, as this script only takes temporary control.