def get_all_announce(self, position, offset, count, content): session = SessionManager.Session() try: if content is not None: announce_list = session.query(Announce).\ filter(Announce.content == content).\ all() else: announce_list = session.query(Announce).\ filter(Announce.position == position).\ offset(offset).\ limit(count).\ all() total = session.query(func.count(Announce.id)). \ scalar() announce_dict_list = [] for announce in announce_list: announce_dict = row2dict(announce) announce_dict_list.append(announce_dict) if position == Announce.POSITION_BANGUMI: self.__add_bangumi_info(session, announce_dict_list) return json_resp({'data': announce_dict_list, 'total': total}) finally: SessionManager.Session.remove()
def delete_episode(self, episode): session = SessionManager.Session() try: task_content = {'episode_id': str(episode.id)} video_file_list = session.query(VideoFile).\ filter(VideoFile.episode_id == episode.id).\ all() watch_progress_list = session.query(WatchProgress).filter( WatchProgress.episode_id == episode.id).all() task_content['video_file_list'] = [ row2dict(video_file) for video_file in video_file_list ] task_content['task_step'] = ['db', 'torrent', 'file_system'] task = Task(type=Task.TYPE_EPISODE_DELETE, content=json.dumps(task_content), status=Task.STATUS_IN_PROGRESS) session.add(task) session.commit() for video_file in video_file_list: session.delete(video_file) # remove watch-progress for watch_progress in watch_progress_list: session.delete(watch_progress) # remove episode session.delete(episode) self.__unshift_task_step(task_content, task, session) # remove torrent if len(task_content['video_file_list']) > 0: threads.blockingCallFromThread( reactor, download_manager.remove_torrents, task_content['video_file_list']['torrent_id'], True) self.__unshift_task_step(task_content, task, session) # remove files of episode bangumi_folder_path = '{0}/{1}'.format(self.base_path, str(episode.bangumi_id)) for torrent_file in task_content['video_file_list']: file_path = '{0}/{1}'.format(bangumi_folder_path, torrent_file['file_path']) os.remove(file_path) task_content['task_step'].pop(0) task.content = json.dumps(task_content) task.status = Task.STATUS_COMPLETE session.commit() return str(task.id) finally: SessionManager.Session.remove()
def register_web_hook(self, web_hook_dict, add_by_uid): """ register an web hook and send an initial keep alive event :param web_hook_dict: :param add_by_uid: :return: """ session = SessionManager.Session() try: web_hook = WebHook( name=web_hook_dict.get('name'), description=bleach.clean(web_hook_dict.get('description'), tags=self.ALLOWED_TAGS), url=web_hook_dict.get('url'), shared_secret=web_hook_dict.get('shared_secret'), created_by_uid=add_by_uid, permissions=web_hook_dict.get('permissions')) session.add(web_hook) session.commit() web_hook_id = str(web_hook.id) # send event via rpc rpc_request.send( 'initialize_web_hook', { 'web_hook_id': web_hook_id, 'web_hook_url': web_hook.url, 'shared_secret': web_hook.shared_secret }) return json_resp({'data': web_hook_id}) finally: SessionManager.Session.remove()
def episode_history(self, bangumi_id, episode_id, user_id, last_watch_position, percentage, is_finished): last_watch_time = datetime.now() watch_status = WatchProgress.WATCHED if is_finished else WatchProgress.WATCHING session = SessionManager.Session() try: watch_progress = session.query(WatchProgress).\ filter(WatchProgress.bangumi_id == bangumi_id).\ filter(WatchProgress.episode_id == episode_id).\ filter(WatchProgress.user_id == user_id).\ first() if watch_progress is None: watch_progress = WatchProgress( bangumi_id=bangumi_id, episode_id=episode_id, user_id=user_id, watch_status=watch_status, last_watch_position=last_watch_position, last_watch_time=last_watch_time, percentage=0) session.add(watch_progress) else: watch_progress.watch_status = watch_status watch_progress.last_watch_time = last_watch_time watch_progress.last_watch_position = last_watch_position watch_progress.percentage = percentage session.commit() return json_resp({'message': 'ok', 'status': 0}) finally: SessionManager.Session.remove()
def scan_bangumi(self): session = SessionManager.Session() try: task_list = session.query(Task).\ filter(Task.status != Task.STATUS_COMPLETE).\ filter(Task.type == Task.TYPE_BANGUMI_DELETE).\ all() bangumi_id_in_task = [] for task in task_list: content_dict = json.loads(task.content) bangumi_id_in_task.append(content_dict['bangumi_id']) latest_delete_time = datetime.now() - timedelta( minutes=self.bangumi_delete_delay) query = session.query(Bangumi) if len(bangumi_id_in_task) > 0: query = query.filter(Bangumi.id.notin_(bangumi_id_in_task)) bangumi_list = query.\ filter(Bangumi.delete_mark != None).\ filter(Bangumi.delete_mark <= latest_delete_time).\ all() return bangumi_list finally: SessionManager.Session.remove()
def on_air_bangumi(self): session = SessionManager.Session() current_day = datetime.today() start_time = datetime(current_day.year, current_day.month, 1) if current_day.month == 12: next_year = current_day.year + 1 next_month = 1 else: next_year = current_day.year next_month = current_day.month + 1 end_time = datetime(next_year, next_month, 1) try: result = session.query(distinct(Episode.bangumi_id), Bangumi).\ join(Bangumi).\ filter(Episode.airdate >= start_time).\ filter(Episode.airdate <= end_time) bangumi_list = [ row2dict(bangumi) for bangumi_id, bangumi in result ] return json_resp({'data': bangumi_list}) except Exception as error: raise error finally: SessionManager.Session.remove()
def open_session(self, app, request): sid = request.cookies.get(app.session_cookie_name) if not sid: sid = self._generate_sid() return self.session_class(sid=sid, permanent=True) signer = self._get_signer(app) if signer is None: return None try: sid_as_bytes = signer.unsign(sid) sid = sid_as_bytes.decode() except BadSignature: sid = self._generate_sid() return self.session_class(sid=sid, permanent=True) db_session = SessionManager.Session() saved_session = db_session.query(ServerSession).filter(ServerSession.session_id == sid).first() if saved_session and not saved_session.expiry and saved_session.expiry <= datetime.utcnow(): # delete expired session db_session.delete(saved_session) db_session.commit() saved_session = None if saved_session: try: val = saved_session.data data = self.serializer.loads(want_bytes(val)) return self.session_class(data, sid=sid) except: return self.session_class(sid=sid, permanent=True) return self.session_class(sid=sid, permanent=True)
def recent_update(self, days): current = datetime.now() # from one week ago start_time = current - timedelta(days=days) session = SessionManager.Session() try: result = session.query(Episode, Bangumi).\ join(Bangumi).\ filter(Episode.status == Episode.STATUS_DOWNLOADED).\ filter(Episode.update_time >= start_time).\ filter(Episode.update_time <= current).\ order_by(desc(Episode.update_time)) episode_list = [] for eps, bgm in result: episode = row2dict(eps) episode['thumbnail'] = utils.generate_thumbnail_link(eps, bgm) episode['bangumi'] = row2dict(bgm) episode['bangumi']['cover'] = utils.generate_cover_link(bgm) episode_list.append(episode) return json_resp({'data': episode_list}) except Exception as error: raise error finally: SessionManager.Session.remove()
def list_pending_delete_episode(self): try: current = datetime.now() session = SessionManager.Session() result = session.query(Episode, Bangumi).\ join(Bangumi).\ filter(Episode.delete_mark != None).\ all() eps_list = [] for episode, bangumi in result: bgm = row2dict(bangumi) eps = row2dict(episode) # noinspection PyTypeChecker delete_eta = int( (episode.delete_mark + timedelta(minutes=self.delete_delay['episode']) - current).total_seconds() / 60) eps['delete_eta'] = delete_eta eps['bangumi'] = bgm eps_list.append(eps) return json_resp({ 'data': eps_list, 'delete_delay': self.delete_delay['episode'] }) finally: SessionManager.Session.remove()
def list_pending_delete_banguimi(self): try: current = datetime.now() session = SessionManager.Session() bangumi_list = session.query(Bangumi).\ filter(Bangumi.delete_mark != None).\ all() bgm_list = [] for bangumi in bangumi_list: bgm = row2dict(bangumi) # noinspection PyTypeChecker delete_eta = int( (bangumi.delete_mark + timedelta(minutes=self.delete_delay['bangumi']) - current).total_seconds() / 60) bgm['delete_eta'] = delete_eta bgm_list.append(bgm) return json_resp({ 'data': bgm_list, 'delete_delay': self.delete_delay['bangumi'] }) finally: SessionManager.Session.remove()
def register_user(name, password, invite_code): session = SessionManager.Session() try: code = session.query(InviteCode).filter( InviteCode.code == invite_code).one() if code.used_by is not None: raise ClientError(ClientError.INVALID_INVITE_CODE) user = User(name=name, password=generate_password_hash(password), level=0) session.add(user) session.commit() code.used_by = user.id session.commit() return True except NoResultFound: raise ClientError(ClientError.INVALID_INVITE_CODE) except DataError: raise ClientError(ClientError.INVALID_INVITE_CODE) except IntegrityError: raise ClientError(ClientError.DUPLICATE_NAME) except ClientError as error: raise error except Exception as error: raise ServerError(error.message) finally: SessionManager.Session.remove()
def register_user(name, password, email, invite_code): email_patteren = re.compile( "(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)") if not email_patteren.match(email): raise ClientError(ClientError.INVALID_EMAIL) session = SessionManager.Session() try: code = session.query(InviteCode).filter( InviteCode.code == invite_code).one() if code.used_by is not None: raise ClientError(ClientError.INVALID_INVITE_CODE) user = User(name=name, password=UserCredential.get_pass_hash(password), email=email, level=0) session.add(user) session.commit() code.used_by = user.id session.commit() return True except NoResultFound: raise ClientError(ClientError.INVALID_INVITE_CODE) except DataError: raise ClientError(ClientError.INVALID_INVITE_CODE) except IntegrityError as error: if error.diag.column_name == 'name': raise ClientError(ClientError.DUPLICATE_NAME) elif error.diag.column_name == 'email': raise ClientError(ClientError.DUPLICATE_EMAIL) except ClientError as error: raise error except Exception as error: raise ServerError(error.message) finally: SessionManager.Session.remove()
def get_bangumi(self, id): try: session = SessionManager.Session() bangumi = session.query(Bangumi).options(joinedload(Bangumi.episodes)).\ filter(Bangumi.id == id).\ filter(Bangumi.delete_mark == None).\ one() episodes = [] for episode in bangumi.episodes: if episode.delete_mark is not None: continue eps = row2dict(episode) eps['thumbnail'] = utils.generate_thumbnail_link( episode, bangumi) episodes.append(eps) bangumi_dict = row2dict(bangumi) bangumi_dict['episodes'] = episodes bangumi_dict['cover'] = utils.generate_cover_link(bangumi) return json_resp({'data': bangumi_dict}) except NoResultFound: raise ClientError(ClientError.NOT_FOUND, 404) except Exception as exception: raise exception finally: SessionManager.Session.remove()
def list_episode(self, page, count, sort_field, sort_order, status): try: session = SessionManager.Session() query_object = session.query(Episode) if status is not None: query_object = query_object.filter(Episode.status == status) # count total rows total = session.query(func.count( Episode.id)).filter(Episode.status == status).scalar() else: total = session.query(func.count(Episode.id)).scalar() offset = (page - 1) * count if sort_order == 'desc': episode_list = query_object.\ order_by(desc(getattr(Episode, sort_field))).\ offset(offset).\ limit(count).\ all() else: episode_list = query_object.\ order_by(asc(getattr(Episode, sort_field))).\ offset(offset).limit(count).\ all() episode_dict_list = [row2dict(episode) for episode in episode_list] return json_resp({'data': episode_dict_list, 'total': total}) except Exception as exception: raise exception finally: SessionManager.Session.remove()
def upload_episode(self, episode_id, file): try: filename = secure_filename(file.filename) session = SessionManager.Session() (episode, bangumi) = session.query(Episode, Bangumi).\ join(Bangumi).\ filter(Episode.id == episode_id).\ one() file.save( os.path.join(self.base_path, str(episode.bangumi_id), filename)) torrent_file = None try: torrent_file = session.query(TorrentFile).filter( TorrentFile.episode_id == episode_id).one() except NoResultFound: torrent_file = TorrentFile() session.add(torrent_file) torrent_file.torrent_id = str(-1) torrent_file.episode_id = episode_id torrent_file.file_path = filename episode.update_time = datetime.now() episode.status = Episode.STATUS_DOWNLOADED session.commit() return json_resp({'msg': 'ok'}) except NoResultFound: raise ClientError(ClientError.INVALID_REQUEST) except Exception as error: raise error finally: SessionManager.Session.remove()
def list_user(self, name, count, offset): session = SessionManager.Session() try: query_object = session.query(User) if name is not None: name_pattern = '%{0}%'.format(name.encode('utf-8'), ) logger.debug(name_pattern) query_object = query_object. \ filter(User.name.like(name_pattern)) # count total rows total = session.query(func.count(User.id)). \ filter(User.name.like(name_pattern)). \ scalar() else: total = session.query(func.count(User.id)).scalar() # we now support query all method by passing count = -1 if count == -1: user_list = query_object.all() else: user_list = query_object.offset(offset).limit(count).all() user_dict_list = [] for user in user_list: user_dict_list.append({ 'id': str(user.id), 'name': user.name, 'level': user.level }) return json_resp({'data': user_dict_list, 'total': total}) finally: SessionManager.Session.remove()
def update_bangumi(self, bangumi_id, bangumi_dict): try: session = SessionManager.Session() bangumi = session.query(Bangumi).filter( Bangumi.id == bangumi_id).one() bangumi.name = bangumi_dict['name'] bangumi.name_cn = bangumi_dict['name_cn'] bangumi.summary = bangumi_dict['summary'] bangumi.eps = bangumi_dict['eps'] # bangumi.eps_regex = bangumi_dict['eps_regex'] bangumi.image = bangumi_dict['image'] bangumi.air_date = datetime.strptime(bangumi_dict['air_date'], '%Y-%m-%d') bangumi.air_weekday = bangumi_dict['air_weekday'] # bangumi.rss = bangumi_dict['rss'] if 'dmhy' in bangumi_dict: bangumi.dmhy = bangumi_dict['dmhy'] else: bangumi.dmhy = None if 'acg_rip' in bangumi_dict: bangumi.acg_rip = bangumi_dict['acg_rip'] else: bangumi.acg_rip = None bangumi.update_time = datetime.now() session.commit() return json_resp({'msg': 'ok'}) except NoResultFound: raise ClientError(ClientError.NOT_FOUND) finally: SessionManager.Session.remove()
def __query_feed(self): session = SessionManager.Session() try: return session.query(Feed).filter( Feed.torrent_file_id == None).all() finally: SessionManager.Session.remove()
def update_episode(self, episode_id, episode_dict): try: session = SessionManager.Session() episode = session.query(Episode).filter( Episode.id == episode_id).one() episode.episode_no = episode_dict.get('episode_no') episode.bgm_eps_id = episode_dict.get('bgm_eps_id') episode.name = episode_dict.get('name') episode.name_cn = episode_dict.get('name_cn') if 'airdate' in episode_dict: episode.airdate = datetime.strptime( episode_dict.get('airdate'), '%Y-%m-%d') episode.duration = episode_dict.get('duration') episode.update_time = datetime.utcnow() if 'status' in episode_dict: episode.status = episode_dict['status'] session.commit() return json_resp({'msg': 'ok'}) except NoResultFound: raise ClientError(ClientError.NOT_FOUND, 404) finally: SessionManager.Session.remove()
def update_password(self, old_pass, new_pass): from server import app, mail session = SessionManager.Session() try: user = session.query(User).filter(User.id == self.id).one() if check_password_hash(user.password, old_pass): user.password = UserCredential.get_pass_hash(new_pass) session.commit() if user.email is not None and user.email_confirmed: # send notification mail subject = '[{0}] Password Update Notification'.format( app.config['SITE_NAME']) email_content = render_template( 'update-pass-notification.html', info={ 'title': subject, 'user_name': user.name, 'site_name': app.config['SITE_NAME'] }) msg = Message(subject, recipients=[self.email], html=email_content) try: mail.send(msg) except SMTPAuthenticationError: raise ServerError('SMTP authentication failed', 500) return True else: raise ClientError(ClientError.PASSWORD_INCORRECT) except NoResultFound: raise ServerError('user not found') finally: SessionManager.Session.remove()
def update_password_with_token(new_pass, token, expiration=3600): from server import app serializer = URLSafeTimedSerializer(app.config['SECRET_KEY']) session = SessionManager.Session() try: combine_str = serializer.loads( token, salt=app.config['SECRET_PASSWORD_SALT'], max_age=expiration) email = combine_str[:-(PASSWORD_DIGEST_LENGTH + 1)] old_pass_digest = combine_str[-PASSWORD_DIGEST_LENGTH:] user = session.query(User).filter(User.email == email).one() if not user.email_confirmed: raise ClientError(ClientError.EMAIL_NOT_CONFIRMED) if old_pass_digest != UserCredential.get_password_digest( user.password): raise ClientError('invalid token') user.password = UserCredential.get_pass_hash(new_pass) session.commit() return json_resp({'message': 'ok'}) except NoResultFound: raise ClientError(ClientError.EMAIL_NOT_EXISTS, 400) finally: SessionManager.Session.remove()
def episode_detail(self, episode_id): session = SessionManager.Session() try: (episode, bangumi) = session.query(Episode, Bangumi).\ join(Bangumi).\ filter(Episode.id == episode_id).one() episode_dict = row2dict(episode) episode_dict['bangumi'] = row2dict(bangumi) episode_dict['thumbnail'] = utils.generate_thumbnail_link( episode, bangumi) if episode.status == Episode.STATUS_DOWNLOADED: episode_dict['videos'] = [] torrent_file_cur = session.query(TorrentFile).filter( TorrentFile.episode_id == episode_id) for torrent_file in torrent_file_cur: episode_dict['videos'].append( utils.generate_video_link(str(bangumi.id), torrent_file.file_path)) return json_resp(episode_dict) except NoResultFound: raise ClientError(ClientError.NOT_FOUND, 404) except Exception as error: raise error finally: SessionManager.Session.remove()
def add_web_hook_token(self, token_id, web_hook_id, user): session = SessionManager.Session() try: web_hook = session.query(WebHook).filter( WebHook.id == web_hook_id).one() web_hook_token = WebHookToken(web_hook_id=web_hook_id, user_id=user.id, token_id=token_id) session.add(web_hook_token) session.commit() method_args = { 'web_hook_id': web_hook_id, 'token_id': token_id, 'user_id': user.id, 'email': None } if web_hook.has_permission( WebHook.PERMISSION_EMAIL ) and user.email is not None and user.email_confirmed: method_args['email'] = user.email rpc_request.send('token_add', method_args) return json_resp({'message': 'ok'}) except NoResultFound: raise ClientError('web hook not existed') finally: SessionManager.Session.remove()
def update_web_hook(self, web_hook_id, web_hook_dict): """ update a web hook :param web_hook_dict: :param web_hook_id: :return: """ session = SessionManager.Session() try: web_hook = session.query(WebHook).\ filter(WebHook.id == web_hook_id).\ one() web_hook.name = web_hook_dict.get('name') web_hook.description = bleach.clean( web_hook_dict.get('description'), tags=self.ALLOWED_TAGS) web_hook.url = web_hook_dict.get('url') web_hook.status = web_hook_dict.get('status') web_hook.consecutive_failure_count = web_hook_dict.get( 'consecutive_failure_count') web_hook.permissions = web_hook_dict.get('permissions') if 'shared_secret' in web_hook_dict and web_hook_dict.get( 'shared_secret') is not None: web_hook.shared_secret = web_hook_dict.get('shared_secret') session.commit() return json_resp({'message': 'ok'}) finally: SessionManager.Session.remove()
def list_bangumi(self, page, count, sort_field, sort_order, name, user_id, bangumi_type): try: session = SessionManager.Session() query_object = session.query(Bangumi).\ options(joinedload(Bangumi.cover_image)).\ filter(Bangumi.delete_mark == None) if bangumi_type != -1: query_object = query_object.filter( Bangumi.type == bangumi_type) if name is not None: name_pattern = '%{0}%'.format(name.encode('utf-8'), ) logger.debug(name_pattern) query_object = query_object.\ filter(or_(Bangumi.name.ilike(name_pattern), Bangumi.name_cn.ilike(name_pattern))) # count total rows total = session.query(func.count(Bangumi.id)).\ filter(or_(Bangumi.name.ilike(name_pattern), Bangumi.name_cn.ilike(name_pattern))).\ scalar() else: total = session.query(func.count(Bangumi.id)).scalar() if sort_order == 'desc': query_object = query_object.\ order_by(desc(getattr(Bangumi, sort_field))) else: query_object = query_object.\ order_by(asc(getattr(Bangumi, sort_field))) if count == -1: bangumi_list = query_object.all() else: offset = (page - 1) * count bangumi_list = query_object.offset(offset).limit(count).all() bangumi_id_list = [bgm.id for bgm in bangumi_list] favorites = session.query(Favorites).\ filter(Favorites.bangumi_id.in_(bangumi_id_list)).\ filter(Favorites.user_id == user_id).\ all() bangumi_dict_list = [] for bgm in bangumi_list: bangumi = row2dict(bgm) bangumi['cover'] = utils.generate_cover_link(bgm) utils.process_bangumi_dict(bgm, bangumi) for fav in favorites: if fav.bangumi_id == bgm.id: bangumi['favorite_status'] = fav.status bangumi_dict_list.append(bangumi) return json_resp({'data': bangumi_dict_list, 'total': total}) finally: SessionManager.Session.remove()
def __update_feed(self, feed, torrent_file_id): session = SessionManager.Session() try: feed.torrent_file_id = torrent_file_id session.add(feed) session.commit() finally: SessionManager.Session.remove()
def list_task(self): try: session = SessionManager.Session() result = session.query(Task).all() task_list = [row2dict(task) for task in result] return json_resp({'data': task_list}) finally: SessionManager.Session.remove()
def update_video_files(file_list): session = SessionManager.Session() try: result = session.query(VideoFile, Episode).\ join(Episode).\ filter(VideoFile.torrent_id == torrent_id).\ filter(Episode.id == VideoFile.episode_id).\ all() for (video_file, episode) in result: if video_file.file_path is None and video_file.file_name is None: if len(file_list) == 1: # only one file file_path = file_list[0]['path'] elif len(file_list) > 1: max_size = file_list[0]['size'] main_file = file_list[0] for file in file_list: if not file['path'].endswith('.mp4'): continue if file['size'] > max_size: main_file = file file_path = main_file['path'] else: logger.warn('no file found in %s', torrent_id) continue video_file.file_path = file_path video_file.status = VideoFile.STATUS_DOWNLOADED episode.update_time = datetime.now() episode.status = Episode.STATUS_DOWNLOADED create_thumbnail(episode, file_path) update_video_meta(video_file) else: file_path_list = [file['path'] for file in file_list] for file_path in file_path_list: if video_file.file_name is not None and video_file.file_path is None and file_path.endswith( video_file.file_name): video_file.file_path = file_path video_file.status = VideoFile.STATUS_DOWNLOADED episode.update_time = datetime.now() episode.status = Episode.STATUS_DOWNLOADED create_thumbnail(episode, file_path) update_video_meta(video_file) break elif video_file.file_path is not None and file_path == video_file.file_path: video_file.status = VideoFile.STATUS_DOWNLOADED episode.update_time = datetime.now() episode.status = Episode.STATUS_DOWNLOADED create_thumbnail(episode, file_path) update_video_meta(video_file) break session.commit() except exc.DBAPIError as db_error: if db_error.connection_invalidated: session.rollback() finally: SessionManager.Session.remove()
def get(cls, id): session = SessionManager.Session() try: user = session.query(User).filter(User.id == id).one() credential = cls(user) SessionManager.Session.remove() return credential except Exception: return None
def get_web_hooks(self): session = SessionManager.Session() try: web_hook = session.query(WebHook).\ filter(WebHook.id == self.web_hook_id).\ one() return [(self.web_hook_id, web_hook.url, web_hook.shared_secret)] finally: SessionManager.Session.remove()