示例#1
0
 def get_config_object(self):
     if self.args.config is not None:
         return Config(os.path.abspath(self.args.config))
     else:
         return Config(
             os.path.join('../../../../TestFramework/',
                          Config.DEFAULT_CONFIG_FILE))
示例#2
0
def handle_enabled(user):
    if request.method == 'GET':
        return format_return(Config.get_enabled())
    elif request.method == 'PUT':
        return format_return(Config.put_enabled(request.get_json()))
    else:
        return 'access to that route not allowed', 204
示例#3
0
def handle_helpers(user, helper):
    if request.method == 'GET':
        return format_return(Config.get_helper(helper))
    elif request.method == 'PUT':
        return format_return(Config.put_helper(helper, request.get_json()))
    elif request.method == 'DELETE':
        return format_return(Config.delete_helper(helper))
    else:
        return 'access to that service not allowed', 204
示例#4
0
def handle_thing(user, thing):
    if request.method == 'GET':
        return format_return(Config.get_thing(thing))
    elif request.method == 'PUT':
        return format_return(Config.put_thing(thing, request.get_json()))
    elif request.method == 'DELETE':
        return format_return(Config.delete_thing(thing))
    else:
        return 'access to that service not allowed', 204
示例#5
0
 def __init__(self, host: str, port: int):
     self._root = dirname(__file__)
     self._app = Quart(__name__)
     self._debug = False
     self._host = host
     self._port = port
     self._domain = f"http://{host}:{port}"
     self._agent = Agent()
     self._config = Config()
     self._proxy = RequestProxy()
示例#6
0
    def __init__(self):
        # Anime
        self._config = Config()
        self._anime_searchers: Dict[str, AnimeSearcher] = {}
        self._anime_detail_parsers: Dict[str, AnimeDetailParser] = {}
        self._anime_url_parsers: Dict[str, AnimeUrlParser] = {}
        self._anime_proxy_cls: Dict[str, Type[StreamProxy]] = {}
        # Danmaku
        self._danmaku_searchers: Dict[str, DanmakuSearcher] = {}
        self._danmaku_detail_parsers: Dict[str, DanmakuDetailParser] = {}
        self._danmaku_data_parsers: Dict[str, DanmakuDataParser] = {}

        for module in self._config.get_enabled_modules():
            self.load_full_module(module)
示例#7
0
def test_connection():
    """AWS Cognito Connection test."""
    _config = Config()
    test_connection = boto3.client(
        _config.AWS_SERVICE,
        aws_access_key_id=_config.AWS_ACCESS_KEY_ID,
        aws_secret_access_key=_config.AWS_SECRET_ACCESS_KEY,
        region_name=_config.AWS_REGION_NAME)
示例#8
0
def main() -> None:
    """Application entrypoint."""

    config = Config.load_config()

    app = init_app(config)

    web.run_app(app)
示例#9
0
 def __init__(self, channel, message, config: Config):
     self.channel = channel
     channel_url = config.slack_channel(channel)
     if not channel_url:
         raise HTTPException(
             status_code=501, detail=f"No slack channel '{channel}' configured"
         )
     self.channel_url = channel_url
     self.message = message
示例#10
0
 def __init__(self):
     self._scheduler = Scheduler()
     self._bangumi = Bangumi()
     self._config = Config()
     # Memory Database for cache
     self._anime_db = CacheDB()
     self._danmaku_db = CacheDB()
     self._proxy_db = CacheDB()
     self._others_db = CacheDB()
示例#11
0
def main() -> None:
    """Start the API for controlling mitmproxy."""
    if sys.version_info < (3, 6):
        sys.exit("Python >= 3.6 required")

    config = Config(parse_args())
    flow = Flow(config)
    proxy = Proxy(flow)
    http = Server(proxy)
    http.start()
示例#12
0
    def test_builder(self) -> None:
        self.assertIsInstance(Config(_EXAMPLE_CONFIG), Config)

        self.temp_config.write_text(_NOT_A_CONFIG)
        self.assertRaises(config.exception.InvalidConfiguration,
                          Config._build, self.temp_config)

        self.temp_config.write_text(_BAD_YAML)
        self.assertRaises(config.exception.InvalidConfiguration,
                          Config._build, self.temp_config)
