THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""

import sanic

import logging
from .helpers import url_validator

bp = sanic.Blueprint('API-Routes')
log = logging.getLogger(__name__)


@bp.route("/ip/redirect", methods=["GET"])
async def ip_redirect_tracker(request):
    try:
        url = request.args["url"]
    except KeyError:
        try:
            url = request.json.get("url")
        except (AttributeError, KeyError):
            error = """Please specify one or more IP Addresses under the "ip" query parameter
                (multiple or space separated) or as a json body under the "ip" (single) or
                "addresses" (array) keys."""
            return sanic.response.json({"error": error}, status=400)
Exemplo n.º 2
0
"""/api"""
import sanic
from sanic_jwt import decorators as jwtdec

from . import uid_get

root = sanic.Blueprint('attrs_api', url_prefix='')


@root.get('/attrs')
@uid_get('perms', 'location')
@jwtdec.protected()
async def serve_attrs(rqst, perms, location):
    """
    Catch-all combination of location-related attributes.
    """
    resp = {
        'types': await location.media_types(),
        'genres': await location.genres(),
        'color': location.color,
    }
    resp['names'] = {
        'perms': [
            None,  # -- line 42 --
            'Manage accounts (edit names, usernames and passwords)',
            'Manage media (add items, edit metadata)',
            'Manage roles (edit permissions and names)',
            None,  # -- line 43 --
            'Generate & view reports',
            'Return items',
        ],
Exemplo n.º 3
0
from json import dumps
from os.path import exists, join

import sanic
import sqlalchemy
from sqlalchemy.future import select

from xss_receiver import constants
from xss_receiver import system_config, publish_subscribe
from xss_receiver.constants import ALLOWED_METHODS
from xss_receiver.mailer import send_mail
from xss_receiver.models import HttpRule, HttpAccessLog
from xss_receiver.publish_subscribe import PublishMessage
from xss_receiver.utils import process_headers, random_string, fix_upper_case, write_file, filter_list, render_dynamic_template, read_file, generate_dynamic_template_globals, add_system_log, secure_filename_with_directory

index_controller = sanic.Blueprint('index_controller', __name__)


@index_controller.route('/', methods=ALLOWED_METHODS)
@index_controller.route('/<path:path>', methods=ALLOWED_METHODS)
@process_headers
async def mapping(request: sanic.Request, path=''):
    path = request.path
    result: sqlalchemy.engine.result.ChunkedIteratorResult
    result = await request.ctx.db_session.execute(
        select(HttpRule).where(HttpRule.path == path))
    rule = result.scalar()

    if rule is None:
        return sanic.response.html('', 404)
Exemplo n.º 4
0
import sanic
from sanic.log import logger
from sanic.response import json, text

from . import secrets
from .slacker import Slacker

# attach additional api routes to 'routing'
routing = sanic.Blueprint('slack-bot-extras')

# To create a new app go to https://api.slack.com/apps?new_app=1
# Manager your apps:
#     https://api.slack.com/apps
# Manage slash commands in an app:
#     https://api.slack.com/apps/:id/slash-commands
bot = Slacker(
    token=secrets.slack_api_token,
    signing_secret=secrets.slack_signing_secret,
)


# this would be called by the `/hello` slash command.
#
# the url will be <openfaas_gateway>/function/<function_name>/hello
@bot.slash_cmd("hello")
async def hello(request: sanic.request.Request):
    logger.debug(f"handling request: {request}")
    # sample form payload
    # {
    #     'token': ['...'],
    #     'team_id': ['...'],
Exemplo n.º 5
0
# -*- coding: utf-8 -*-
import spmapi.utils.tools as tools
import spmapi.schemas.formula
import sanic

bp = sanic.Blueprint(name='formulas', version=1)

formulas = spmapi.schemas.formula.Formula(many=True)


@bp.post('/formulas')
async def upload_formula(request):
    if not request.files:
        return sanic.response.json({'error': 'No files uploaded'}, status=400)

    for name, archive in request.files.items():
        await tools.upload(name=name, spmfile=archive[0])

    return sanic.response.json({'message': 'success'}, status=200)


@bp.get('/formulas')
async def list_formula(request):
    name = request.form.get('name')

    result = await tools.list_formulas(name)
    return sanic.response.json(
        {
            'message': 'success',
            'formulas': formulas.dump(result).data
        },
Exemplo n.º 6
0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging

import sanic
from sanic import response

from cnapps import exceptions

LOGGER = logging.getLogger(__name__)

REST = sanic.Blueprint("errors")


def debug_error(error):
    message = [str(x) for x in error.args]
    if not message:
        message = error.message
    LOGGER.debug("Error: %s", message)


def make_error_response(error_type, message, status_code, description=None):
    content = {
        "success": False,
        "error": {
            "type": error_type,
            "message": message,
Exemplo n.º 7
0
import sanic
from asyncpg.exceptions import UniqueViolationError
from sanic_jwt import decorators as jwtdec

from . import uid_get, rqst_get
from . import MediaType

types = sanic.Blueprint('location_media_types', url_prefix='/types')


@types.get('/')
@uid_get('location')
@jwtdec.protected()
async def get_location_media_types(rqst, location):
    """
    Serves all media types (as serialized dicts) defined on a location.
    """
    return sanic.response.json({'types': await location.media_types()}, status=200)


@types.get('/info')
@uid_get('location')
@rqst_get('name')
@jwtdec.protected()
async def get_media_type_info(rqst, location, *, name):
    """
    Serves attrs of a requested media type given its name.
    """
    mtype = await MediaType(name, location, rqst.app)
    return sanic.response.json({'type': mtype.to_dict()}, status=200)
Exemplo n.º 8
0
                {
                    'id': 42,
                    'name': 'fantasy'
                    'created_at': 1502680672,
                    'updated_at': 1502680672
                }

        Raises:
            :class:`NotFound<sanic:sanic.exceptions.NotFound>`: The media_genre
                does not exist.
        """
        async with request.app.pool.acquire() as conn:
            rows = await conn.fetch(
                """ SELECT g.id, g.name, g.created_at, g.updated_at
                    FROM ysr.genre g
                    INNER JOIN ysr.media_genre mg ON mg.gid = g.id
                    WHERE mg.mid=$1 AND mg.gid=$2 """, mid, gid)

        try:
            return sanic.response.json(dict(rows[0]))
        except IndexError:
            raise sanic.exceptions.NotFound(
                'no genre with id {} on media {}'.format(gid, mid))


media = sanic.Blueprint('media', url_prefix='/media')
media.add_route(MediaList.as_view(), '/')
media.add_route(Media.as_view(), '/<mid:int>')
media.add_route(MediaGenreList.as_view(), '/<mid:int>/genre')
media.add_route(MediaGenre.as_view(), '/<mid:int>/genre/<gid:int>')
Exemplo n.º 9
0
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging

import sanic
from sanic.response import json
from sanic_openapi import doc

from cnapps.api import commons
from cnapps import version

LOGGER = logging.getLogger(__name__)

bp = sanic.Blueprint("version", url_prefix='/version')


@bp.route("", methods=["GET"])
@doc.summary("Application version API")
@doc.produces({"version": str})
async def version_status(request):
    """Display application version.

    Returns:
        A HTTP response in JSON (application/json content-type)
    """

    LOGGER.info("Get version")
    return commons.make_webservice_response({"version": version.RELEASE})
Exemplo n.º 10
0
import sanic

bp_version1 = sanic.Blueprint('version1', url_prefix='/v1')
bp_version2 = sanic.Blueprint('version2', url_prefix='/v2')


@bp_version1.route('/generate')
async def generate(request):
    return sanic.response.text('OK from version 1')


@bp_version2.route('/generate')
async def generate(request):
    return sanic.response.text('OK from version 2')


if __name__ == '__main__':
    app = sanic.Sanic()
    app.blueprint(bp_version1)
    app.blueprint(bp_version2)

    app.run(host='0.0.0.0', port=8080)
Exemplo n.º 11
0
import sanic
from sanic_jwt import decorators as jwtdec

from . import uid_get, rqst_get
from . import MediaType

root = sanic.Blueprint('location_media_api', url_prefix='')


@root.get('/')
@uid_get('location')
@rqst_get('cont')
@jwtdec.protected()
async def all_location_items(rqst, location, *, cont):
    """
    Serves all media items, in groups of 5 (paginated according to 'cont', i.e. what
    page to continue from).
    """
    return sanic.response.json({'items': await location.items(cont=int(cont))},
                               status=200)


@root.get('/search')
@rqst_get('title', 'genre', 'media_type', 'author', 'cont')
@uid_get('location')
@jwtdec.protected()
async def search_location_media(rqst, location, *, title, genre, media_type,
                                author, cont):
    """
    Implements item search functionality, serving a list of items
    that match the given search query.
Exemplo n.º 12
0
"""/stock/buttons"""
import sanic
import sanic_jwt as jwt
from sanic_jwt import decorators as jwtdec

from . import uid_get, rqst_get
from . import Location, Role, MediaType, MediaItem, User

btn = sanic.Blueprint('button_stock', url_prefix='/buttons')

@btn.get('/main-header')
async def expose_header_buttons(rqst):
    """
    Essentially a static resource; don't think I have anything to add.
    Keeping it here, though, so I can change it ... if I ever want to.
    
    Serves header buttons (via the angular webapp's HeadButtonService)
    to display at the top of every page.
    
    Requires nothing from client, as it's static.
    """
    buttons = [{"text": 'home'}, {"text": 'help'}, {"text": 'about'}]
    # dest on home should not be necessary, but for some reason Angular
    # isn't picking up the redirect I've tried to place on the router
    # from '/home' to '/'... so instead it says
    # "Cannot match routes. url segment: home"
    return sanic.response.json({'buttons': buttons}, status=200)

@btn.get('/home-sidebar')
@rqst_get('user')
@jwtdec.protected()
Exemplo n.º 13
0
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
import time

import sanic
from sanic import response
import prometheus_client
from prometheus_client import core
from prometheus_client import exposition

LOGGER = logging.getLogger(__name__)

REST = sanic.Blueprint("prometheus")

GLOBAL_STATUS = prometheus_client.Gauge(
    "cnapps_sanic_up", "Was the last query of cnapps successful", ["service"])

REQUEST_LATENCY = prometheus_client.Histogram(
    "cnapps_sanic_request_latency_seconds",
    "Request Latency",
    ["method", "endpoint"],
)

REQUEST_COUNT = prometheus_client.Gauge(
    "cnapps_sanic_request_count",
    "Request Count",
    ["method", "endpoint", "status_code"],
)
Exemplo n.º 14
0
                    'tuid': 14,
                    'mid': 3,
                    'value': 3.7,
                    'created_at': 1502680672,
                    'updated_at': 1502680672
                }

        Raises:
            :class:`NotFound<sanic:sanic.exceptions.NotFound>`: The
                recommendation does not exist.

        TODO:
            Raise exception when no patch body is provided.
        """
        current = await self.get(request, rid)

        value = self.get_field(request, 'value', default=current['value'])

        async with request.app.pool.acquire() as conn:
            await conn.execute(
                """ UPDATE ysr.recommendation
                    SET value=$1 WHERE id=$2 """, value, rid)

        return await self.get(request, rid)


recommendation = sanic.Blueprint('recommendation',
                                 url_prefix='/recommendation')
recommendation.add_route(RecommendationList.as_view(), '/')
recommendation.add_route(Recommendation.as_view(), '/<rid:int>')
import os
import json
os.sys.path.append(
    "/home/ubuntu/ws/go/src/github.com/ontio/ontology-python-compiler")
import sanic
import tempfile
import functools
import subprocess
from ontology.compiler import Compiler

tmp_exts = (".abi.json", ".debug.json", ".Func.Map", ".avm", ".avm.str",
            ".warning")

app = sanic.Sanic(__name__)
api = sanic.Blueprint("api", url_prefix="/api")
v2_0 = sanic.Blueprint("v2.0", url_prefix="/v2.0")

app_v2_0_list = api.group(v2_0, url_prefix=api.url_prefix)


def read_value(data: dict, path, key: str):
    if key in ["abi", "debug", "funcmap", "opcode"]:
        with open(path, "r") as fp:
            content = fp.read()
            try:
                data[key] = json.dumps(json.loads(content))
            except json.JSONDecodeError:
                data[key] = content
    elif key in ["avm"]:
        with open(path, "rb") as fp:
            data[key] = "{}".format(fp.read())
Exemplo n.º 16
0
"""/api/role-attrs"""
import sanic
from sanic_jwt import decorators as jwtdec

from . import uid_get, rqst_get
from . import Role

roles = sanic.Blueprint('roles_api', url_prefix='/roles')


@roles.get('/me')
@uid_get()
@jwtdec.protected()
async def provide_me_attrs(rqst, user):
    """
    Provides all attributes - permissions, limits, and lock thresholds -
    for current user.
    
    Requires current session's Role ID from client.
    """
    # resp = {'rid': user.role.rid, 'perms': user.perms, 'limits': user.limits, 'locks': user.locks}
    resp = {i: getattr(user, i) for i in ('perms', 'limits', 'locks')}
    return sanic.response.json(resp, status=200)


@roles.get('/me/<attr:(perms|limits|locks)>')
@uid_get()
@jwtdec.protected()
async def provide_specific_me_attr(rqst, user, *, attr):
    """
    Provides a specific attribute (of perms/limits/locks) for requesting role.
Exemplo n.º 17
0
        return deco

    def unauthorized_handler(self, func: Callable) -> Callable:
        if asyncio.iscoroutinefunction(func) is False:
            raise ValueError('Function must be a coroutine')
        self.unauthorized_handler_ = func

        @wraps(func)
        def deco(*args: Any, **kwargs: Any):
            return func(*args, **kwargs)

        return deco


auth = LoginManager()
bp = sanic.Blueprint('app')


@auth.unauthorized_handler
async def login(request: Request, *args: Any, **kwargs: Any) -> HTTPResponse:
    app = request.app
    return await app.render_template('login.jinja')


@bp.route('/readme', methods=['GET'])
@auth.login_required
async def readme(request: Request) -> HTTPResponse:
    app = request.app
    if app.bot.config['lang'] == 'ja':
        return await res.file('README.md')
    elif app.bot.config['lang'] == 'en':
Exemplo n.º 18
0
"""/api/member"""
import sanic
from sanic_jwt import decorators as jwtdec

from . import uid_get, rqst_get
from . import User

mbr = sanic.Blueprint('member_api', url_prefix='/member')


@mbr.post('/self')
@rqst_get('user', 'fullname', 'newpass', 'curpass')
@jwtdec.protected()
async def edit_self(rqst, user, *, fullname, newpass, curpass):
    """Full name; new password; current password to verify"""
    if not await user.verify_pw(curpass):
        return sanic.exceptions.abort(403, "Incorrectly-entered password. Please try again.")
    await user.edit_self(name=fullname, pw=newpass)
    return sanic.response.raw(b'', status=204)


@mbr.get('/notifications')
@rqst_get('location', 'username')
@jwtdec.protected()
async def get_notifs(rqst, location, *, username):
    """
    Serves user's notifications -- overdue items, readied holds, etc.
    """
    user = await User.from_identifiers(username, location, app=rqst.app)
    return sanic.response.json(await user.notifs(), status=200)
Exemplo n.º 19
0
import sanic

system = sanic.Blueprint('system')


@system.route('/ping', methods=['GET', 'HEAD'])
async def ping(_request):
    """Simple healthcheck."""
    return sanic.response.text('pong')
Exemplo n.º 20
0
            format::

                {
                    'id': 42,
                    'name': 'not-fantasy'
                    'created_at': 1502680672,
                    'updated_at': 1502680672
                }

        Raises:
            :class:`NotFound<sanic:sanic.exceptions.NotFound>`: The genre does
                not exist.

        TODO:
            Raise exception when no patch body is provided.
        """
        current = await self.get(request, gid)

        name = self.get_field(request, 'name', default=current['name'])

        async with request.app.pool.acquire() as conn:
            await conn.execute('UPDATE ysr.genre SET name=$1 WHERE id=$2',
                               name, gid)

        return await self.get(request, gid)


genre = sanic.Blueprint('genre', url_prefix='/genre')
genre.add_route(GenreList.as_view(), '/')
genre.add_route(Genre.as_view(), '/<gid:int>')
Exemplo n.º 21
0
"""/location/members"""
import asyncpg
import io

import sanic
from sanic_jwt import decorators as jwtdec

from . import uid_get, rqst_get
from . import User

mbrs = sanic.Blueprint('location_members_api', url_prefix='/members')


@mbrs.get('/')
@rqst_get('cont')
@uid_get('location')
@jwtdec.protected()
async def serve_location_members(rqst, location, *,
                                 cont: 'where to continue search from'):
    """
    Serves all a location's members, in page determined by cont.
    (Output is not paginated in the actual application)
    """
    return sanic.response.json(await location.members(cont=int(cont)))


@mbrs.get('/info')
@uid_get('perms')
@rqst_get('check')
@jwtdec.protected()
async def serve_specific_member(rqst, perms, *, check: 'member to check'):
Exemplo n.º 22
0
import asyncio

from sanic import exceptions
from sanic import response
import sanic

from discode_server.utils import baseconv
from discode_server.utils import limiter
from discode_server.utils import templates
from discode_server import db
from discode_server import forms

bp = sanic.Blueprint('paste')


@bp.listener('after_server_start')
async def delete_expired(app, loop):
    while True:
        async with app.config.DB.acquire() as conn:
            await db.delete_expired(conn)
        await asyncio.sleep(60 * 60)


@bp.get('/')
async def index(request):
    paste_form = forms.NewPasteForm()
    return templates.render('index.html', paste_form=paste_form)


@bp.post('/')
@limiter.limiter("6/minute")
Exemplo n.º 23
0
                {
                    'id': 42,
                    'uid': 12,
                    'mid': 3,
                    'value': 3.7,
                    'created_at': 1502680672,
                    'updated_at': 1502680672
                }

        Raises:
            :class:`NotFound<sanic:sanic.exceptions.NotFound>`: The rating does
                not exist.

        TODO:
            Raise exception when no patch body is provided.
        """
        current = await self.get(request, rid)

        value = self.get_field(request, 'value', default=current['value'])

        async with request.app.pool.acquire() as conn:
            await conn.execute('UPDATE ysr.rating SET value=$1 WHERE id=$2',
                               value, rid)

        return await self.get(request, rid)


rating = sanic.Blueprint('rating', url_prefix='/rating')
rating.add_route(RatingList.as_view(), '/')
rating.add_route(Rating.as_view(), '/<rid:int>')
Exemplo n.º 24
0
    def bp(self) -> sanic.Blueprint:
        bp = sanic.Blueprint("websub")

        @bp.route("/hb/<hex_id>")
        async def heartbeat(request: Request,
                            hex_id: str) -> sanic.response.HTTPResponse:
            return text(hex_id,
                        status=200 if hex_id in self.heartbeat_hashes else 404)

        @bp.route("/push-callback/<hex_id>", methods=["GET", "POST"])
        async def callback(request: Request,
                           hex_id: str) -> sanic.response.HTTPResponse:
            topic = request.args.get("hub.topic")
            mode = request.args.get("hub.mode")

            if mode == "subscribe":
                sub = self.subscriptions.get(topic)
                if sub is None:
                    logger.warning(
                        f"Unexpected subscription for {topic} on {hex_id}")
                    return text("Unexpected subscription", status=400)
                else:
                    lease_s = request.args.get('hub.lease_seconds')
                    if not lease_s:
                        logger.error(
                            f"Lease is not resolved for sub {sub}: {lease_s!r}"
                        )
                        return text("No lease", status=400)
                    sub.verified_at = datetime.datetime.now()
                    sub.lease = datetime.timedelta(seconds=int(lease_s))
                    logger.info(
                        f"Subscription verified for {sub}, lease is {sub.lease}"
                    )
                    if hex_id != sub.hex_id:
                        logger.warning(
                            f"Subscription hex does not match path hex: {sub.hex_id} != {hex_id}"
                        )
                    return text(request.args.get("hub.challenge"))

            elif mode == "unsubscribe":
                sub = self.subscriptions.get(topic)
                if sub is None:
                    logger.warning(
                        f"Unexpected unsubscribe for {topic} on {hex_id}")
                    return text("Unexpected unsubscribe", status=400)
                else:
                    logger.info(
                        f"Unsubscribe confirmed for {topic} on {hex_id}")
                    if hex_id != sub.hex_id:
                        logger.warning(
                            f"Subscription hex does not match path hex: {sub.hex_id} != {hex_id}"
                        )
                    return text(request.args.get("hub.challenge"))

            elif mode == "denied":
                logger.warning(
                    f"Subscription denied for {topic}, reason was {request.args.get('hub.reason')}"
                )
                return sanic.response.HTTPResponse()
                # TODO: Don't do anything for now, should probably mark the subscription.
            else:
                sub = self.get_sub_by_hex(hex_id)
                if sub is None:
                    logger.warning(
                        "Got unknown message for unknown subscription:")
                    logger.warning(f"{hex_id}: {request}")
                    return text("Unknown subscription", status=400)
                else:
                    logger.info(f"Update for {sub}")
                    await self.broadcast(sub, request)
                    return sanic.response.HTTPResponse()

        return bp
Exemplo n.º 25
0
import datetime
import os
import random
import string
from functools import partial, wraps
from typing import Any, Callable, Optional

import sanic
from jinja2 import Environment, FileSystemLoader
from sanic.request import Request
from sanic.response import HTTPResponse, html

from .localize import LocalizedText


bp = sanic.Blueprint(__name__)

@bp.route("/",methods=["GET"])
async def main(self, request: Request) -> HTTPResponse:
    return await request.app.render_template("index.html",{"self": request.app})


class LoginManager:
    def __init__(self, bot: 'Bot') -> None:
        self.id_len = 64
        self.expires_in = datetime.timedelta(minutes=10)
        self.expires = {}
        self.cookie_key = "X-SessionId"
        self.unauthorized_handler_ = sanic.response.html("Unauthorized")

    def generate_id(self, request: Request) -> str:
Exemplo n.º 26
0
import sanic, time

a_list = []

app = sanic.Blueprint(__name__, url_prefix="/api/a")


@app.route('/', methods=['POST'])
async def add_a(request):
    a_list.append('a-' + time.asctime())
    return sanic.response.text('')


@app.route('/', methods=['GET'])
async def get_a(request):
    return sanic.response.json(a_list)
Exemplo n.º 27
0
                {
                    'id': 42,
                    'uid': 12,
                    'mid': 3,
                    'url': 'https://example.com/page-4'
                    'created_at': 1502680672,
                    'updated_at': 1502680672
                }

        Raises:
            :class:`NotFound<sanic:sanic.exceptions.NotFound>`: The bookmark
                does not exist.

        TODO:
            Raise exception when no patch body is provided.
        """
        current = await self.get(request, bid)

        url = self.get_field(request, 'url', default=current['url'])

        async with request.app.pool.acquire() as conn:
            await conn.execute('UPDATE ysr.bookmark SET url=$1 WHERE id=$2',
                               url, bid)

        return await self.get(request, bid)


bookmark = sanic.Blueprint('bookmark', url_prefix='/bookmark')
bookmark.add_route(BookmarkList.as_view(), '/')
bookmark.add_route(Bookmark.as_view(), '/<bid:int>')
Exemplo n.º 28
0
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
"""

import logging

import sanic
from sanic import request

from twitchio.ext.webhooks.utils import remove_duplicates, verify_payload, Topic
from twitchio.ext.webhooks.dispatcher import WebhookEventDispatcher

log = logging.getLogger(__name__)

dispatcher = WebhookEventDispatcher._registered_dispatcher
bp = sanic.Blueprint("Twitchio Webhooks", url_prefix="/webhooks")


@bp.route('/streams', ['GET'])
async def handle_stream_changed_get(request: request.Request):
    """Route receiving the challenge requests for the topic StreamChanged

    Parameters
    ----------
    request: sanic.request.Request
        The challenge request received from Twitch
    """
    return dispatcher().accept_subscription(request, Topic.stream_changed)


@bp.route('/streams', ['POST'])
Exemplo n.º 29
0
        Raises:
            :class:`NotFound<sanic:sanic.exceptions.NotFound>`: The user does
                not exist.

        TODO:
            Raise exception when no patch body is provided.
        """
        current = await self.get(request, uid)

        name = self.get_field(request, 'name', default=current['name'])

        async with request.app.pool.acquire() as conn:
            await conn.execute('UPDATE ysr.user SET name=$1 WHERE id=$2', name,
                               uid)

        return await self.get(request, uid)


user = sanic.Blueprint('user', url_prefix='/user')
user.add_route(UserList.as_view(), '/')
user.add_route(User.as_view(), '/<uid:int>')
# TODO:
# /user/<uid>/rating
# /user/<uid>/rating/<rtid>
# /user/<uid>/bookmark
# /user/<uid>/bookmark/<bmid>
# /user/<uid>/recommendation-send
# /user/<uid>/recommendation-send/<rid>
# /user/<uid>/recommendation-receive
# /user/<uid>/recommendation-receive/<rid>
Exemplo n.º 30
0
# Note, this is the only one of these route-handler files that uses
# straight Postgres instead of outsourcing it to the classes in typedef.
import sanic

from . import rqst_get

help = sanic.Blueprint('api_help', url_prefix='/help')


@help.get('/titles')
async def serve_help_titles(rqst):
    """
    These can be cached because they won't change
    """
    titles = await rqst.app.pg_pool.fetch(
        '''SELECT id, title FROM help WHERE true''')
    return sanic.response.json(
        {'articles': [{
            'id': i['id'],
            'title': i['title']
        } for i in titles]},
        status=200)


@help.get('/content')
@rqst_get('ID')
async def serve_help_article(rqst, *, ID):
    """
    These should never be cached.
    """
    title, content = await rqst.app.pg_pool.fetchrow(