def process_ajax(self, sub, req): try: ret = {} if sub == 'command': command = req.form['command'] if command == 'source_section': data = PlexDBHandle.library_sections( db_file=req.form['arg1']) ret['modal'] = d(data) elif command == 'target_section_id': data = PlexDBHandle.library_sections() ret['modal'] = d(data) elif command == 'target_section_location_id': logger.warning(req.form['arg1']) data = PlexDBHandle.select2( 'SELECT * FROM section_locations WHERE library_section_id = ?', (req.form['arg1'], )) ret['modal'] = d(data) elif command == 'select_source_locations': data = PlexDBHandle.select( 'SELECT * FROM section_locations', db_file=req.form['arg1']) ret['modal'] = d(data) elif command == 'select_target_locations': data = PlexDBHandle.select( 'SELECT * FROM section_locations') ret['modal'] = d(data) return jsonify(ret) except Exception as e: P.logger.error(f'Exception:{str(e)}') P.logger.error(traceback.format_exc()) return jsonify({'ret': 'danger', 'msg': str(e)})
def wait(self): #logger.warning("33333333333333333333") while True: self.section_locations = PlexDBHandle.section_location() #logger.debug(section_locations) time.sleep(10) #logger.warning(f"WAIT : {datetime.now()}") items = ModelScanItem.get_items('wait') for item in items: try: logger.debug(d(item.as_dict())) if item.status == 'ready': self.process_ready(item) if item.status == 'wait_add_not_find': self.process_add(item) except ScanException as e: logger.error(f'Known Exception :{str(e)}') except Exception as e: logger.error(f'Exception:{str(e)}') logger.error(traceback.format_exc()) finally: item.save()
def kill(self, db_item_id): import psutil try: db_item = ModelPeriodicItem.get_by_id(db_item_id) logger.debug(d(db_item.as_dict())) if db_item is not None: process = psutil.Process(int(db_item.process_pid)) logger.debug(process) logger.debug(process.name()) if process.name().find('Plex Media Scanner') != -1: for proc in process.children(recursive=True): proc.kill() process.kill() db_item.status = 'user_stop' db_item.save() ret = {'ret':'success', 'msg':'정상적으로 중지하였습니다.'} else: ret = {'ret':'success', 'msg':'Plex Media Scanner 파일이 아닙니다.'} except psutil.NoSuchProcess: ret = {'ret':'danger', 'msg':'실행중인 프로세스가 아닙니다.'} if db_item is not None: db_item.status = 'terminated' db_item.save() except Exception as e: P.logger.error(f'Exception:{str(e)}') P.logger.error(traceback.format_exc()) ret = {'ret':'danger', 'msg':str(e)} return ret
def search_album_api(cls, keyword): try: data = cls.search_api(keyword, 'album') logger.warning(d(data)) return data if code.startswith(cls.module_char + cls.site_char): code = code[2:] ret = {} ret['review'] = cls.info_review(code, None, api_return=True) ret['collection'] = cls.info_collection(code, None, api_return=True) return ret except Exception as exception: logger.error('Exception:%s', exception) logger.error(traceback.format_exc())
def enqueue(self): while True: time.sleep(10) #logger.warning(f"ENQUEUE : {datetime.now()}") items = ModelScanItem.get_items('run') #current_queue = list(self.queue.queue) #logger.warning(current_queue) for item in items: try: logger.warning(d(item.as_dict())) self.queue.put(item) item.set_status(item.status.replace('run_', 'enqueue_')) except Exception as e: #logger.error(f'Exception:{str(e)}') #logger.error(traceback.format_exc()) pass finally: item.save()
def process_ajax(self, sub, req): try: ret = {} if sub == 'command': command = req.form['command'] logger.error(f"sub : {sub} / command : {command}") if command == 'update_show_add': query = 'UPDATE metadata_items SET added_at = (SELECT max(added_at) FROM metadata_items mi WHERE mi.parent_id = metadata_items.id OR mi.parent_id IN(SELECT id FROM metadata_items mi2 WHERE mi2.parent_id = metadata_items.id)) WHERE metadata_type = 2;' result = PlexDBHandle.execute_query(query) if result: ret = {'ret': 'success', 'msg': '정상적으로 처리되었습니다.'} else: ret = {'ret': 'warning', 'msg': '실패'} elif command == 'remove_collection_count': query = f"SELECT count(*) AS cnt FROM metadata_items WHERE metadata_type = 18 AND library_section_id = {req.form['arg1']};" result = PlexDBHandle.select(query) if result is not None and len(result) > 0: ret = { 'ret': 'success', 'msg': f"{result[0]['cnt']}개의 컬렉션이 있습니다." } else: ret = {'ret': 'warning', 'msg': '실패'} elif command == 'remove_collection': query = f"DELETE FROM metadata_items WHERE metadata_type = 18 AND library_section_id = {req.form['arg1']};" result = PlexDBHandle.execute_query(query) if result: ret = {'ret': 'success', 'msg': '정상적으로 처리되었습니다.'} else: ret = {'ret': 'warning', 'msg': '실패'} elif command == 'remove_sjva_extra_count': query = f"SELECT count(*) AS cnt FROM metadata_items WHERE metadata_type = 12 AND guid LIKE 'sjva://sjva.me%';" result = PlexDBHandle.select(query) if result is not None and len(result) > 0: ret = { 'ret': 'success', 'msg': f"{result[0]['cnt']}개의 부가영상이 있습니다." } else: ret = {'ret': 'warning', 'msg': '실패'} elif command == 'remove_sjva_extra': query = f"DELETE FROM metadata_items WHERE metadata_type = 12 AND guid LIKE 'sjva://sjva.me%';" result = PlexDBHandle.execute_query(query) if result: ret = {'ret': 'success', 'msg': '정상적으로 처리되었습니다.'} else: ret = {'ret': 'warning', 'msg': '실패'} elif command == 'update_sjva_extra': query = f"DELETE FROM metadata_items WHERE metadata_type = 12 AND (guid LIKE 'sjva://sjva.me/wavve_movie%' OR guid LIKE 'sjva://sjva.me/redirect.m3u8/tving%' OR guid LIKE '%=ooo5298ooo%');\n" query += f'UPDATE metadata_items SET guid = REPLACE(REPLACE(guid, "http://localhost:9999", "{SystemModelSetting.get("ddns")}"), "apikey=0123456789", "apikey={SystemModelSetting.get("auth_apikey")}") WHERE metadata_type = 12 AND guid LIKE "sjva://sjva.me%" AND guid LIKE "%http://localhost:9999%";' result = PlexDBHandle.execute_query(query) if result: ret = {'ret': 'success', 'msg': '정상적으로 처리되었습니다.'} else: ret = {'ret': 'warning', 'msg': '실패'} elif command == 'library_location_source': ModelSetting.set( f'{self.parent.name}_{self.name}_library_location_source', req.form['arg1']) query = f'SELECT count(*) AS cnt FROM section_locations WHERE root_path LIKE "{req.form["arg1"]}%";' result = PlexDBHandle.select(query) msg = f"섹션폴더 (section_locations) : {result[0]['cnt']}<br>" query = f'SELECT count(*) AS cnt FROM media_parts WHERE file LIKE "{req.form["arg1"]}%";' result = PlexDBHandle.select(query) msg += f"영상파일 (media_parts) : {result[0]['cnt']}<br>" query = f'SELECT count(*) AS cnt FROM media_streams WHERE url LIKE "file://{req.form["arg1"]}%";' result = PlexDBHandle.select(query) msg += f"자막 (media_streams) : {result[0]['cnt']}" ret = {'ret': 'success', 'msg': msg} elif command == 'library_location_target': ModelSetting.set( f'{self.parent.name}_{self.name}_library_location_source', req.form['arg1']) ModelSetting.set( f'{self.parent.name}_{self.name}_library_location_target', req.form['arg2']) query = f'UPDATE section_locations SET root_path = REPLACE(root_path, "{req.form["arg1"]}", "{req.form["arg2"]}");' query += f'UPDATE media_parts SET file = REPLACE(file, "{req.form["arg1"]}", "{req.form["arg2"]}");' query += f'UPDATE media_streams SET url = REPLACE(url, "{req.form["arg1"]}", "{req.form["arg2"]}");' result = PlexDBHandle.execute_query(query) if result: ret = {'ret': 'success', 'msg': '정상적으로 처리되었습니다.'} else: ret = {'ret': 'warning', 'msg': '실패'} elif command == 'duplicate_list': query = f"select metadata_items.id as meta_id, metadata_items.media_item_count, media_items.id as media_id, media_parts.id as media_parts_id, media_parts.file from media_items, metadata_items, media_parts, (select media_parts.file as file, min(media_items.id) as media_id, count(*) as cnt from media_items, metadata_items, media_parts where media_items.metadata_item_id = metadata_items.id and media_parts.media_item_id = media_items.id and metadata_items.media_item_count > 1 and media_parts.file != '' group by media_parts.file having cnt > 1) as ttt where media_items.metadata_item_id = metadata_items.id and media_parts.media_item_id = media_items.id and metadata_items.media_item_count > 1 and media_parts.file != '' and media_parts.file = ttt.file order by meta_id, media_id, media_parts_id;" data = PlexDBHandle.select(query) ret['modal'] = json.dumps(data, indent=4, ensure_ascii=False) elif command == 'duplicate_remove': query = f"select metadata_items.id as meta_id, metadata_items.media_item_count, media_items.id as media_id, media_parts.id as media_parts_id, media_parts.file from media_items, metadata_items, media_parts, (select media_parts.file as file, min(media_items.id) as media_id, count(*) as cnt from media_items, metadata_items, media_parts where media_items.metadata_item_id = metadata_items.id and media_parts.media_item_id = media_items.id and metadata_items.media_item_count > 1 and media_parts.file != '' group by media_parts.file having cnt > 1) as ttt where media_items.metadata_item_id = metadata_items.id and media_parts.media_item_id = media_items.id and metadata_items.media_item_count > 1 and media_parts.file != '' and media_parts.file = ttt.file order by meta_id, media_id, media_parts_id;" data = PlexDBHandle.select(query) prev = None filelist = [] query = '' def delete_medie(meta_id, media_id): tmp = f"DELETE FROM media_streams WHERE media_item_id = {media_id};\n" tmp += f"DELETE FROM media_parts WHERE media_item_id = {media_id};\n" tmp += f"DELETE FROM media_items WHERE id = {media_id};\n" tmp += f"UPDATE metadata_items SET media_item_count = (SELECT COUNT(*) FROM media_items WHERE metadata_item_id = {meta_id}) WHERE id = {meta_id};\n" return tmp def delete_part(part_id): tmp = f"DELETE FROM media_streams WHERE media_part_id = {part_id};\n" tmp += f"DELETE FROM media_parts WHERE id = {part_id};\n" return tmp for idx, current in enumerate(data): try: if prev is None: continue if current['meta_id'] != prev[ 'meta_id'] and current['file'] in filelist: logger.warning(d(current)) pass if current['meta_id'] == prev[ 'meta_id'] and current['file'] == prev[ 'file']: if current['media_id'] != prev['media_id']: query += delete_medie( current['meta_id'], current['media_id']) elif current['media_parts_id'] != prev[ 'media_parts_id']: query += delete_part( current['media_parts_id']) finally: if current['file'] not in filelist: filelist.append(current['file']) prev = current if query != '': logger.warning(query) result = PlexDBHandle.execute_query(query) if result: ret = {'ret': 'success', 'msg': '정상적으로 처리되었습니다.'} else: ret = {'ret': 'warning', 'msg': '실패'} else: ret = {'ret': 'success', 'msg': '처리할 내용이 없습니다.'} elif command == 'equal_file_equal_meta': query = f"""select media_parts.file, replace(media_parts.file, rtrim(media_parts.file, replace(media_parts.file, '/', '')), '') AS filename from media_parts, metadata_items, media_items, (SELECT metadata_items.id as id, replace(media_parts.file, rtrim(media_parts.file, replace(media_parts.file, '/', '')), '') AS filename, count(*) AS cnt FROM metadata_items, media_items, media_parts WHERE metadata_items.id = media_items.metadata_item_id AND media_items.id = media_parts.media_item_id AND metadata_items.library_section_id = 18 GROUP BY filename HAVING cnt > 1 ORDER BY file) AS tmp where metadata_items.id = media_items.metadata_item_id AND media_items.id = media_parts.media_item_id AND metadata_items.library_section_id = {req.form['arg1']} and media_parts.file != '' and filename = tmp.filename and metadata_items.id = tmp.id order by file""" #logger.error(query) data = PlexDBHandle.select(query) ret['modal'] = json.dumps(data, indent=4, ensure_ascii=False) elif command == 'empty_episode_process': section_id = req.form['arg1'] #P.logic.get_module('base').task_interface('empty_episode_process', (section_id,)) #ret = {'ret':'success', 'msg':'시작합니다.'} #query = f"""UPDATE metadata_items as A SET user_thumb_url = (SELECT user_art_url FROM metadata_items as B WHERE id in (SELECT parent_id FROM metadata_items WHERE A.id = b.parent_id AND library_section_id = {section_id} AND (user_thumb_url = '' or user_thumb_url LIKE 'media%'))) WHERE library_section_id = {section_id} AND (user_thumb_url = '' or user_thumb_url LIKE 'media%');""" # null로 세팅하면 부모것을 사용함 query = f"""UPDATE metadata_items as A SET user_thumb_url = (SELECT user_art_url FROM metadata_items WHERE id in (SELECT parent_id FROM metadata_items as B WHERE id in (SELECT parent_id FROM metadata_items WHERE A.id = b.parent_id AND library_section_id = {section_id} AND (user_thumb_url = '' or user_thumb_url LIKE 'media%')))) WHERE library_section_id = {section_id} AND (user_thumb_url = '' or user_thumb_url LIKE 'media%')""" result = PlexDBHandle.execute_query(query) if result: ret = {'ret': 'success', 'msg': '정상적으로 처리되었습니다.'} else: ret = {'ret': 'warning', 'msg': '실패'} elif command == 'remove_trash': section_id = req.form['arg1'] query = f"""UPDATE metadata_items SET deleted_at = null WHERE deleted_at is not null AND library_section_id = {section_id}; UPDATE media_items SET deleted_at = null WHERE deleted_at is not null AND library_section_id = {section_id}; UPDATE media_parts SET deleted_at = null WHERE deleted_at is not null AND media_item_id in (SELECT id FROM media_itmes WHERE library_section_id = {section_id});""" result = PlexDBHandle.execute_query(query) logger.error(result) if result: ret = {'ret': 'success', 'msg': '정상적으로 처리되었습니다.'} else: ret = {'ret': 'warning', 'msg': '실패'} elif command == 'vacuum': P.logic.get_module('base').task_interface( 'size', (ModelSetting.get('base_path_db'), )) query = f"""VACUUM;""" result = PlexDBHandle.execute_query(query) logger.error(result) #result = True if result: ret = {'ret': 'success', 'msg': '처리중입니다.'} else: ret = {'ret': 'warning', 'msg': '실패'} P.logic.get_module('base').task_interface( 'size', (ModelSetting.get('base_path_db'), )) return jsonify(ret) except Exception as e: P.logger.error(f'Exception:{str(e)}') P.logger.error(traceback.format_exc()) return jsonify({'ret': 'danger', 'msg': str(e)})
def task_interface2(self, command, *args): logger.warning(command) if command == 'size' or command == 'size_ret': func = Task.get_size elif command == 'backup': func = Task.backup elif command == 'clear' or command == 'clear_ret': func = Task.clear elif command == 'empty_episode_process': func = Task.empty_episode_process #ret = func(*args) if app.config['config']['use_celery']: result = func.apply_async(args) ret = result.get() else: ret = func(*args) if command == 'size': #noti_data = {'type':'info', 'msg' : f"경로 : {ret['target']}<br>크기 : {ret['sizeh']}"} #socketio.emit("notify", noti_data, namespace='/framework', broadcast=True) modal_data = { 'title': 'Size', 'data': f"경로 : {ret['target']}\n크기 : {ret['sizeh']}", } logger.debug(d(modal_data)) socketio.emit("modal", modal_data, namespace='/framework', broadcast=True) elif command == 'size_ret': return ret elif command == 'backup': if ret['ret'] == 'success': noti_data = { 'type': 'info', 'msg': f"경로 : {ret['target']}<br>복사하였습니다." } else: noti_data = { 'type': 'danger', 'msg': f"백업에 실패하였습니다.<br>{ret['log']}" } socketio.emit("notify", noti_data, namespace='/framework', broadcast=True) elif command == 'clear': noti_data = { 'type': 'info', 'msg': f"경로 : {ret['target']}<br>크기 : {ret['sizeh']}" } socketio.emit("notify", noti_data, namespace='/framework', broadcast=True) elif command == 'clear_ret': return ret elif command == 'empty_episode_process': noti_data = {'type': 'info', 'msg': f"썸네일 처리 완료"} return
def process_ajax(self, sub, req): try: ret = {} if sub == 'command': command = req.form['command'] if command == 'size': #if req.form['arg1'] in ['plex_data', 'plex_db']: path = req.form['arg2'] self.task_interface('size', (path, )) ret = { 'ret': 'success', 'msg': '명령을 전달하였습니다. 잠시 후 결과 알림을 확인하세요.' } elif command == 'execute': if req.form['arg1'] == 'scanner': data = ToolSubprocess.execute_command_return( [req.form['arg2']]) data = data.replace('\n', '<br>').lstrip('"').rstrip('"') ret['modal'] = data elif req.form['arg1'] == 'sqlite': data = [] data.append(f"SQLite 버전") data.append( f" - {ToolSubprocess.execute_command_return([req.form['arg2'], '-version'])}" ) data.append("") data.append(f"Plex Media Server 버전") data.append( f" - {ToolSubprocess.execute_command_return([req.form['arg2'], '--version'])}" ) data = '<br>'.join(data) ret['modal'] = data elif command == 'backup': if req.form['arg1'] == 'plex_db': self.task_interface('backup', (req.form['arg2'], )) ret = { 'ret': 'success', 'msg': '명령을 전달하였습니다. 잠시 후 결과 알림을 확인하세요.' } elif command == 'db': if req.form['arg1'] == 'library_sections': data = PlexDBHandle.library_sections(req.form['arg2']) ret['modal'] = json.dumps(data, indent=4, ensure_ascii=False) elif command == 'clear': if req.form['arg1'] == 'plex_phototranscode': path = req.form['arg2'] self.task_interface('clear', (path, )) ret = { 'ret': 'success', 'msg': '명령을 전달하였습니다. 잠시 후 결과 알림을 확인하세요.' } elif command == 'system_agents': data = PlexWebHandle.system_agents(url=req.form['arg1'], token=req.form['arg2']) data = json.loads(json.dumps(xmltodict.parse(data))) ret['modal'] = json.dumps(data, indent=4, ensure_ascii=False) elif command == 'version': url = req.form['arg1'] token = req.form['arg2'] msg = f"SJVA.bundle : {PlexWebHandle.get_sjva_version(url=url, token=token)}<br>SjvaAgent : {PlexWebHandle.get_sjva_agent_version(url=url, token=token)}<br>" regex = re.compile("VERSION\s=\s'(?P<version>.*?)'") text = requests.get( 'https://raw.githubusercontent.com/soju6jan/SJVA.bundle/master/SJVA.bundle/Contents/Code/version.py' ).text match = regex.search(text) if match: msg += u'SJVA.bundle (최신) : ' + match.group('version') text = requests.get( 'https://raw.githubusercontent.com/soju6jan/SjvaAgent.bundle/main/Contents/Code/version.py' ).text match = regex.search(text) if match: msg += u'<br>SjvaAgent (최신) : ' + match.group( 'version') return jsonify({'ret': 'success', 'msg': msg}) elif command == 'make_sql': self.make_sql() elif sub == 'plex_folder_test': program_path = req.form['program_path'] data_path = req.form['data_path'] if os.path.exists(program_path) == False: ret = {'ret': 'fail', 'msg': '데이터 폴더가 없습니다.'} elif os.path.exists(data_path) == False: ret = {'ret': 'fail', 'msg': '프로그램 폴더가 없습니다.'} else: ret['data'] = {} ret['data']['bin_scanner'] = os.path.join( program_path, 'Plex Media Scanner') ret['data']['bin_sqlite'] = os.path.join( program_path, 'Plex SQLite') ret['data']['path_db'] = os.path.join( data_path, 'Plug-in Support', 'Databases', 'com.plexapp.plugins.library.db') ret['data']['path_metadata'] = os.path.join( data_path, 'Metadata') ret['data']['path_media'] = os.path.join( data_path, 'Media') ret['data']['path_phototranscoder'] = os.path.join( data_path, 'Cache', 'PhotoTranscoder') if platform.system() == 'Windows': ret['data']['bin_scanner'] += '.exe' ret['data']['bin_sqlite'] += '.exe' ret['data']['token'] = ModelSetting.get( f'{name}_token') else: xml_string = ToolBaseFile.read( os.path.join(data_path, 'Preferences.xml')) result = xmltodict.parse(xml_string) prefs = json.loads(json.dumps(result)) logger.warning(d(prefs)) ret['data']['token'] = prefs['Preferences'][ '@PlexOnlineToken'] ret['data']['machine'] = prefs['Preferences'][ '@ProcessedMachineIdentifier'] for key, value in ret['data'].items(): if key not in ['token', 'machine']: if os.path.exists(value) == False: ret = { 'ret': 'fail', 'msg': '올바른 경로가 아닙니다.<br>' + value } return jsonify(ret) ret['ret'] = 'success' ret['msg'] = '설정을 저장하세요.' return jsonify(ret) except Exception as e: P.logger.error(f'Exception:{str(e)}') P.logger.error(traceback.format_exc()) return jsonify({'ret': 'danger', 'msg': str(e)})
def on_closed(self, event): logger.error('on_closed') logger.warning(d(event))
def on_modified(self, event): logger.error('on_modified') logger.warning(d(event))
def on_deleted(self, event): #<DirDeletedEvent: event_type=deleted, src_path='/mnt/gds/VOD/1.방송중/드라마/aaa', is_directory=True> logger.error('on_deleted') logger.warning(d(event))