示例#13
0
    def test_validator(self) -> None:
        self.assertTrue(Config(_EXAMPLE_CONFIG)._is_valid)

        self.temp_config.write_text(_ADDED_INFO_CONFIG)
        self.assertTrue(Config(self.temp_config)._is_valid)

        self.temp_config.write_text(_SCALAR_LIST_CONFIG)
        self.assertRaises(config.exception.InvalidSemantics,
                          Config, self.temp_config)

        self.temp_config.write_text(_INCORRECT_TYPE_CONFIG)
        self.assertRaises(config.exception.InvalidSemantics,
                          Config, self.temp_config)

        self.temp_config.write_text(_MISSING_KEY_CONFIG)
        self.assertRaises(config.exception.InvalidSemantics,
                          Config, self.temp_config)

        self.temp_config.write_text(_MISSING_OPTIONAL_CONFIG)
        self.assertTrue((c := Config(self.temp_config))._is_valid)
        self.assertEqual(c.email.smtp.port, 25)

        self.temp_config.write_text(_MISSING_DELETION_LIMBO)
示例#14
0
def aws_config(providers: dict):
    test = config.TEST_CONFIG
    config.TEST_CONFIG = True
    cfg = Config(
        providers={
            "aws":
            dict(
                access_key_id="access",
                secret_access_key="secret",
                region="region",
                **providers,
            )
        },
        topics=[],
        boto=MockBoto(),
    )
    config.TEST_CONFIG = test
    return cfg
def app():
    """
    Set up global app for functional tests
    """
    class Response(APIResponse):
        @cached_property
        def json(self):
            return json.loads(self.data)

    class APIClient(FlaskClient):
        def open(self, *args, **kwargs):
            if 'json' in kwargs:
                kwargs['data'] = json.dumps(kwargs.pop('json'))
                kwargs['content_type'] = 'application/json'
            return super(APIClient, self).open(*args, **kwargs)

    _config = Config()
    app = create_app(_config)
    app.response_class = Response
    app.test_client_class = APIClient
    app.testing = True
    return app
示例#16
0
    def test_example_config(self) -> None:
        # NOTE This is coupled to eg/.vaultrc
        # Any changes there must be reflected in these tests
        config = Config(_EXAMPLE_CONFIG)

        self.assertEqual(config.identity.ldap.host, "ldap.example.com")
        self.assertEqual(config.identity.ldap.port, 389)

        self.assertEqual(config.identity.users.dn,
                         "ou=users,dc=example,dc=com")
        self.assertEqual(config.identity.users.attributes.uid, "uidNumber")
        self.assertEqual(config.identity.users.attributes.name, "cn")
        self.assertEqual(config.identity.users.attributes.email, "mail")

        self.assertEqual(config.identity.groups.dn,
                         "ou=groups,dc=example,dc=com")
        self.assertEqual(config.identity.groups.attributes.gid, "gidNumber")
        self.assertEqual(config.identity.groups.attributes.owners, "owner")
        self.assertEqual(config.identity.groups.attributes.members, "member")

        self.assertEqual(config.persistence.postgres.host,
                         "postgres.example.com")
        self.assertEqual(config.persistence.postgres.port, 5432)

        self.assertEqual(config.persistence.database, "sandman")
        self.assertEqual(config.persistence.user, "a_db_user")
        self.assertEqual(config.persistence.password, "abc123")

        self.assertEqual(config.email.smtp.host, "mail.example.com")
        self.assertEqual(config.email.smtp.port, 25)
        self.assertEqual(config.email.sender, "*****@*****.**")

        self.assertEqual(config.deletion.threshold, time.delta(days=90))
        self.assertEqual(config.deletion.warnings, [time.delta(
            days=10), time.delta(days=3), time.delta(days=1)])
        self.assertEqual(config.deletion.limbo, time.delta(days=14))

        self.assertEqual(config.archive.threshold, 1000)
        self.assertEqual(config.archive.handler, T.Path("/path/to/executable"))
示例#17
0
def app():
    """ Set up global app for functional testing """
    class Response(APIResponse):
        @cached_property
        def json(self):
            return json.loads(self.data)

    class APIClient(FlaskClient):
        def open(self, *args, **kwargs):
            if 'json' in kwargs:
                kwargs['data'] = json.dumps(kwargs.pop('json'))
                kwargs['content_type'] = 'application/json'
            return super(APIClient, self).open(*args, **kwargs)

    _config = Config()
    app = create_app(_config)
    app.response_class = Response
    app.test_client_class = APIClient
    app.testing = True
    disconnect()  # Disconnets the previous connection with MongoDB
    connect('mockDB', host='mongomock://localhost')  # MongoDB mock connection

    return app
