def directory(lib_id, dir_id): ''' 这里处理分页 入参为: items_per_page:30, page:1 返回: 总数 ''' def toInt(val, default): try: return int(val) except: return default items_per_page = toInt(request.args.get("items_per_page", "30"), 30) page = toInt(request.args.get("page", "1"), 1) if dir_id == 0: result = { 'library': get_library(lib_id), 'dir': [], 'items': sub_items(lib_id, dir_id, items_per_page, page), 'item_count': sub_item_count(lib_id, dir_id), 'parents': [] } return json_return(result) return json_return({ 'library': get_library(lib_id), 'dir': get_dir(lib_id, dir_id), 'items': sub_items(lib_id, dir_id, items_per_page, page), 'item_count': sub_item_count(lib_id, dir_id), 'parents': get_parent(lib_id, dir_id) })
def random_item(): count = int(request.args.get("count", "12")) library = int(request.args.get("library", "0")) item_type = request.args.get("item_type", "dir") if item_type not in ('file', 'dir'): return json_return({ 'message': f"error request for item_type:{item_type}" }) file_type = request.args.get("file_type", None) if file_type is not None: if file_type not in ('photo', 'video'): return json_return({ 'message': f"error request for file_type:{file_type}" }) # 最近新增,如果定义了,根据id逆序排列(不能根据文件更新时间,新增文件可能是时间非常久之前的文件) new_add = request.args.get("new_add", None) if new_add: new_add = int(new_add) with Database() as db: sql = f"select id,name,cover,path,library_id,item_type,version,parent from item where item_type='{item_type}'" if library: sql += f" and library_id={library}" if file_type: sql += f" and file_type='{file_type}'" if new_add: sql = f"select * from ( {sql} order by id desc limit {new_add}) x order by random() limit {count}" else: sql+=f" order by random() limit {count}" return json_return( db.select(sql) )
def library_list(): if request.method == 'PUT': data = json.loads(request.get_data().decode("utf8")) Library.add(data['name'], data['path'], data['lib_type'], '', '', '') return json_return({'message': "添加成功"}) full = request.args.get("full", "false") == 'true' with Database() as db: rows = db.select( "select id,name,lib_type,dir,status,version from library order by id", dict_result=True) if not full: return json_return(rows) result = { row['id']: { 'id': row['id'], 'name': row['name'], 'lib_type': row['lib_type'], 'dir': row['dir'], 'status': row['status'], 'version': row['version'], 'count': 0, 'next_count': 0 } for row in rows } item_sql = "select library_id,version,count(1) c from item group by library_id,version" item_rows = db.select(item_sql, dict_result=True) for row in item_rows: if row['version'] == result[row['library_id']]['version']: result[row['library_id']]['count'] = row['c'] else: result[row['library_id']]['next_count'] = row['c'] return json_return([item for item in result.values()])
def changeAuth(): data = request.get_data() json_data = json.loads(data.decode('utf8')) username = json_data['username'] password = json_data['password'] new_username = json_data.get('new_username', None) new_password = json_data.get('new_password', None) try: if User.change(username, password, new_username, new_password): return json_return( { 'message': "修改用户成功" } ) else: return json_return( { 'message': "用户密码填写错误" } ) except Exception as e: return json_return( { 'message': str(e) } )
def login(): data = request.get_data() print((data, )) json_data = json.loads(data.decode('utf8')) username = json_data['username'] password = json_data['password'] if User.login(username, password): return json_return({'token': get_password(username, password)}) else: return json_return({'token': None})
def library(lib_id): if request.method == 'DELETE': Library.drop(lib_id) return json_return({'message': "删除成功"}) if request.method == 'POST': data = json.loads(request.data.decode("utf8")) Library.changeName(lib_id, data['name']) return json_return({'message': "修改名称成功"}) return json_return({ 'library': get_library(lib_id), 'dirs': sub_items(lib_id, 0) })
def web_file(file_id): # 这里处理全信息 # 包括 前一个文件,后一个文件 # 包括 当前目录信息,当前目录文件总数 # 包括 前一个目录信息,后一个目录信息 目录的前一个后一个允许跨越父目录 full = request.args.get('full', 'false') == 'true' return json_return(inner_web_file(file_id, full))
def search(): count = int(request.args.get("count", "12")) library = int(request.args.get("library", "0")) item_type = request.args.get("item_type", "dir") keyword = request.args.get("keyword", None) if keyword is None: return {"message": "必须指定搜索关键字"} keyword = '%' + keyword + '%' with Database() as db: if library: rows = db.select( "select id,name,cover,path,library_id,item_type,version,parent from item where library_id=%s and item_type=%s and name ilike %s limit %s", ( library, item_type, keyword, count, )) else: rows = db.select( "select id,name,cover,path,library_id,item_type,version,parent from item where item_type=%s and name like %s order by name limit %s", ( item_type, keyword, count, )) return json_return(rows)
def change_pos(lib_id, chapter_id): chapter = Chapter.getChapter(chapter_id) data = request.get_data() json_data = json.loads(data.decode('utf8')) dest_chapter = json_data['dest_chapter'] dest_position = json_data['dest_position'] chapter.changePositon(dest_chapter, dest_position) return json_return({ "message": f"修改节点{chapter_id} 到目标节点 {dest_chapter} 位置 {dest_position} 成果" } )
def video_ffprobe_info(video_id): video = get_file(video_id) ffprobe_command = f'{ffprobe_path} -print_format json -v error -show_entries format=duration "{video["path"]}"' result = os.popen(ffprobe_command).read() if result: video_info = json.loads(result) duration = float(video_info['format']['duration']) return json_return({ 'message': f"视频 {video['name']} {video['id']}开始转码", 'duration': duration })
def hsl_index(): # ffmpeg_cache=f'{PHOTO_CATCH}/ffmpeg' file_path = f'{PHOTO_CATCH}/ffmpeg/' + 'index.m3u8' ''' 这里可能无法找到文件,最多等待10s,如果10s后依然没有文件,返回错误 ''' for i in range(100): if os.path.exists(file_path): return send_file(file_path, cache_timeout=0) time.sleep(0.1) return json_return({'message': f"文件{file_path}没有找到,解码错误或者失败"})
def auth(): if request.path in ('/api/login'): return if request.path.startswith('/static/') or request.path.startswith( '/api/public/'): return username = request.cookies.get('username') token = request.cookies.get('token') if not User.isLogin(username, token): resp = json_return({'token': None}) resp.delete_cookie('username') resp.delete_cookie('token') return resp
def chapter_library(lib_id): if request.method == 'POST': data = request.get_data() json_data = json.loads(data.decode('utf8')) title = json_data['title'] summary = json_data['summary'] Chapter.newBook(lib_id, title, summary, None) return json_return({"message": f"新增书 {title} 成功"}) result = [] with Database() as db: for row in db.select( "select id from chapter where library_id=%s and parent=0", (lib_id, ), dict_result=True): chapter = Chapter.getChapter(row['id']) chapter.cover = None result.append({ k: v for k, v in chapter.__dict__.items() if not k.startswith('__') }) return json_return(result)
def chapter_info(lib_id, chapter_id): chapter = Chapter.getChapter(chapter_id) if chapter is None: return not_found("没有找到章节") if request.method == 'PUT': data = request.get_data() json_data = json.loads(data.decode('utf8')) current_update_id = chapter.update_id for name in ('title', 'summary', 'note', 'status', 'chapter_type', 'context', 'update_id'): if name in json_data: if json_data[name]: chapter.__dict__[name] = json_data[name] ''' 注意,这里为了防止客户端服务端时间不一,响应时间不一的情况,导致更新乱序(比如自动保存触发的update,后发先至),chapter更新时候需要附带update id,只有update id大于当前update id的情况,才会触发章节更新 ''' if chapter.update_id > current_update_id: chapter.update() return json_return({ 'utime': chapter.utime, "message": f"修改章节 {chapter.title} 成功" }) else: return json_return({ 'utime': chapter.utime, "message": "这是一个过老的更新请求,请设置最新的update id" }) if request.method == 'POST': data = request.get_data() json_data = json.loads(data.decode('utf8')) title = json_data['title'] summary = json_data['summary'] new_chapter = chapter.newChapter(title, summary) return json_return({ "chapter": { 'id': new_chapter.id }, "message": f"新增章节 {title} 成功" }) if request.method == 'DELETE': chapter.drop() return json_return({"message": f"删除章节 {chapter.title} 成功"}) # GET full = request.args.get("full", "false") == 'true' if not full: chapter.children = chapter.getChildren() chapter.parents = chapter.getParents() return json_return(chapter.__dict__) else: chapter.children = chapter.getChildren(all=True, asList=False) chapter.parents = chapter.getParents() return json_return(chapter.__dict__)
def books_sync(lib_id): with Database() as db: status = db.select("select status from library where id=%s", (lib_id, ), dict_result=True)[0]['status'] if status == 'syncing': return {'message': "当前正在执行同步任务,无法另外启动"} db.execute("update library set status=%s where id=%s", ('syncing', lib_id)) def inner_sync_books(lib_id): Chapter.syncWordCount(lib_id) with Database() as db: db.execute("update library set status=%s where id=%s", ('synced', lib_id)) executor.submit(inner_sync_books, lib_id) return json_return({"message": "重新统计字数开始执行"})
def library_lsdir(): ''' 这里用来支持页面选择库路径 对于windows,如果列出根/目录,则返回盘符列表 可以通过选项仅选择文件或者仅选择目录 ''' data = request.get_data() json_data = json.loads(data.decode('utf8')) path = json_data['path'] show_file = json_data.get('show_file', 'true') == 'true' show_dir = json_data.get('show_dir', 'true') == 'true' result = [] for name in os.listdir(path): item = {'name': name, 'isdir': os.path.isdir(path + '/' + name)} if show_file and not item['isdir']: result.append(item) if show_dir and item['isdir']: result.append(item) return json_return(result)
def ffmpeg_hls(video_id): # global ffmpen_popen start_time = request.args.get("start", "0") start_time = float(start_time) video = get_file(video_id) ffmpeg_cache = f'{PHOTO_CATCH}/ffmpeg' ffmpeg_command = f'{ffmpeg_path} -ss {start_time} -i "{video["path"]}" -c:a aac -vcodec {ffmpeg_codec} -f hls -bsf:v h264_mp4toannexb -hls_list_size 100 -b:v 6000k -hls_time 10 "{ffmpeg_cache}/index.m3u8"' shutil.rmtree(ffmpeg_cache) os.makedirs(ffmpeg_cache) executor.submit(inner_ffmpeg, ffmpeg_command) ffprobe_command = f'{ffprobe_path} -print_format json -v error -show_entries format=duration "{video["path"]}"' result = os.popen(ffprobe_command).read() if result: video_info = json.loads(result) duration = float(video_info['format']['duration']) return json_return({ 'message': f"视频 {video['name']} {video['id']}开始转码", 'duration': duration })
def chapter_prevew(lib_id, chapter_id): chapter = Chapter.getChapter(chapter_id) return json_return({ 'context': chapter.preview() } )
def list_torrents(): bt = Client(qbittorrent_url) bt.login(qbittorrent_username, qbittorrent_password) return json_return(bt.torrents())
def library_sync(lib_id): return json_return( flush_lib(lib_id) )