def exit_bot(): from JJMumbleBot.lib.utils import dir_utils if global_settings.mumble_inst: global_settings.gui_service.quick_gui( f"{get_bot_name()} is being shutdown.", text_type='header', box_align='left', ignore_whisper=True, ) for plugin in global_settings.bot_plugins.values(): plugin.quit() if global_settings.flask_server: global_settings.flask_server.stop() dprint("Terminated flask server instance.", origin=L_SHUTDOWN) if global_settings.socket_server: global_settings.socket_server = None dprint("Terminated web socket server instance.", origin=L_SHUTDOWN) if global_settings.audio_inst: global_settings.audio_inst.kill() global_settings.audio_inst = None global_settings.aud_interface.exit_flag = True dprint("Terminated audio web interface instance.", origin=L_SHUTDOWN) dir_utils.clear_directory(dir_utils.get_temp_med_dir()) dprint("Cleared temporary directories on shutdown.") log(INFO, "Cleared temporary directories on shutdown.", origin=L_SHUTDOWN) global_settings.exit_flag = True
def download_image_stream_to_dir(img_url, dir_name, img_name='_image', force_jpg=True): dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/{dir_name}') img_ext = img_url.rsplit('.', 1)[1] with open( f"{dir_utils.get_temp_med_dir()}/{dir_name}/{img_name}.{img_ext}", 'wb') as img_file: resp = requests.get(img_url, stream=True) for block in resp.iter_content(1024): if not block: break img_file.write(block) if img_ext == 'png' and force_jpg: log(WARNING, WARN_IMG_INCORRECT_FORMAT, origin=L_GENERAL, error_type=WARN_FIXED_IMG_FORMAT, print_mode=PrintMode.VERBOSE_PRINT.value) img_fix = Image.open( f"{dir_utils.get_temp_med_dir()}/{dir_name}/{img_name}.{img_ext}") img_fix.convert('RGB').save( f"{dir_utils.get_temp_med_dir()}/{dir_name}/{img_name}.jpg") dir_utils.remove_file(f"{img_name}.png", f'{dir_utils.get_temp_med_dir()}/{dir_name}') log(INFO, INFO_IMG_DOWNLOADED, origin=L_GENERAL, print_mode=PrintMode.VERBOSE_PRINT.value)
def on_reset(): # Clear the thumbnails since the queue is cleared. dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/{settings.plugin_name}') log(INFO, "Cleared the thumbnails in the temporary media folder when resetting audio interface.", origin=L_GENERAL, print_mode=PrintMode.VERBOSE_PRINT.value) settings.can_play = False settings.search_results = None
def quit(self): if gs.aud_interface.check_dni_is_mine(self.plugin_name): gs.aud_interface.stop() gs.audio_dni = None self.is_running = False dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/{self.plugin_name}') log(INFO, f"Exiting {self.plugin_name} plugin...", origin=L_SHUTDOWN, print_mode=PrintMode.REG_PRINT.value)
def quit(self): ttsu.clear_audio_thread() ttsu.stop_audio() dir_utils.clear_directory( f'{dir_utils.get_temp_med_dir()}/text_to_speech') tts_settings.exit_flag = True dprint(f"Exiting {self.plugin_name} plugin...", origin=L_SHUTDOWN) log(INFO, f"Exiting {self.plugin_name} plugin...", origin=L_SHUTDOWN)
def quit(self): if gs.aud_interface.check_dni_is_mine(self.plugin_name): gs.aud_interface.stop() gs.audio_dni = None dir_utils.clear_directory( f'{dir_utils.get_temp_med_dir()}/text_to_speech') dprint(f"Exiting {self.plugin_name} plugin...", origin=L_SHUTDOWN) log(INFO, f"Exiting {self.plugin_name} plugin...", origin=L_SHUTDOWN)
def quit(self): if gs.vlc_interface.check_dni_is_mine( self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]): gs.vlc_interface.stop() gs.audio_dni = None dir_utils.clear_directory( f'{dir_utils.get_temp_med_dir()}/{self.plugin_name}') dprint(f"Exiting {self.plugin_name} plugin...", origin=L_SHUTDOWN) log(INFO, f"Exiting {self.plugin_name} plugin...", origin=L_SHUTDOWN)
def download_image_stream(img_url): dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/internal/images') img_ext = img_url.rsplit('.', 1)[1] with open(f"{dir_utils.get_temp_med_dir()}/internal/images/_image.{img_ext}", 'wb') as img_file: resp = requests.get(img_url, stream=True) for block in resp.iter_content(1024): if not block: break img_file.write(block) log(INFO, INFO_IMG_DOWNLOADED, origin=L_GENERAL, print_mode=PrintMode.VERBOSE_PRINT.value)
def download_image_stream(img_url): dir_utils.clear_directory( f'{dir_utils.get_temp_med_dir()}/internal/images') img_ext = img_url.rsplit('.', 1)[1] with open( f"{dir_utils.get_temp_med_dir()}/internal/images/_image.{img_ext}", 'wb') as img_file: resp = requests.get(img_url, stream=True) for block in resp.iter_content(1024): if not block: break img_file.write(block) dprint(f"Downloaded image from: {img_url}")
def exit_bot(): from JJMumbleBot.lib.utils import dir_utils global_settings.gui_service.quick_gui( f"{get_bot_name()} is being shutdown.", text_type='header', box_align='left', ignore_whisper=True, ) for plugin in global_settings.bot_plugins.values(): plugin.quit() dir_utils.clear_directory(dir_utils.get_temp_med_dir()) dprint("Cleared temporary directories on shutdown.") log(INFO, "Cleared temporary directories on shutdown.", origin=L_SHUTDOWN) global_settings.exit_flag = True
def download_image_requests(img_url): dir_utils.clear_directory( f'{dir_utils.get_temp_med_dir()}/internal/images') img_ext = img_url.rsplit('.', 1)[1] s = requests.Session() r = s.get(img_url, headers={'User-Agent': 'Mozilla/5.0'}) if r.status_code == 200: with open( f"{dir_utils.get_temp_med_dir()}/internal/images/_image.{img_ext}", 'wb') as f: r.raw.decode_content = True shutil.copyfileobj(r.raw, f) dprint(f"Downloaded image from: {img_url}") else: dprint(f"{r.status_code} Error! - {img_url}")
def __init__(self): super().__init__() from json import loads self.plugin_name = os.path.basename(__file__).rsplit('.')[0] self.metadata = PluginUtilityService.process_metadata(f'plugins/extensions/{self.plugin_name}') self.plugin_cmds = loads(self.metadata.get(C_PLUGIN_INFO, P_PLUGIN_CMDS)) self.is_running = True dir_utils.make_directory(f'{gs.cfg[C_MEDIA_SETTINGS][P_TEMP_MED_DIR]}/{self.plugin_name}/') dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/{self.plugin_name}') warnings.filterwarnings("ignore", category=UserWarning, module='bs4') log( INFO, f"{self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]} v{self.metadata[C_PLUGIN_INFO][P_PLUGIN_VERS]} Plugin Initialized.", origin=L_STARTUP, print_mode=PrintMode.REG_PRINT.value )
def exit_bot_error(error_code: ExitCodes): if global_settings.mumble_inst: global_settings.gui_service.quick_gui( f"{get_bot_name()} has encountered an error and is being shutdown.<br>Please check the bot logs/console." f"<br>Exit Code: {error_code.value}", text_type='header', box_align='center', ignore_whisper=True, ) try: for plugin in global_settings.bot_plugins.values(): plugin.quit() except AttributeError: pass dir_utils.clear_directory(dir_utils.get_temp_med_dir()) log(INFO, "Cleared temporary directories on shutdown.", origin=L_SHUTDOWN, print_mode=PrintMode.VERBOSE_PRINT.value) global_settings.exit_flag = True
def download_image_requests(img_url): dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/internal/images') img_ext = img_url.rsplit('.', 1)[1] s = requests.Session() r = s.get(img_url, headers={'User-Agent': 'Mozilla/5.0'}) if r.status_code == 200: with open(f"{dir_utils.get_temp_med_dir()}/internal/images/_image.{img_ext}", 'wb') as f: r.raw.decode_content = True shutil.copyfileobj(r.raw, f) log(INFO, INFO_IMG_DOWNLOADED, origin=L_GENERAL, print_mode=PrintMode.VERBOSE_PRINT.value) else: log( ERROR, f"ERROR: Encountered a Requests Module error while trying to download an image - {r.status_code} - {img_url}", origin=L_GENERAL, error_type=GEN_PROCESS_ERR, print_mode=PrintMode.VERBOSE_PRINT.value )
def exit_bot(): if global_settings.mumble_inst: global_settings.gui_service.quick_gui( f"{get_bot_name()} is being shutdown.", text_type='header', box_align='left', ignore_whisper=True, ) for plugin in global_settings.bot_plugins.values(): plugin.quit() if global_settings.audio_inst: global_settings.audio_inst.kill() global_settings.audio_inst = None global_settings.aud_interface.exit_flag = True log(INFO, "Terminated audio interface instance.", origin=L_SHUTDOWN, print_mode=PrintMode.REG_PRINT.value) dir_utils.clear_directory(dir_utils.get_temp_med_dir()) log(INFO, "Cleared temporary directories on shutdown.", origin=L_SHUTDOWN, print_mode=PrintMode.VERBOSE_PRINT.value) global_settings.exit_flag = True
def __init__(self): super().__init__() from json import loads self.plugin_name = os.path.basename(__file__).rsplit('.')[0] self.metadata = PluginUtilityService.process_metadata( f'plugins/extensions/{self.plugin_name}') self.plugin_cmds = loads( self.metadata.get(C_PLUGIN_INFO, P_PLUGIN_CMDS)) dir_utils.make_directory( f'{gs.cfg[C_MEDIA_SETTINGS][P_TEMP_MED_DIR]}/{self.plugin_name}/') dir_utils.clear_directory( f'{dir_utils.get_temp_med_dir()}/{self.plugin_name}') warnings.filterwarnings("ignore", category=UserWarning, module='bs4') md_settings.youtube_metadata = self.metadata md_settings.plugin_name = self.plugin_name self.register_callbacks() rprint( f"{self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]} v{self.metadata[C_PLUGIN_INFO][P_PLUGIN_VERS]} Plugin Initialized." )
def download_image_stream_to_dir(img_url, dir_name): dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/{dir_name}') img_ext = img_url.rsplit('.', 1)[1] with open(f"{dir_utils.get_temp_med_dir()}/{dir_name}/_image.{img_ext}", 'wb') as img_file: resp = requests.get(img_url, stream=True) for block in resp.iter_content(1024): if not block: break img_file.write(block) if img_ext == 'png': dprint(f"Fixing image to force jpg conversion: {img_url}") img_fix = Image.open( f"{dir_utils.get_temp_med_dir()}/{dir_name}/_image.{img_ext}") img_fix.convert('RGB').save( f"{dir_utils.get_temp_med_dir()}/{dir_name}/_image.jpg") dir_utils.remove_file("_image.png", f'{dir_utils.get_temp_med_dir()}/{dir_name}') dprint(f"Downloaded image from: {img_url}")
def skipto(skip_val): if GS.audio_inst is not None: if not GS.audio_dni[0]: GS.audio_dni = (True, YoutubeHelper.yt_metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]) else: if GS.audio_dni[1] != YoutubeHelper.yt_metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]: rprint( f'An audio plugin is using the audio thread with no interruption mode enabled. [{GS.audio_dni[1]}]') GS.gui_service.quick_gui( "An audio plugin is using the audio thread with no interruption mode enabled.", text_type='header', box_align='left') return if YoutubeHelper.queue_instance.is_empty(): GS.gui_service.quick_gui( "The youtube queue is empty, so I can't skip tracks.", text_type='header', box_align='left') return if skip_val > YoutubeHelper.queue_instance.size() - 1: GS.gui_service.quick_gui( f"You can't skip beyond the length of the current queue.", text_type='header', box_align='left') return if skip_val < 1: next_track() return GS.gui_service.quick_gui( f"Skipping to track {skip_val} in the queue.", text_type='header', box_align='left') for i in range(skip_val): YoutubeHelper.queue_instance.pop() GS.log_service.info("The youtube audio queue skipped tracks.") dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/youtube') stop_audio() GS.audio_dni = (True, YoutubeHelper.yt_metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]) download_next() play_audio() return
def create_new_template(plugin_name: str): formatted_name = plugin_name.strip().replace(" ", "_") dir_utils.make_directory(f'{dir_utils.get_main_dir()}/user_generated/plugins/{formatted_name}') dir_utils.clear_directory(f'{dir_utils.get_main_dir()}/user_generated/plugins/{formatted_name}') with open( f'{dir_utils.get_main_dir()}/user_generated/plugins/{formatted_name}/{formatted_name.lower()}.py', 'w+') as f: f.write(py_template) with open( f'{dir_utils.get_main_dir()}/user_generated/plugins/{formatted_name}/help.html', 'w+') as f: f.write(help_template) with open( f'{dir_utils.get_main_dir()}/user_generated/plugins/{formatted_name}/metadata.ini', 'w+') as f: f.write(meta_template) with open( f'{dir_utils.get_main_dir()}/user_generated/plugins/{formatted_name}/privileges.csv', 'w+') as f: f.write(priv_template)
def download_image_requests_to_dir(img_url, dir_name): dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/{dir_name}') img_ext = img_url.rsplit('.', 1)[1] s = requests.Session() r = s.get(img_url) if r.status_code == 200: with open( f"{dir_utils.get_temp_med_dir()}/{dir_name}/_image.{img_ext}", 'wb') as f: r.raw.decode_content = True shutil.copyfileobj(r.raw, f) dprint(f"Downloaded image from: {img_url}") else: dprint(f"{r.status_code} Error! - {img_url}") if img_ext == 'png': dprint(f"Fixing image to force jpg conversion: {img_url}") img_fix = Image.open( f"{dir_utils.get_temp_med_dir()}/{dir_name}/_image.{img_ext}") img_fix.convert('RGB').save( f"{dir_utils.get_temp_med_dir()}/{dir_name}/_image.jpg") dir_utils.remove_file("_image.png", f'{dir_utils.get_temp_med_dir()}/{dir_name}') dprint(f"Downloaded image from: {img_url}")
def download_image_requests_to_dir(img_url, dir_name, img_name='_image', force_jpg=True): dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/{dir_name}') img_ext = img_url.rsplit('.', 1)[1] s = requests.Session() r = s.get(img_url) if r.status_code == 200: with open( f"{dir_utils.get_temp_med_dir()}/{dir_name}/{img_name}.{img_ext}", 'wb') as f: r.raw.decode_content = True shutil.copyfileobj(r.raw, f) log(INFO, INFO_IMG_DOWNLOADED, origin=L_GENERAL, print_mode=PrintMode.VERBOSE_PRINT.value) else: log(ERROR, f"ERROR: Encountered a Requests Module error while trying to download an image - {r.status_code} - {img_url}", origin=L_GENERAL, error_type=GEN_PROCESS_ERR, print_mode=PrintMode.VERBOSE_PRINT.value) if img_ext == 'png' and force_jpg: log(WARNING, WARN_IMG_INCORRECT_FORMAT, origin=L_GENERAL, error_type=WARN_FIXED_IMG_FORMAT, print_mode=PrintMode.VERBOSE_PRINT.value) img_fix = Image.open( f"{dir_utils.get_temp_med_dir()}/{dir_name}/{img_name}.{img_ext}") img_fix.convert('RGB').save( f"{dir_utils.get_temp_med_dir()}/{dir_name}/{img_name}.jpg") dir_utils.remove_file(f"{img_name}.png", f'{dir_utils.get_temp_med_dir()}/{dir_name}')
def on_skip(): if gs.vlc_interface.status.get_track().track_type == TrackType.STREAM: # Clear the thumbnails since the queue order has shifted. dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/{settings.plugin_name}')
if args.quiet_mode: global_settings.quiet_mode = True if args.safe_mode: global_settings.safe_mode = True elif args.verbose_mode: global_settings.verbose_mode = True if global_settings.verbose_mode and global_settings.quiet_mode: raise SysArgError( "It looks like both verbose mode and quiet mode are enabled.\n" "Only one or the other can be used!") if not path.exists(f'{dir_utils.get_main_dir()}/cfg/'): dir_utils.make_directory(f'{dir_utils.get_main_dir()}/cfg/') if args.force_defaults: dir_utils.clear_directory(f'{dir_utils.get_main_dir()}/cfg/') if not path.exists(f'{dir_utils.get_main_dir()}/cfg/config.ini'): copy(f'{dir_utils.get_main_dir()}/templates/config_template.ini', f'{dir_utils.get_main_dir()}/cfg/config.ini') if not path.exists(f'{dir_utils.get_main_dir()}/cfg/global_aliases.csv'): copy(f'{dir_utils.get_main_dir()}/templates/aliases_template.csv', f'{dir_utils.get_main_dir()}/cfg/global_aliases.csv') if not path.exists(f'{dir_utils.get_main_dir()}/cfg/plugins/'): dir_utils.make_directory(f'{dir_utils.get_main_dir()}/cfg/plugins/') global_settings.cfg = configparser.ConfigParser() global_settings.cfg.read(f'{dir_utils.get_main_dir()}/cfg/config.ini') global_settings.web_cfg = configparser.ConfigParser() if path.exists( f'{dir_utils.get_core_plugin_dir()}/web_server/metadata.ini'):
def process(self, text): message = text.message.strip() message_parse = message[1:].split(' ', 1) command = message_parse[0] if command == "song": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return if YH.current_song_info is not None: GS.gui_service.quick_gui_img(f"{dir_utils.get_temp_med_dir()}/youtube", f"{YH.current_song_info['img_id']}", caption=f"Now playing: {YH.current_song_info['main_title']}", format_img=True, img_size=32768) log(INFO, "Displayed current song in the youtube plugin.", origin=L_COMMAND) else: GS.gui_service.quick_gui( f"{runtime_utils.get_bot_name()}({self.plugin_name}) is not playing anything right now.", text_type='header', box_align='left') elif command == "autoplay": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return if YH.autoplay: YH.autoplay = False GS.gui_service.quick_gui( "Autoplay has been disabled.", text_type='header', box_align='left') log(INFO, "Autoplay has been disabled in the youtube plugin.", origin=L_COMMAND) else: YH.autoplay = True GS.gui_service.quick_gui( "Autoplay has been enabled.", text_type='header', box_align='left') log(INFO, "Autoplay has been enabled in the youtube plugin.", origin=L_COMMAND) elif command == "shuffle": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return if GS.audio_inst is not None: if not YH.queue_instance.is_empty(): YH.queue_instance.shuffle() YM.download_next() GS.gui_service.quick_gui( "The youtube queue has been shuffled.", text_type='header', box_align='left') log(INFO, "The youtube audio queue was shuffled.", origin=L_COMMAND) return elif command == "next": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return if not GS.audio_dni[0]: GS.audio_dni = (True, self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]) else: if GS.audio_dni[1] != self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]: rprint( f'An audio plugin is using the audio thread with no interruption mode enabled. [{GS.audio_dni[0]}|{GS.audio_dni[1]}]') GS.gui_service.quick_gui( "An audio plugin is using the audio thread with no interruption mode enabled.", text_type='header', box_align='left') return YM.next_track() elif command == "removetrack": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return if GS.audio_inst is not None: if YH.queue_instance.is_empty(): GS.gui_service.quick_gui( "The youtube queue is empty, so I can't remove tracks.", text_type='header', box_align='left') return rem_val = int(message[1:].split(' ', 1)[1]) if rem_val > YH.queue_instance.size() - 1 or rem_val < 0: GS.gui_service.quick_gui( f"You can't remove tracks beyond the length of the current queue.", text_type='header', box_align='left') return removed_item = YH.queue_instance.remove(rem_val) GS.gui_service.quick_gui( f"Removed track: [{rem_val}]-{removed_item['main_title']} from the queue.", text_type='header', box_align='left') log(INFO, f"Removed track #{rem_val} from the youtube audio queue.", origin=L_COMMAND) return elif command == "skipto": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return skip_val = int(message[1:].split(' ', 1)[1]) YM.skipto(skip_val) log(INFO, f"The youtube audio queue skipped to track #{skip_val}.", origin=L_COMMAND) elif command == "stop": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return if GS.audio_inst is not None: if not GS.audio_dni[0]: GS.audio_dni = (True, self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]) else: if GS.audio_dni[1] != self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]: rprint( f'An audio plugin is using the audio thread with no interruption mode enabled. [{GS.audio_dni[1]}]') GS.gui_service.quick_gui( "An audio plugin is using the audio thread with no interruption mode enabled.", text_type='header', box_align='left') return GS.gui_service.quick_gui( "Stopping youtube audio thread.", text_type='header', box_align='left') YH.queue_instance.clear() YM.stop_audio() dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/youtube') YH.queue_instance = qh.QueueHandler(YH.max_queue_size) log(INFO, "The youtube audio thread was stopped.", origin=L_COMMAND) return elif command == "clear": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return rprint("Clearing youtube queue.") YM.clear_queue() GS.gui_service.quick_gui( "Cleared youtube queue.", text_type='header', box_align='left') log(INFO, "The youtube queue was cleared.", origin=L_COMMAND) elif command == "volume": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return try: vol = float(message[1:].split(' ', 1)[1]) except IndexError: GS.gui_service.quick_gui( f"Current youtube volume: {YH.volume}", text_type='header', box_align='left') return if vol > 1 or vol < 0: GS.gui_service.quick_gui( "Invalid Volume Input: [0-1]", text_type='header', box_align='left') return YH.volume = vol GS.gui_service.quick_gui( f"Set volume to {YH.volume}", text_type='header', box_align='left') log(INFO, f"The youtube audio volume was changed to {YH.volume}.", origin=L_COMMAND) elif command == "youtube": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return if not GS.audio_dni[0]: GS.audio_dni = (True, self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]) else: if GS.audio_dni[1] != self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]: rprint( f'An audio plugin is using the audio thread with no interruption mode enabled. [{GS.audio_dni[1]}]') GS.gui_service.quick_gui( "An audio plugin is using the audio thread with no interruption mode enabled.", text_type='header', box_align='left') return try: search_term = message_parse[1] except IndexError: return YH.all_searches = YM.get_search_results(search_term) search_results = YM.get_choices(YH.all_searches) GS.gui_service.quick_gui( f"{search_results}\nWhich one would you like to play?", text_type='header', box_align='left', text_align='left') log(INFO, "Displayed youtube search results.", origin=L_COMMAND) YH.can_play = True elif command == "queue": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return queue_results = YM.get_queue() if queue_results is not None: cur_text = "" for i, item in enumerate(queue_results): cur_text += f"{item}" if i % 50 == 0 and i != 0: GS.gui_service.quick_gui( f"{cur_text}", text_type='header', box_align='left', text_align='left') cur_text = "" if cur_text != "": GS.gui_service.quick_gui( f"{cur_text}", text_type='header', box_align='left', text_align='left') log(INFO, "Displayed current youtube queue.", origin=L_COMMAND) else: GS.gui_service.quick_gui( "The youtube queue is empty.", text_type='header', box_align='left') elif command == "playlist": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return if len(message_parse) == 2: if not GS.audio_dni[0]: GS.audio_dni = (True, self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]) else: if GS.audio_dni[1] != self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]: rprint( f'An audio plugin is using the audio thread with no interruption mode enabled. [{GS.audio_dni[0]}|{GS.audio_dni[1]}]') GS.gui_service.quick_gui( "An audio plugin is using the audio thread with no interruption mode enabled.", text_type='header', box_align='left') return stripped_url = BeautifulSoup(message_parse[1], features='html.parser').get_text() if "youtube.com" in stripped_url or "youtu.be" in stripped_url: if YH.queue_instance.is_full(): GS.gui_service.quick_gui( "The youtube queue is full!", text_type='header', box_align='left') return all_song_data = YM.download_playlist(stripped_url) if all_song_data is None: return for i, song_data in enumerate(all_song_data): YH.queue_instance.insert(song_data) GS.gui_service.quick_gui( f'Playlist Generated:<br><a href="{stripped_url}">{stripped_url}</a>', text_type='header', box_align='left') log(INFO, f"Generated playlist: {stripped_url}", origin=L_COMMAND) if not YH.is_playing: YM.download_next() YM.play_audio() return else: GS.gui_service.quick_gui( "The given link was not identified as a youtube video link!", text_type='header', box_align='left') return elif command == "linkfront": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return if not GS.audio_dni[0]: GS.audio_dni = (True, self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]) else: if GS.audio_dni[1] != self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]: rprint( f'An audio plugin is using the audio thread with no interruption mode enabled. [{GS.audio_dni[1]}]') GS.gui_service.quick_gui( "An audio plugin is using the audio thread with no interruption mode enabled.", text_type='header', box_align='left') return if len(message_parse) == 2: stripped_url = BeautifulSoup(message_parse[1], features='html.parser').get_text() if "youtube.com" in stripped_url or "youtu.be" in stripped_url: if YH.queue_instance.is_full(): GS.gui_service.quick_gui( "The youtube queue is full!", text_type='header', box_align='left') return song_data = YM.download_song_name(stripped_url) if song_data is None: GS.gui_service.quick_gui( "ERROR: The chosen stream was either too long or a live stream.", text_type='header', box_align='left') return # song_data['main_url'] = stripped_url # self.sound_board_plugin.clear_audio_thread() if not GS.audio_dni[0]: GS.audio_dni = (True, self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]) else: if GS.audio_dni[1] != self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]: rprint( f'An audio plugin is using the audio thread with no interruption mode enabled. [{GS.audio_dni[1]}]') GS.gui_service.quick_gui( "An audio plugin is using the audio thread with no interruption mode enabled.", text_type='header', box_align='left') return YH.queue_instance.insert_priority(song_data) GS.gui_service.quick_gui( f"Added to front of queue: {stripped_url}", text_type='header', box_align='left') GS.log_service.info("Direct link added to the front of the youtube queue.") if not YH.is_playing: YM.download_next() YM.play_audio() else: GS.gui_service.quick_gui( "The given link was not identified as a youtube video link!", text_type='header', box_align='left') elif command == "link": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return if not GS.audio_dni[0]: GS.audio_dni = (True, self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]) else: if GS.audio_dni[1] != self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]: rprint( f'An audio plugin is using the audio thread with no interruption mode enabled. [{GS.audio_dni[1]}]') GS.gui_service.quick_gui( "An audio plugin is using the audio thread with no interruption mode enabled.", text_type='header', box_align='left') return if len(message_parse) == 2: stripped_url = BeautifulSoup(message_parse[1], features='html.parser').get_text() if "youtube.com" in stripped_url or "youtu.be" in stripped_url: if YH.queue_instance.is_full(): GS.gui_service.quick_gui( "The youtube queue is full!", text_type='header', box_align='left') return song_data = YM.download_song_name(stripped_url) if song_data is None: GS.gui_service.quick_gui( "ERROR: The chosen stream was either too long or a live stream.", text_type='header', box_align='left') return # song_data['main_url'] = stripped_url # self.sound_board_plugin.clear_audio_thread() if not GS.audio_dni[0]: GS.audio_dni = (True, self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]) else: if GS.audio_dni[1] != self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]: rprint( f'An audio plugin is using the audio thread with no interruption mode enabled. [{GS.audio_dni[1]}]') GS.gui_service.quick_gui( "An audio plugin is using the audio thread with no interruption mode enabled.", text_type='header', box_align='left') return YH.queue_instance.insert(song_data) GS.gui_service.quick_gui( f"Added to queue: {stripped_url}", text_type='header', box_align='left') GS.log_service.info("Direct link added to youtube queue.") if not YH.is_playing: YM.download_next() YM.play_audio() else: GS.gui_service.quick_gui( "The given link was not identified as a youtube video link!", text_type='header', box_align='left') elif command == "loop": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return YH.loop_song = not YH.loop_song rprint( f'{"Enabled" if YH.loop_song is True else "Disabled"} {self.plugin_name} loop mode. {"The next track in the queue will start looping." if YH.loop_song else ""}') GS.gui_service.quick_gui( f'{"Enabled" if YH.loop_song is True else "Disabled"} {self.plugin_name} loop mode. {"The next track in the queue will start looping." if YH.loop_song else ""}', text_type='header', box_align='left') elif command == "play": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return if YH.can_play: if not GS.audio_dni[0]: GS.audio_dni = (True, self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]) else: if GS.audio_dni[1] != self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]: rprint( f'An audio plugin is using the audio thread with no interruption mode enabled. [{GS.audio_dni[1]}]') GS.gui_service.quick_gui( "An audio plugin is using the audio thread with no interruption mode enabled.", text_type='header', box_align='left') return if YH.queue_instance.is_full(): GS.gui_service.quick_gui( "The youtube queue is full!", text_type='header', box_align='left') return all_messages = message[1:].split() if len(all_messages) == 1: song_data = YM.download_song_name( "https://www.youtube.com" + YH.all_searches[0]['href']) if song_data is None: GS.gui_service.quick_gui( f"The chosen video is too long. The maximum video length is {(YH.max_track_duration / 60)} minutes", text_type='header', box_align='left') return # song_data['main_url'] = "https://www.youtube.com" + YH.all_searches[0]['href'] GS.gui_service.quick_gui( f"Automatically chosen: {YH.all_searches[0]['title']}", text_type='header', box_align='left') YH.can_play = False YH.queue_instance.insert(song_data) if not YH.is_playing: YM.download_next() YM.play_audio() elif len(all_messages) == 2: if 9 >= int(all_messages[1]) >= 0: song_data = YM.download_song_name( "https://www.youtube.com" + YH.all_searches[int(all_messages[1])]['href']) if song_data is None: GS.gui_service.quick_gui( f"The chosen video is too long. The maximum video length is {(YH.max_track_duration / 60)} minutes", text_type='header', box_align='left') return # song_data['main_url'] = "https://www.youtube.com" + YH.all_searches[int(all_messages[1])]['href'] GS.gui_service.quick_gui( f"You've chosen: {YH.all_searches[int(all_messages[1])]['title']}", text_type='header', box_align='left') YH.can_play = False else: GS.gui_service.quick_gui( "Invalid choice! Valid Range [0-9]", text_type='header', box_align='left') YH.can_play = False return YH.queue_instance.insert(song_data) if not YH.is_playing: YM.download_next() YM.play_audio() elif len(all_messages) == 3: if 9 >= int(all_messages[1]) >= 0: song_data = YM.download_song_name( "https://www.youtube.com" + YH.all_searches[int(all_messages[1])]['href']) if song_data is None: GS.gui_service.quick_gui( f"The chosen video is too long. The maximum video length is {(YH.max_track_duration / 60)} minutes", text_type='header', box_align='left') return #song_data['main_url'] = "https://www.youtube.com" + YH.all_searches[int(all_messages[1])]['href'] GS.gui_service.quick_gui( f"You've chosen: {YH.all_searches[int(all_messages[1])]['title']}", text_type='header', box_align='left') YH.can_play = False else: GS.gui_service.quick_gui( "Invalid choice! Valid Range [0-9]", text_type='header', box_align='left') YH.can_play = False return count = int(all_messages[2]) for i in range(count): YH.queue_instance.insert(song_data) if not YH.is_playing: YM.download_next() YM.play_audio() elif command == "replay": if not privileges.plugin_privilege_checker(text, command, self.plugin_name): return if GS.audio_inst is not None: if not GS.audio_dni[0]: GS.audio_dni = (True, self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]) else: if GS.audio_dni[1] != self.metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]: rprint( f'An audio plugin is using the audio thread with no interruption mode enabled. [{GS.audio_dni[1]}]') GS.gui_service.quick_gui( "An audio plugin is using the audio thread with no interruption mode enabled.", text_type='header', box_align='left') return if YH.current_song is not None and YH.current_song_info is not None: YH.queue_instance.insert_priority(YH.current_song_info) YM.stop_audio() YM.download_next() YM.play_audio() else: GS.gui_service.quick_gui( "There is no track available to replay.", text_type='header', box_align='left') return
def on_skip(): if gs.aud_interface.status.get_track().track_type == TrackType.STREAM: # Clear the thumbnails since the queue order has shifted. dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/{settings.plugin_name}') log(INFO, "Cleared the temporary media folder when skipping tracks.", origin=L_GENERAL, print_mode=PrintMode.VERBOSE_PRINT.value)
def play_audio(): GS.audio_dni = (True, YoutubeHelper.yt_metadata[C_PLUGIN_INFO][P_PLUGIN_NAME]) GS.mumble_inst.sound_output.clear_buffer() time.sleep(0.1) YoutubeHelper.current_song_info = YoutubeHelper.queue_instance.pop() if YoutubeHelper.current_song_info is None: stop_audio() return if YoutubeHelper.current_song_info['img_id'] is None: return YoutubeHelper.current_song = YoutubeHelper.current_song_info.get('main_url') stripped_url = BeautifulSoup(YoutubeHelper.current_song, features='html.parser').get_text() uri = stripped_url dprint(uri) dprint(YoutubeHelper.current_song) command = YoutubeHelper.yt_metadata[C_PLUGIN_SETTINGS][P_YT_VLC_DIR] thr = None if not YoutubeHelper.queue_instance.is_empty(): thr = threading.Thread(target=download_next) thr.start() if GS.audio_inst: GS.audio_inst.terminate() GS.audio_inst.kill() GS.audio_inst = None if GS.audio_inst is None: use_stereo = GS.cfg.getboolean(C_MAIN_SETTINGS, P_AUD_STEREO) dprint(f"USE STEREO: {use_stereo}") if use_stereo: GS.audio_inst = sp.Popen( [command, uri] + ['-I', 'dummy', f'{"--quiet" if YoutubeHelper.yt_metadata.getboolean(C_PLUGIN_SETTINGS, P_YT_VLC_QUIET, fallback=True) else ""}', '--one-instance', f'{"--no-repeat" if YoutubeHelper.loop_song is False else "--repeat"}', '--sout', '#transcode{acodec=s16le, channels=2, ' 'samplerate=48000, ab=192, threads=8}:std{access=file, ' 'mux=wav, dst=-}', 'vlc://quit'], stdout=sp.PIPE, bufsize=1024) else: GS.audio_inst = sp.Popen( [command, uri] + ['-I', 'dummy', f'{"--quiet" if YoutubeHelper.yt_metadata.getboolean(C_PLUGIN_SETTINGS, P_YT_VLC_QUIET, fallback=True) else ""}', '--one-instance', f'{"--no-repeat" if YoutubeHelper.loop_song is False else "--repeat"}', '--sout', '#transcode{acodec=s16le, channels=2, ' 'samplerate=24000, ab=192, threads=8}:std{access=file, ' 'mux=wav, dst=-}', 'vlc://quit'], stdout=sp.PIPE, bufsize=1024) # YoutubeHelper.music_thread.wait() YoutubeHelper.is_playing = True runtime_utils.unmute() try: GS.gui_service.quick_gui_img(f"{dir_utils.get_temp_med_dir()}/youtube", f"{YoutubeHelper.current_song_info['img_id']}", caption=f"Now playing: {YoutubeHelper.current_song_info['main_title']}", format_img=True, img_size=32768) except FileNotFoundError: GS.gui_service.quick_gui(f"Thumbnail Image Unavailable<br>Now playing: {YoutubeHelper.current_song_info['img_id']}", text_type='header', box_align='left') while not YoutubeHelper.exit_flag and GS.mumble_inst.isAlive(): while GS.mumble_inst.sound_output.get_buffer_size() > 0.5 and not YoutubeHelper.exit_flag: time.sleep(0.01) if GS.audio_inst: raw_music = GS.audio_inst.stdout.read(1024) if raw_music and GS.audio_inst and YoutubeHelper.is_playing: GS.mumble_inst.sound_output.add_sound(audioop.mul(raw_music, 2, YoutubeHelper.volume)) else: if not YoutubeHelper.autoplay: YoutubeHelper.is_playing = False if thr: thr.join() try: dir_utils.remove_file(f"{YoutubeHelper.current_song_info['img_id']}.jpg", f'{dir_utils.get_temp_med_dir()}/youtube') if YoutubeHelper.queue_instance.size() < 1: dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/youtube') except (FileNotFoundError, TypeError): pass download_next() return YoutubeHelper.is_playing = False if thr: thr.join() try: dir_utils.remove_file(f"{YoutubeHelper.current_song_info['img_id']}.jpg", f'{dir_utils.get_temp_med_dir()}/youtube') if YoutubeHelper.queue_instance.size() < 1: dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/youtube') except (FileNotFoundError, TypeError): pass download_next() play_audio() return else: return return
def clear_queue(): YoutubeHelper.queue_instance.clear() if not YoutubeHelper.is_playing: dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/youtube')
def quit(self): YM.stop_audio() dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/youtube') YH.exit_flag = True dprint(f"Exiting {self.plugin_name} plugin...", origin=L_SHUTDOWN) log(INFO, f"Exiting {self.plugin_name} plugin...", origin=L_SHUTDOWN)
def on_reset(): # Clear the thumbnails since the queue is cleared. dir_utils.clear_directory(f'{dir_utils.get_temp_med_dir()}/{settings.plugin_name}') settings.can_play = False settings.search_results = None