示例#18
0
文件: main.py 项目: ttymck/botschaft
def topic(
    topic_name: str,
    config: Config = Depends(get_config),
    message=Depends(message),
):
    topic = config.topic(topic_name)
    if not topic:
        raise HTTPException(
            status_code=501, detail=f"No topic '{topic_name}' configured"
        )
    for provider, params in topic.params(message):
        if provider == Provider.SLACK:
            SlackMessage(**params, config=config).send()
        elif provider == Provider.DISCORD:
            DiscordMessage(**params, config=config).send()
        elif provider == Provider.TWILIO:
            TwilioMessage(**params, config=config).send()
        elif provider == Provider.SNS:
            SnsMessage(**params, config=config).send()
        else:
            raise HTTPException(
                status_code=400, detail=f"Unsupported provider '{provider}'"
            )
    return f"Sent {message} to topic '{topic_name}'"
示例#19
0
You should have received a copy of the GNU General Public License along
with this program. If not, see https://www.gnu.org/licenses/
"""

import unittest
from unittest.mock import patch

import core.idm
from core import typing as T
from api.config import Config
from api.idm.idm import LDAPIdentityManager, LDAPUser, LDAPGroup
from api.idm.ldap import NoResultsFound

# NOTE This ties our tests to the example configuration
_EXAMPLE_CONFIG = Config(T.Path("eg/.vaultrc")).identity


def _DUMMY_PWUID(uid):
    # Dummy passwd interface, that acts as an identity function
    return T.SimpleNamespace(pw_uid=uid)


def _DUMMY_GRGID(gid):
    # Dummy group interface, that acts as an identity function
    return T.SimpleNamespace(gr_name="foo", gr_gid=gid)


def _DUMMY_PWNAM(username):
    # Dummy passwd-by-username interface: Take the bottom 10-bits from
    # the hash of the username string as the user ID
示例#20
0
import pytest
import requests

from api.config import Config
from api.providers import discord

test_config = Config(
    providers={"discord": {
        "channels": {
            "alerts": "fake-webhook"
        }
    }}, topics=[])


def test_discord_message():
    discord_message = discord.DiscordMessage(channel="alerts",
                                             message="test message",
                                             config=test_config)
    discord_message.send()
    assert True
示例#21
0
class ModuleLoader(object):
    """
    模块加载器, 负责动态加载/卸载各个模块
    """
    def __init__(self):
        # Anime
        self._config = Config()
        self._anime_searchers: Dict[str, AnimeSearcher] = {}
        self._anime_detail_parsers: Dict[str, AnimeDetailParser] = {}
        self._anime_url_parsers: Dict[str, AnimeUrlParser] = {}
        self._anime_proxy_cls: Dict[str, Type[StreamProxy]] = {}
        # Danmaku
        self._danmaku_searchers: Dict[str, DanmakuSearcher] = {}
        self._danmaku_detail_parsers: Dict[str, DanmakuDetailParser] = {}
        self._danmaku_data_parsers: Dict[str, DanmakuDataParser] = {}

        for module in self._config.get_enabled_modules():
            self.load_full_module(module)

    def load_full_module(self, module: str):
        """
        加载模块中所以的类
        :param module: 引擎引擎模块名, api.xxx.xxx
        """
        self.load_search_module(module)
        self.load_utils_module(module)

    def load_search_module(self, module: str):
        """
        只加载搜索引擎模块, 用于搜索资源
        """
        py_module = import_module(module)
        for name, cls in getmembers(py_module, isclass):

            if issubclass(cls, AnimeSearcher) and cls != AnimeSearcher \
                    and module not in self._anime_searchers:
                self._anime_searchers[module] = cls(
                )  # 创建 Searcher 对象, 程序执行期间一直使用
                logger.info(f"Loading {name}: {cls}")

            if issubclass(cls, DanmakuSearcher) and cls != DanmakuSearcher \
                    and module not in self._danmaku_searchers:
                self._danmaku_searchers[module] = cls()
                logger.info(f"Loading {name}: {cls}")

    def load_utils_module(self, module: str):
        """
        只加载工具模块, 用于资源数据的解析
        """
        py_module = import_module(module)
        for name, cls in getmembers(py_module, isclass):

            if issubclass(cls, AnimeDetailParser) and cls != AnimeDetailParser \
                    and module not in self._anime_detail_parsers:
                self._anime_detail_parsers[module] = cls()
                logger.info(f"Loading {name}: {cls}")

            if issubclass(cls, AnimeUrlParser) and cls != AnimeUrlParser \
                    and module not in self._anime_url_parsers:
                self._anime_url_parsers[module] = cls()
                logger.info(f"Loading {name}: {cls}")

            if issubclass(cls, StreamProxy) and cls != StreamProxy \
                    and module not in self._anime_proxy_cls:
                self._anime_proxy_cls[module] = cls  # 只加载 class, 动态创建
                logger.info(f"Loading {name}: {cls}")

            if issubclass(cls, DanmakuDetailParser) and cls != DanmakuDetailParser \
                    and module not in self._danmaku_detail_parsers:
                self._danmaku_detail_parsers[module] = cls()
                logger.info(f"Loading {name}: {cls}")

            if issubclass(cls, DanmakuDataParser) and cls != DanmakuDataParser \
                    and module not in self._danmaku_data_parsers:
                self._danmaku_data_parsers[module] = cls()
                logger.info(f"Loading {name}: {cls}")

    def unload_full_module(self, module: str) -> None:
        """卸载模块名对应的引擎"""
        if module.startswith("api.anime"):
            self._anime_searchers.pop(module, None)
            self._anime_detail_parsers.pop(module, None)
            self._anime_url_parsers.pop(module, None)
            self._anime_proxy_cls.pop(module, None)
        if module.startswith("api.danmaku"):
            self._danmaku_searchers.pop(module, None)
            self._danmaku_detail_parsers.pop(module, None)
            self._danmaku_data_parsers.pop(module, None)
        logger.info(f"Unloaded <module {module}>")

    def change_module_state(self, module: str, enable: bool) -> bool:
        """动态加载/卸载引擎, 并更新配置文件"""
        if enable:  # 加载引擎
            self.load_full_module(module)
            return self._config.update_module_state(module, True)
        else:  # 卸载引擎
            self.unload_full_module(module)
            return self._config.update_module_state(module, False)

    def get_anime_searchers(self) -> List[AnimeSearcher]:
        return list(self._anime_searchers.values())

    def get_anime_detail_parser(self,
                                module: str) -> Optional[AnimeDetailParser]:
        return self._anime_detail_parsers.get(module)

    def get_anime_url_parser(self, module: str) -> AnimeUrlParser:
        return self._anime_url_parsers.get(
            module) or AnimeUrlParser()  # 没有就有默认的

    def get_anime_proxy_class(self, module: str) -> Type[StreamProxy]:
        return self._anime_proxy_cls.get(module) or StreamProxy

    def get_danmaku_searcher(self) -> List[DanmakuSearcher]:
        return list(self._danmaku_searchers.values())

    def get_danmaku_detail_parser(
            self, module: str) -> Optional[DanmakuDetailParser]:
        return self._danmaku_detail_parsers.get(module)

    def get_danmaku_data_parser(self,
                                module: str) -> Optional[DanmakuDataParser]:
        return self._danmaku_data_parsers.get(module)
示例#22
0
class APIRouter:
    def __init__(self, host: str, port: int):
        self._root = dirname(__file__)
        self._app = Quart(__name__)
        self._debug = False
        self._host = host
        self._port = port
        self._domain = f"http://{host}:{port}"
        self._agent = Agent()
        self._config = Config()
        self._proxy = RequestProxy()
        self._stats = Statistics()

    def set_domain(self, domain: str):
        """
        设置 API 返回的资源链接的域名, 域名含协议头不含端口号
        如: http://www.foo.bar
        """
        self._domain = f"{domain}:{self._port}" if domain else self._domain

    def run(self):
        """启动 API 解析服务"""
        def exception_handler(_loop, context):
            logger.debug(context)

        self._init_routers()
        # 为了解决事件循环内部出现的异常
        if os.name == "nt":
            asyncio.set_event_loop_policy(
                asyncio.WindowsSelectorEventLoopPolicy())
        loop = asyncio.new_event_loop()
        loop.set_exception_handler(exception_handler)
        asyncio.set_event_loop(loop)
        self._app.run(host=self._host,
                      port=self._port,
                      debug=False,
                      use_reloader=False,
                      loop=loop)

    def _init_routers(self):
        """创建路由接口"""
        @self._app.after_request
        async def apply_caching(resp: Response):
            """设置响应的全局 headers, 允许跨域"""
            resp.headers["Server"] = "Anime-API"
            resp.headers["Access-Control-Allow-Origin"] = "*"
            resp.headers["Access-Control-Allow-Headers"] = "*"
            return resp

        @self._app.route("/")
        async def index():
            """API 主页显示帮助信息"""
            file = f"{self._root}/templates/interface.txt"
            with open(file, encoding="utf-8") as f:
                text = f.read()
            return Response(text, mimetype="text/plain")

        @self._app.route("/statistics")
        async def statistics():
            """百度统计转发, 用户体验计划"""
            return await self._stats.transmit(request)

        @self._app.route("/statistics/<hm_js>")
        async def get_statistics_js(hm_js):
            return await self._stats.get_hm_js(request)

        # ======================== Anime Interface ===============================

        @self._app.route("/anime/bangumi/updates")
        async def get_bangumi_updates():
            """获取番剧更新时间表"""
            bangumi_list = await self._agent.get_bangumi_updates()
            data = []
            for bangumi in bangumi_list:
                one_day = {
                    "date": bangumi.date,
                    "day_of_week": bangumi.day_of_week,
                    "is_today": bangumi.is_today,
                    "updates": []
                }
                for info in bangumi:
                    one_day["updates"].append({
                        "title": info.title,
                        "cover_url": f"{info.cover_url}",  # 图片一律走代理, 防止浏览器跨域拦截
                        "update_time": info.update_time,
                        "update_to": info.update_to
                    })
                data.append(one_day)
            return jsonify(data)

        @self._app.route("/anime/search/<path:keyword>")
        async def search_anime(keyword):
            """番剧搜索, 该方法回阻塞直到所有引擎数据返回"""
            result: List[AnimeMeta] = []
            await self._agent.get_anime_metas(
                keyword.strip(), callback=lambda m: result.append(m))
            ret = []
            for meta in result:
                ret.append({
                    "title": meta.title,
                    "cover_url": f"{meta.cover_url}",
                    "category": meta.category,
                    "description": meta.desc,
                    "score": 80,  # TODO: 番剧质量评分机制
                    "module": meta.module,
                    "url": f"{self._domain}/anime/{meta.token}"
                })
            return jsonify(ret)

        @self._app.websocket("/anime/search")
        async def ws_search_anime():
            async def push(meta: AnimeMeta):
                await websocket.send_json({
                    "title":
                    meta.title,
                    "cover_url":
                    f"{meta.cover_url}",
                    "category":
                    meta.category,
                    "description":
                    meta.desc,
                    "score":
                    80,
                    "engine":
                    meta.module,
                    "url":
                    f"{self._domain}/anime/{meta.token}"
                })

            # route path 不能有中文, 客户端 send 关键字
            keyword = await websocket.receive()
            await self._agent.get_anime_metas(keyword.strip(),
                                              co_callback=push)

        @self._app.route("/anime/<token>")
        async def get_anime_detail(token):
            """返回番剧详情页面信息"""
            detail = await self._agent.get_anime_detail(token)
            if not detail:
                return Response("Parse detail failed", status=404)

            ret = {
                "title": detail.title,
                "cover_url": f"{detail.cover_url}",
                "description": detail.desc,
                "category": detail.category,
                "module": detail.module,
                "play_lists": []
            }
            for idx, playlist in enumerate(detail):
                lst = {
                    "name": playlist.name,
                    "num": playlist.num,
                    "video_list": []
                }  # 一个播放列表
                for episode, video in enumerate(playlist):
                    video_path = f"{token}/{idx}/{episode}"
                    lst["video_list"].append({
                        "name":
                        video.name,
                        "info":
                        f"{self._domain}/anime/{video_path}",
                        "player":
                        f"{self._domain}/anime/{video_path}/player",
                    })
                ret["play_lists"].append(lst)
            return jsonify(ret)

        @self._app.route("/anime/<token>/<playlist>/<episode>")
        async def parse_anime_info(token: str, playlist: str, episode: str):
            """获取视频信息"""
            url = await self._agent.get_anime_real_url(token, int(playlist),
                                                       int(episode))
            info = {
                "raw_url":
                f"{self._domain}/anime/{token}/{playlist}/{episode}/url",
                "proxy_url":
                f"{self._domain}/proxy/anime/{token}/{playlist}/{episode}",
                "format": url.format,
                # "resolution": url.resolution,
                "size": url.size,
                "lifetime": url.left_lifetime
            }
            return jsonify(info)

        @self._app.route("/anime/<token>/<playlist>/<episode>/url")
        async def redirect_to_real_url(token: str, playlist: str,
                                       episode: str):
            """重定向到视频直链, 防止直链过期导致播放器无法播放"""
            proxy = await self._agent.get_anime_proxy(token, int(playlist),
                                                      int(episode))
            if not proxy or not proxy.is_available():
                return Response("Resource not available", status=404)
            if proxy.is_enforce_proxy():  # 该资源启用了强制代理
                return redirect(f"/proxy/anime/{token}/{playlist}/{episode}")
            return redirect(proxy.get_real_url())

        @self._app.route("/anime/<token>/<playlist>/<episode>/player")
        async def player_without_proxy(token, playlist, episode):
            """视频直链播放测试"""
            url = f"{self._domain}/anime/{token}/{playlist}/{episode}"
            return await render_template("player.html", info_url=url)

        # ======================== Danmaku Interface ===============================

        @self._app.route("/danmaku/search/<path:keyword>")
        async def search_danmaku(keyword):
            """搜索番剧弹幕库"""
            result: List[DanmakuMeta] = []
            await self._agent.get_danmaku_metas(
                keyword.strip(), callback=lambda m: result.append(m))
            data = []
            for meta in result:
                data.append({
                    "title": meta.title,
                    "num": meta.num,
                    "module": meta.module,
                    "score": 80,  # TODO: 弹幕质量评分机制
                    "url": f"{self._domain}/danmaku/{meta.token}"
                })
            return jsonify(data)

        @self._app.websocket("/danmaku/search")
        async def ws_search_danmaku():
            """搜索番剧弹幕库"""
            async def push(meta: DanmakuMeta):
                await websocket.send_json({
                    "title":
                    meta.title,
                    "num":
                    meta.num,
                    "module":
                    meta.module,
                    "score":
                    80,
                    "url":
                    f"{self._domain}/danmaku/{meta.token}"
                })

            keyword = await websocket.receive()
            await self._agent.get_danmaku_metas(keyword.strip(),
                                                co_callback=push)

        @self._app.route("/danmaku/<token>")
        async def get_danmaku_detail(token):
            """获取番剧各集对应的弹幕库信息"""
            detail = await self._agent.get_danmaku_detail(token)
            if detail.is_empty():
                return Response("Parse danmaku detail failed", status=404)

            data = []
            for episode, danmaku in enumerate(detail):
                data.append({
                    "name":
                    danmaku.name,
                    "url":
                    f"{self._domain}/danmaku/{token}/{episode}",  # Dplayer 会自动添加 /v3/
                    "data":
                    f"{self._domain}/danmaku/{token}/{episode}/v3/"  # 调试用
                })
            return jsonify(data)

        @self._app.route("/danmaku/<token>/<episode>/v3/")
        async def get_danmaku_data(token, episode):
            """解析视频的弹幕库信息, 返回 DPlayer 支持的弹幕格式"""
            data = await self._agent.get_danmaku_data(token, int(episode))
            ret = {"code": 0, "data": data.data, "num": data.num}
            return jsonify(ret)

        # ======================== IPTV Interface ===============================

        @self._app.route("/iptv/list")
        async def get_iptv_list():
            """IPTV 直播源"""
            sources = self._agent.get_iptv_sources()
            data = []
            for source in sources:
                data.append({"name": source.name, "url": source.url})
            return jsonify(data)

        # ======================== Proxy Interface ===============================

        @self._app.route("/proxy/image/<path:raw_url>")
        async def image_proxy(raw_url):
            """对跨域图片进行代理访问, 返回数据"""
            return await self._proxy.make_response(raw_url)

        @self._app.route("/proxy/anime/<token>/<playlist>/<episode>")
        async def anime_stream_proxy(token, playlist, episode):
            """代理访问普通的视频数据流"""
            proxy = await self._agent.get_anime_proxy(token, int(playlist),
                                                      int(episode))
            if not proxy:
                return Response("proxy error", status=404)

            if proxy.get_stream_format() == "hls":  # m3u8 代理
                proxy.set_chunk_proxy_router(
                    f"{self._domain}/proxy/hls/{token}/{playlist}/{episode}")
                return await proxy.make_response_for_m3u8()
            else:  # mp4 代理
                range_field = request.headers.get("range")
                return await proxy.make_response_with_range(range_field)

        @self._app.route("/proxy/hls/<token>/<playlist>/<episode>/<path:url>")
        async def m3u8_chunk_proxy(token, playlist, episode, url):
            """代理访问视频的某一块数据"""
            proxy = await self._agent.get_anime_proxy(token, int(playlist),
                                                      int(episode))
            if not proxy:
                return Response("m3u8 chunk proxy error", status=404)
            return await proxy.make_response_for_chunk(url)

        # ======================== System Interface ===============================

        @self._app.route("/system/logs")
        async def show_logs():
            file = f"{self._root}/logs/api.log"
            with open(file, encoding="utf-8") as f:
                text = f.read()
            return Response(text, mimetype="text/plain")

        @self._app.route("/system/version")
        async def show_system_version():
            return jsonify(self._config.get_version())

        @self._app.route("/system/clear")
        async def clear_system_cache():
            """清空 API 的临时缓存数据"""
            mem_free = self._agent.cache_clear()
            return jsonify({"clear": "success", "free": mem_free})

        @self._app.route("/system/modules", methods=["GET", "POST", "OPTIONS"])
        async def show_global_settings():
            if request.method == "GET":
                return jsonify(self._config.get_modules_status())
            if request.method == "POST":
                options = await request.json
                ret = {}
                for option in options:
                    module = option.get("module")
                    enable = option.get("enable")
                    if not module:
                        continue
                    ok = self._agent.change_module_state(module, enable)
                    ret[module] = "success" if ok else "failed"
                return jsonify(ret)
            if request.method == "OPTIONS":
                return Response("")
示例#23
0
 def setUpClass(cls):
     cls.config = Config(os.path.dirname(__file__))
示例#24
0
class DatabaseTest(unittest.TestCase):

    db = WeatherTalkDatabase(Config())
    app = app

    def setUp(self):
        self.db = WeatherTalkDatabase(Config())

    def tearDown(self):
        self.db.session.remove()

    @staticmethod
    def generate_observation():
        observation = Observation(humidity=float(random.randrange(0, 100)),
                                  temperature=float(random.randrange(0, 100)),
                                  pressure=float(random.randrange(0, 100)),
                                  wind=float(random.randrange(0, 100)),
                                  condition=WeatherTypes.Sunny,
                                  location="test, test")
        return observation

    @staticmethod
    def generate_device():
        return Device(name=str(uuid.uuid1().hex))

    @staticmethod
    def generate_user():
        return User(name=str(uuid.uuid1().hex),
                    email=str(uuid.uuid1().hex),
                    password=str(uuid.uuid1().hex))

    def test_create_user(self):
        test_content = ENTRIES.get("user")

        user = None
        try:
            user = self.generate_user()
            self.db.session.add(user)
        except Exception as e:
            self.fail(f"Error {e}, {e.__class__}")

        self.assertIsNotNone(user)
        for _ in range(0, random.randrange(1, 10)):
            try:
                device = self.generate_device()
                user.devices.append(device)

                self.db.session.add(device)
            except Exception as e:
                self.fail(f"Error {e}, {e.__class__}")

        self.db.session.commit()

    def test_delete_user(self):
        db_users = self.db.session.query(User).all()
        if not db_users:
            for _ in range(0, random.randrange(1, 10)):
                user = self.generate_user()
                self.db.session.add(user)
            self.db.session.commit()
            db_users = self.db.session.query(User).all()

        for user in db_users:
            try:
                self.db.session.delete(user)
                self.db.session.commit()
            except Exception as e:
                self.fail(f"Error {e}, {e.__class__}")

    def test_create_device(self):
        device = None
        try:
            device = self.generate_device()
            self.db.session.add(device)
            self.db.session.commit()
        except Exception as e:
            self.fail(f"Error {e}, {e.__class__}")

        self.assertIsNotNone(device)

    def test_delete_device(self):
        devices = self.db.session.query(Device).all()
        if not devices:
            for _ in range(0, random.randrange(1, 10)):
                device = self.generate_device()
                self.db.session.add(device)
            self.db.session.commit()
            devices = self.db.session.query(Device).all()
        for device in devices:
            try:
                self.db.session.delete(device)
                self.db.session.commit()
            except Exception as e:
                self.fail(f"Error {e}, {e.__class__}")

    def test_create_device_group(self):
        try:
            user = self.generate_user()
            group = DeviceGroup(name=str(uuid.uuid1().hex), user_id=user.id)

            for _ in range(0, random.randrange(1, 10)):
                device = self.generate_device()
                group.members.append(device)
                self.db.session.add(device)

            self.db.session.add(user)
            self.db.session.add(group)
            self.db.session.commit()
        except Exception as e:
            self.fail(f"Error {e}, {e.__class__}")

    def test_delete_device_group(self):
        groups = self.db.session.query(DeviceGroup).all()
        if not groups:
            user = self.generate_user()
            group = DeviceGroup(name=str(uuid.uuid1().hex), user_id=user.id)

            for _ in range(0, random.randrange(1, 10)):
                device = self.generate_device()
                group.members.append(device)
                self.db.session.add(device)

            self.db.session.add(user)
            self.db.session.add(group)
            self.db.session.commit()

            groups = self.db.session.query(DeviceGroup).all()

        for group in groups:
            try:
                self.db.session.delete(group)
                self.db.session.commit()
            except Exception as e:
                self.fail(f"Error {e}, {e.__class__}")

    def test_create_observation(self):
        try:
            observation = self.generate_observation()
            self.db.session.add(observation)
            self.db.session.commit()
        except Exception as e:
            self.fail(f"Error {e}, {e.__class__}")

    def test_delete_observation(self):
        observations = self.db.session.query(Observation).all()
        if not observations:
            for _ in range(0, random.randrange(1, 10)):
                observation = self.generate_observation()
                self.db.session.add(observation)
                self.db.session.commit()

        for observation in observations:
            try:
                self.db.session.delete(observation)
                self.db.session.commit()
            except Exception as e:
                self.fail(f"Error {e}, {e.__class__}")
# Copyright 2019 by Mihail Butnaru
# All rights reserved.
from api.app import create_app
from api.config import Config

_config = Config()
app = create_app(_config)
示例#26
0
 def setUp(self):
     self.db = WeatherTalkDatabase(Config())
示例#27
0
def create_app():
    app = Flask(__name__)
    app.config.from_object(Config())
    return app
示例#28
0
 def __init__(self):
     self.session: Optional[ClientSession] = None
     self._domain_mapping: Dict[str, str] = Config().get("domain_mapping")
     self._dns_server = []
    parser.add_argument('--recorder_fs_ready',
                        action='store_true',
                        help='Recorder folders and files already created')
    parser.add_argument(
        '--preserve_player_fs',
        action='store_true',
        help='Do not remove player folders and files after test')
    parser.add_argument(
        '--preserve_recorder_fs',
        action='store_true',
        help='Do not remove recorder folders and files after test')

    args = parser.parse_args()

    if args.config is not None:
        config = Config(os.path.abspath(args.config))
    else:
        config = Config(os.path.join('../../../', Config.DEFAULT_CONFIG_FILE))

    # Create Device Manager
    dev_manager = DeviceManager(config)

    # Assign devices according to role
    player, recorder = dev_manager.get_devices_by_serials(
        args.player, args.recorder)

    # Create test runner instance
    tc_runner = AdnPlayerRecorderExampleTestTcRunner(config,
                                                     player=player,
                                                     recorder=recorder)
示例#30
0
        client.publish(f'{prefix}/rsp',
                       json.dumps(payload),
                       qos=0,
                       retain=True)
    else:
        client.publish(f'{prefix}/data/{topic}',
                       json.dumps(payload),
                       qos=0,
                       retain=True)


if __name__ == '__main__':
    # TODO: error check
    print('m2ag.labs core service 0.2.0')
    print('copyright 2021 https://m2aglabs.com')
    config = Config.get_server_config()
    logging.basicConfig(
        level=config['log_level'],
        format="%(asctime)s %(filename)s:%(lineno)s %(levelname)s %(message)s")
    prefix = config.get('prefix')
    try:
        client = mqtt.Client(config.get('id'),
                             protocol=mqtt.MQTTv311,
                             transport="tcp")
        client.username_pw_set(username=secrets.get('mqtt_id'),
                               password=secrets.get('mqtt_password'))
        if secrets.get('mqtt_tls'):
            client.tls_set(ca_certs=secrets.get('mqtt_ca'))
            if secrets.get('mqtt_insecure'):
                client.tls_insecure_set(True)
        client.connect(secrets.get('mqtt_broker'), secrets.get('mqtt_port'),