async def fetch_link(request, username): """ Fetch link from the given username :param request: The thing that sanic give us, but seems it is useless in this case. :param username: The requested username. :return: Redirection if the profile page's link has been found. """ logger.debug(request) # Stop IDEA from blaming me about unused variable if username in CACHE.keys(): logger.info('Cache hit: [ %s: %s ]' % (username, CACHE[username])) return response.redirect(CACHE[username]) name = username.split('@') if len(name) != 2: raise exceptions.InvalidUsage('Invalid username', status_code=400) host_meta = await fetch('https://' + name[1] + '/.well-known/host-meta') try: host_links = host_meta['XRD']['Link'] except TypeError: raise exceptions.InvalidUsage('Unsupported platform', status_code=400) # Get Webfinger's URL webfinger = '' if type(host_links) == list: for link in host_links: if is_webfinger(link): webfinger = link['@template'] break elif type(host_links) == OrderedDict: if is_webfinger(host_links): webfinger = host_links['@template'] else: raise exceptions.InvalidUsage('Unsupported platform', status_code=400) # Request Webfinger for user's meta user_meta = await fetch( webfinger.replace('{uri}', 'acct%3A' + username.replace('@', '%40'))) try: user_link = '' if 'aliases' in user_meta.keys(): # If the server provides aliases user_link = user_meta['aliases'][0] elif 'links' in user_meta.keys(): # Otherwise, read `links` for link in user_meta['links']: if link['rel'] == 'self' or link[ 'rel'] == 'http://webfinger.net/rel/profile-page': user_link = link['href'] else: raise exceptions.InvalidUsage('Unsupported platform', status_code=400) if user_link: logger.info('Adding to cache: [ %s: %s ], redirecting...' % (username, user_link)) CACHE[username] = user_link return response.redirect(user_link) else: raise exceptions.ServerError( 'I don\'t really know what\'s going on...', status_code=500) except Exception: raise exceptions.InvalidUsage( 'Unknown error, probably the user doesn\'t exist.', status_code=500)
def validate_length(self, value, context=None): length = len(value) if self.max_length is not None and length > self.max_length: raise exceptions.InvalidUsage(self.messages['max_length'].format( self.label, self.max_length)) if self.min_length is not None and length < self.min_length: raise exceptions.InvalidUsage(self.messages['min_length'].format( self.label, self.min_length))
def validate_range(self, value, context=None): if self.min_value is not None and value < self.min_value: raise exceptions.InvalidUsage(self.messages['number_min'].format( self.label, self.min_value)) if self.max_value is not None and value > self.max_value: raise exceptions.InvalidUsage(self.messages['number_max'].format( self.label, self.max_value)) return value
def validate_length(self, value, context=None): list_length = len(value) if value else 0 if self.min_size is not None and list_length < self.min_size: raise exceptions.InvalidUsage('{0}最少包含{1}项'.format( self.label, self.min_size)) if self.max_size is not None and list_length > self.max_size: raise exceptions.InvalidUsage('{0}最多包含{1}项'.format( self.label, self.max_size))
def from_form_data(data, serializer): result = {} for name, field in serializer.fields.items(): if name in data: if isinstance(field, serializers.ListField): values = [] for i in data[name]: i = i.strip() # 每项是json结构 if isinstance(field.field, serializers.SerializerField): try: if isinstance(i, str): values.append(json.loads(i.strip('"'))) else: values.append(field.field.to_native(i)) except Exception: raise exceptions.InvalidUsage( f'"{field.label}"的参数有误, data: {i}, data type: {type(i)}' ) # 每项是普通值, 注意处理'"ITEM"'格式的首尾"号 else: values.extend([j.strip('"') for j in i.split(',') ]) # match `?a=b,c,d&a=d` result[name] = [] for i in values: if i not in result[name]: result[name].append(i) else: result[name] = data[name][0] return result
def _to_native(self, value, context=None): if isinstance(value, datetime.datetime): return datetime_helper.get_utc_time(value) try: return datetime_helper.parse_datetime(value) except (ValueError, TypeError): raise exceptions.InvalidUsage(self.messages['parse'].format( self.label))
def _to_native(self, value, context=None): if not isinstance(value, uuid.UUID): try: value = uuid.UUID(value) except (TypeError, ValueError): raise exceptions.InvalidUsage(self.messages['convert'].format( self.label, value)) return value
async def rate(request): try: voted = VoteSet(request.json["original"], request.json["variant_A"], request.json["variant_B"]) voted_for = request.json["voted_for"] except AttributeError: raise exceptions.InvalidUsage( "Invalid request, missing some parameters") if voted not in app.ctx.image_collector.vote_sets: raise exceptions.InvalidUsage(f"{voted} is not a known image set") if voted_for not in [voted.original, voted.variant_A, voted.variant_B]: raise exceptions.InvalidUsage( f"{voted_for} is not a correct option, must be {voted.variant_A} or {voted.variant_B}" ) logger.info(f"{request.token} rated {voted} with {voted_for}") await app.ctx.database.save_update_vote(request.token, voted, voted_for) return response.empty()
def _to_native(self, value, context=None): value = self._coerce(value) data = [] for index, item in enumerate(value): try: data.append(self.field.to_native(item, context)) except exceptions.SanicException as exc: raise exceptions.InvalidUsage('{0}的第{1}值有误:{2}'.format( self.label, index + 1, exc)) return data
def _coerce(self, value): if isinstance(value, list): return value elif isinstance(value, (str, Mapping)): # unacceptable iterables pass elif isinstance(value, Sequence): return value elif isinstance(value, Iterable): return value raise exceptions.InvalidUsage('{0}应是列表'.format(self.label))
def ensure_sequence(self, value): if isinstance(value, list): return value elif isinstance(value, (str, Mapping)): # unacceptable iterables pass elif isinstance(value, Sequence): return value elif isinstance(value, Iterable): return value raise exceptions.InvalidUsage('内容应是列表')
async def disable_surveys(request): try: if request.json["disable"]: app.ctx.is_disabled = True else: app.ctx.is_disabled = False return response.json(True) except KeyError: raise exceptions.InvalidUsage( "Request must identify whether surveys are enabled or disabled")
def to_native(self, value, context=None): if value is None: return None if not isinstance(value, request.File): raise exceptions.InvalidUsage(self.messages['invalid'].format( self.label)) if not value.name: raise exceptions.InvalidUsage(self.messages['no_name'].format( self.label)) if not self.allow_empty_file and not len(value.body): raise exceptions.InvalidUsage(self.messages['empty'].format( self.label)) if self.max_length and len(value.body) > self.max_length: raise exceptions.InvalidUsage(self.messages['max_length'].format( self.label)) return value
def _to_native(self, value, context=None): if isinstance(value, str): return value if isinstance(value, bytes): try: return str(value, 'utf-8') except UnicodeError: raise exceptions.InvalidUsage(self.messages['decode'].format( self.label)) return str(value)
def to_native(self, value, context=None): try: if isinstance(value, six.binary_type): value = value.decode('utf-8') return json.loads(value) elif isinstance(value, str): return json.loads(value) else: return utils.to_native(value) except (TypeError, ValueError): raise exceptions.InvalidUsage('{0}的值不是有效的json格式')
def to_primitive(self, value, context=None): data = [] value = self._coerce(value) for index, item in enumerate(value): try: item_data = self.field.to_primitive(item, context) if item_data: data.append(item_data) except exceptions.SanicException as exc: raise exceptions.InvalidUsage('{0}的第{1}值有误:{2}'.format( self.label, index, exc)) return data
def _to_native(self, value, context=None): if isinstance(value, decimal.Decimal): return value if not isinstance(value, (str, bool)): value = value try: value = decimal.Decimal(value) except (TypeError, decimal.InvalidOperation): raise exceptions.InvalidUsage( self.messages['number_coerce'].format(self.label, value, self.number_type)) return value
async def oauth(request): if not all(arg in request.raw_args for arg in ('client_id', 'code')): raise exceptions.InvalidUsage('Required parameters missing') async with aiohttp.ClientSession() as session: await session.post(f'{config.MIRO_API_BASE_URL}/oauth/token', params=dict( grant_type='authorization_code', client_id=request.raw_args['client_id'], code=request.raw_args['code'], client_secret=config.APP_SECRET, redirect_uri=config.REDIRECT_URI, )) return response.redirect(f'{config.MIRO_BASE_URL}/app/dashboard')
async def create_comment(request, paste_id): if not request.form: raise exceptions.InvalidUsage("Post a form yo") url_id = paste_id paste_id = paste_id.upper() paste_id = baseconv.base36.to_decimal(paste_id) comment_form = forms.CommentForm(request.form) if not comment_form.validate(): raise exceptions.InvalidUsage("bad datas") lineno = comment_form.line.data async with request.app.config.DB.acquire() as conn: comment = await db.create_comment(conn, paste_id, comment_form.line.data, comment_form.contents.data) request['session'].setdefault('comments', []) request['session']['comments'].append(comment.id) url = request.app.url_for('paste.show_paste', paste_id=url_id) return response.redirect(f"{url}#L{lineno}")
async def associate_characters_route(request, character): if request.json is None or not isinstance(request.json, dict): raise exceptions.InvalidUsage("Must send JSON dictionary payload") character = character.lower() for site, tags in request.json.items(): if isinstance(tags, list): tags = ",".join(tags) request.app.scraper_queue.enqueue( "indexer.scraper.worker.do_associate_character", site, character, tags ) return response.text("", status=204)
def _to_native(self, value, context=None): if isinstance(value, str): if value in self.TRUE_VALUES: value = True elif value in self.FALSE_VALUES: value = False elif value in [0, 1]: value = bool(value) if not isinstance(value, bool): raise exceptions.InvalidUsage("{0}的值应是布尔值true或者false".format( self.label)) return value
async def index_characters_route(request, character): if request.json is None or not isinstance(request.json, list): raise exceptions.InvalidUsage("Must send JSON list payload") character = character.lower() for site in request.json: request.app.scraper_queue.enqueue( "indexer.scraper.worker.do_indexing_crawl", site, character, job_timeout="6h", ) return response.text("", status=202)
def validate(self, data, context=None): data = self.to_native(data) if data: validated_data = [] for index, item in enumerate(data): try: validated_data.append(self.child.validate(item, context)) except exceptions.SanicException as exc: raise exceptions.InvalidUsage('第{0}个值有误:{1}'.format( index + 1, exc)) data = validated_data for validator in self.validators: data = validator(data, context) return data
def validate(self, value, context=None): data = None if value: value = self._coerce(value) data = [] for index, item in enumerate(value): try: data.append(self.field.validate(item, context)) except exceptions.SanicException as exc: raise exceptions.InvalidUsage('{0}的第{1}个值有误:{2}'.format( self.label, index, exc)) for validator in self.validators: validator(data, context) return data
async def save_command(request): command_name, description, code = ( request.form.get('command'), request.form.get('description'), request.form.get('code'), ) if not (command_name and code): raise exceptions.InvalidUsage('Required fields missing') await db.set( command_name, dict( name=command_name, description=description, code=code, ), ) return response.json({'success': True})
def _to_native(self, value, context=None): if isinstance(value, bool): value = int(value) if isinstance(value, self.native_type): return value try: native_value = self.native_type(value) except (TypeError, ValueError): pass else: if self.native_type is float: # Float conversion is strict enough. return native_value if not self.strict or native_value == value: return native_value if isinstance(value, (str, numbers.Integral)): return native_value raise exceptions.InvalidUsage(self.messages['number_coerce'].format( self.label, value, self.number_type))
def validate_ID(self, value, context=None): if not IDField.ID_REGEX.match(value): raise exceptions.InvalidUsage(self.messages['ID'].format( self.label, value))
def validate_email(self, value, context=None): if not EmailField.EMAIL_REGEX.match(value): raise exceptions.InvalidUsage(self.messages['email'].format( self.label, value))
def validate_regex(self, value, context=None): if self.regex is not None and self.regex.match(value) is None: raise exceptions.InvalidUsage(self.messages['regex'].format( self.label))
def validate_phone(self, value, context=None): if not PhoneField.PHONE_REGEX.match(value): raise exceptions.InvalidUsage(self.messages['phone'].format( self.label, value))