def feed_query( request, hints: T.list(T.dict( id=T.feed_unionid.object, dt_updated=T.datetime.object, )).maxlen(MAX_FEED_COUNT * 10).optional, detail: FeedDetailSchema, ) -> T.dict( total=T.int.optional, size=T.int.optional, feeds=T.list(FeedSchema).maxlen(MAX_FEED_COUNT), deleted_size=T.int.optional, deleted_ids=T.list(T.feed_unionid).maxlen(MAX_FEED_COUNT), ): """Feed query, if user feed count exceed limit, only return limit feeds.""" if hints: # allow hints schema exceed feed count limit, but discard exceeded hints = hints[:MAX_FEED_COUNT] check_unionid(request, [x['id'] for x in hints]) total, feeds, deleted_ids = UnionFeed.query_by_user( user_id=request.user.id, hints=hints, detail=detail) feeds = [x.to_dict() for x in feeds] return dict( total=total, size=len(feeds), feeds=feeds, deleted_size=len(deleted_ids), deleted_ids=deleted_ids, )
def feed_query( request, hints: T.list( T.dict(id=T.feed_unionid.object, dt_updated=T.datetime.object)).optional, detail: FeedDetailSchema, ) -> T.dict( total=T.int.optional, size=T.int.optional, feeds=T.list(FeedSchema).maxlen(5000), deleted_size=T.int.optional, deleted_ids=T.list(T.feed_unionid), ): """Feed query""" if hints: check_unionid(request, [x['id'] for x in hints]) total, feeds, deleted_ids = UnionFeed.query_by_user( user_id=request.user.id, hints=hints, detail=detail) feeds = [x.to_dict() for x in feeds] return dict( total=total, size=len(feeds), feeds=feeds, deleted_size=len(deleted_ids), deleted_ids=deleted_ids, )
def feed_delete_all( request, ids: T.list(T.feed_unionid.object).maxlen(MAX_FEED_COUNT).optional, ) -> T.dict(num_deleted=T.int): check_unionid(request, ids) num_deleted = UnionFeed.delete_all(user_id=request.user.id, ids=ids) return dict(num_deleted=num_deleted)
def story_query_batch( request, storys: T.list( T.dict( feed_id=T.feed_unionid.object, offset=T.int.min(0), limit=T.int.min(1).max(10).default(1), )), detail: StoryDetailSchema, ) -> StoryResultSchema: feed_union_ids = [x['feed_id'] for x in storys] check_unionid(request, feed_union_ids) story_keys = [] for item in storys: feed_id = item['feed_id'].feed_id offset = item['offset'] for i in range(item['limit']): story_keys.append((feed_id, offset + i)) storys = UnionStory.batch_get_by_feed_offset(story_keys=story_keys, user_id=request.user.id, detail=detail) storys = [x.to_dict() for x in storys] return dict( total=len(storys), size=len(storys), storys=storys, )
def feed_set_all_readed( request, ids: T.list(T.feed_unionid.object).maxlen(MAX_FEED_COUNT).optional, ) -> T.dict(num_updated=T.int): check_unionid(request, ids) num_updated = UnionFeed.set_all_readed_by_user(user_id=request.user.id, ids=ids) return dict(num_updated=num_updated)
def feed_set_all_group( request, ids: T.list(T.feed_unionid.object).maxlen(MAX_FEED_COUNT), group: T.str.maxlen(50), ) -> T.dict(num_updated=T.int): check_unionid(request, ids) feed_ids = [x.feed_id for x in ids] num_updated = UnionFeed.set_all_group( user_id=request.user.id, feed_ids=feed_ids, group=group) return dict(num_updated=num_updated)
def feed_query_creation( request, limit: T.int.min(10).max(2000).default(500), detail: FeedDetailSchema ) -> T.dict( total=T.int.min(0), size=T.int.min(0), feed_creations=T.list(FeedCreationSchema).maxlen(2000), ): feed_creations = FeedCreation.query_by_user(request.user.id, limit=limit, detail=detail) feed_creations = [x.to_dict() for x in feed_creations] return dict( total=len(feed_creations), size=len(feed_creations), feed_creations=feed_creations, )
def feed_create( request, url: _SCHEMA_FEED_CREATE_URL ) -> T.dict( is_ready=T.bool, feed=FeedSchema.optional, feed_creation=FeedCreationSchema.optional, ): """Deprecated, use feed_import instead.""" try: feed, feed_creation = UnionFeed.create_by_url(url=url, user_id=request.user.id) except FeedExistError: return Response({'message': 'already exists'}, status=400) if feed_creation: scheduler.tell( 'worker_rss.find_feed', dict( feed_creation_id=feed_creation.id, url=feed_creation.url, )) return dict( is_ready=bool(feed), feed=feed.to_dict() if feed else None, feed_creation=feed_creation.to_dict() if feed_creation else None, )
def story_fetch_fulltext( request, feed_id: T.feed_unionid.object, offset: T.int.min(0), ) -> T.dict( feed_id=T.feed_unionid, offset=T.int.min(0), response_status=T.int, response_status_name=T.str, use_proxy=T.bool.optional, accept=T_ACCEPT.optional, story=StorySchema.optional, ): feed_unionid = feed_id check_unionid(request, feed_unionid) user_id, feed_id = feed_unionid content = dict(feed_id=feed_id, offset=offset) expire_at = int(time.time() + 60) use_proxy = None accept = None try: result = scheduler.ask('harbor_rss.sync_story_fulltext', content, expire_at=expire_at) except _TIMEOUT_ERRORS as ex: LOG.error(f'Ask harbor_rss.sync_story_fulltext timeout: {ex}') response_status = FeedResponseStatus.CONNECTION_TIMEOUT else: response_status = result['response_status'] use_proxy = result['use_proxy'] accept = result['accept'] story = None if accept != FulltextAcceptStrategy.REJECT.value: story = UnionStory.get_by_feed_offset(feed_unionid, offset, detail=True) story = story.to_dict() response_status_name = FeedResponseStatus.name_of(response_status) return dict( feed_id=feed_unionid, offset=offset, response_status=response_status, response_status_name=response_status_name, use_proxy=use_proxy, accept=accept, story=story, )
def story_query_recent( request, feed_ids: T.list(T.feed_unionid.object).optional, days: T.int.min(1).max(30).default(14), detail: StoryDetailSchema, ) -> StoryResultSchema: check_unionid(request, feed_ids) storys = UnionStory.query_recent_by_user(user_id=request.user.id, feed_unionids=feed_ids, days=days, detail=detail) storys = [x.to_dict() for x in storys] return dict( total=len(storys), size=len(storys), storys=storys, )
def feed_create(request, url: T.url.default_schema('http')) -> T.dict( is_ready=T.bool, feed=FeedSchema.optional, feed_creation=FeedCreationSchema.optional, ): try: feed, feed_creation = UnionFeed.create_by_url(url=url, user_id=request.user.id) except FeedExistError: return Response({'message': 'already exists'}, status=400) if feed_creation: scheduler.tell('worker_rss.find_feed', dict( feed_creation_id=feed_creation.id, url=feed_creation.url, )) return dict( is_ready=bool(feed), feed=feed.to_dict() if feed else None, feed_creation=feed_creation.to_dict() if feed_creation else None, )
LOG = logging.getLogger(__name__) StorySchema = T.dict( id=T.story_unionid, feed=T.dict(id=T.feed_unionid, ), offset=T.int, user=T.dict(id=T.int, ).optional, unique_id=T.str.optional, title=T.str.optional, link=T.str.optional, author=T.str.optional, image_url=T.str.optional, audio_url=T.str.optional, iframe_url=T.str.optional, has_mathjax=T.bool.optional, sentence_count=T.int.optional, dt_published=T.datetime.object.optional.invalid_to_default, dt_updated=T.datetime.object.optional, dt_created=T.datetime.object.optional, dt_synced=T.datetime.object.optional, is_watched=T.bool.default(False), dt_watched=T.datetime.object.optional, is_favorited=T.bool.default(False), dt_favorited=T.datetime.object.optional, summary=T.str.optional, content=T.str.optional, image_token=T.str.optional, ).slim StoryResultSchema = T.dict( total=T.int.optional,
FeedSchema = T.dict( id=T.feed_unionid, user=T.dict( id=T.int, ), status=T.str, url=T.url, link=T.str.optional, author=T.str.optional, icon=T.str.optional, description=T.str.optional, version=T.str.optional, title=T.str.maxlen(200).optional, group=T.str.maxlen(50).optional, warnings=T.str.optional, num_unread_storys=T.int.optional, total_storys=T.int.optional, dt_updated=T.datetime.object.optional, dt_created=T.datetime.object.optional, dt_checked=T.datetime.object.optional, dt_synced=T.datetime.object.optional, encoding=T.str.optional, etag=T.str.optional, last_modified=T.str.optional, content_hash_base64=T.str.optional, story_offset=T.int.min(0).optional, dryness=T.int.min(0).max(1000).optional, freeze_level=T.int.min(0).optional, use_proxy=T.bool.optional, response_status=T.int.optional, dt_first_story_published=T.datetime.object.optional.invalid_to_default, dt_latest_story_published=T.datetime.object.optional.invalid_to_default, ).slim
from django.contrib.auth.models import User from rest_framework.response import Response from rest_framework.authtoken.models import Token from rest_framework.permissions import AllowAny from rest_framework.exceptions import AuthenticationFailed from allauth.socialaccount.models import SocialAccount from rssant_config import CONFIG from rssant_common.hashid import HASH_ID UserSchema = T.dict( id=T.str, username=T.str, has_usable_password=T.bool.optional, avatar_url=T.str.optional, token=T.str.optional, social_accounts=T.list(T.dict( provider=T.str, avatar_url=T.str.optional, )).optional, shopant_enable=T.bool.default(False), ) UserView = RestRouter(permission_classes=[AllowAny]) def serialize_user(user): avatar_url = None social_accounts_info = [] social_accounts = list(SocialAccount.objects.filter(user=user).all()) for acc in social_accounts: if not avatar_url:
from rssant_api.models import UnionStory from rssant_api.models.story import StoryDetailSchema from .helper import check_unionid StorySchema = T.dict( id=T.story_unionid, feed=T.dict( id=T.feed_unionid, ), offset=T.int, user=T.dict( id=T.int, ).optional, unique_id=T.str.optional, title=T.str.optional, link=T.str.optional, has_mathjax=T.bool.optional, dt_published=T.datetime.object.optional.invalid_to_default, dt_updated=T.datetime.object.optional, dt_created=T.datetime.object.optional, dt_synced=T.datetime.object.optional, is_watched=T.bool.default(False), dt_watched=T.datetime.object.optional, is_favorited=T.bool.default(False), dt_favorited=T.datetime.object.optional, summary=T.str.optional, content=T.str.optional, ).remove_empty StoryResultSchema = T.dict( total=T.int.optional, size=T.int.optional,
from django_rest_validr import RestRouter, T from django.contrib import auth as django_auth from django.contrib.auth.models import User from rest_framework.response import Response from rest_framework.authtoken.models import Token from rest_framework.permissions import AllowAny from rest_framework.exceptions import AuthenticationFailed from allauth.socialaccount.models import SocialAccount UserSchema = T.dict( id=T.int, username=T.str, avatar_url=T.str.optional, token=T.str.optional, ) UserView = RestRouter(permission_classes=[AllowAny]) def serialize_user(user): try: social_account = SocialAccount.objects.get(user=user) avatar_url = social_account.get_avatar_url() except SocialAccount.DoesNotExist: avatar_url = None token, created = Token.objects.get_or_create(user=user) return dict( id=user.id, username=user.username, avatar_url=avatar_url, token=token.key,
from django_rest_validr import RestRouter, T from django.contrib import auth as django_auth from django.contrib.auth.models import User from rest_framework.response import Response from rest_framework.authtoken.models import Token from rest_framework.permissions import AllowAny from rest_framework.exceptions import AuthenticationFailed from allauth.socialaccount.models import SocialAccount UserSchema = T.dict(id=T.int, username=T.str, avatar_url=T.str.optional, token=T.str.optional, social_accounts=T.list( T.dict( provider=T.str, avatar_url=T.str.optional, )).optional) UserView = RestRouter(permission_classes=[AllowAny]) def serialize_user(user): avatar_url = None social_accounts_info = [] social_accounts = list(SocialAccount.objects.filter(user=user).all()) for acc in social_accounts: if not avatar_url: avatar_url = acc.get_avatar_url() social_accounts_info.append( dict(