# Path: sygnal/http.py
# class PushGatewayApiServer(object):
#     def __init__(self, sygnal: "Sygnal"):
#         """
#         Initialises the /_matrix/push/* (Push Gateway API) server.
#         Args:
#             sygnal (Sygnal): the Sygnal object
#         """
#         root = Resource()
#         matrix = Resource()
#         push = Resource()
#         v1 = Resource()
# 
#         # Note that using plain strings here will lead to silent failure
#         root.putChild(b"_matrix", matrix)
#         matrix.putChild(b"push", push)
#         push.putChild(b"v1", v1)
#         v1.putChild(b"notify", V1NotifyHandler(sygnal))
# 
#         # add health
#         root.putChild(b"health", HealthHandler())
# 
#         use_x_forwarded_for = sygnal.config["log"]["access"]["x_forwarded_for"]
# 
#         log_formatter = (
#             proxiedLogFormatter if use_x_forwarded_for else combinedLogFormatter
#         )
# 
#         self.site = SygnalLoggedSite(
#             root,
#             reactor=sygnal.reactor,
#             log_formatter=log_formatter,
#             requestFactory=SizeLimitingRequest,
#         )
# 
# Path: sygnal/notifications.py
# class Pushkin(abc.ABC):
#     def __init__(self, name: str, sygnal: "Sygnal", config: Dict[str, Any]):
#         self.name = name
#         self.appid_pattern = glob_to_regex(name, ignore_case=False)
#         self.cfg = config
#         self.sygnal = sygnal
# 
#     @overload
#     def get_config(self, key: str, type_: Type[T], default: T) -> T:
#         ...
# 
#     @overload
#     def get_config(self, key: str, type_: Type[T], default: None = None) -> Optional[T]:
#         ...
# 
#     def get_config(
#         self, key: str, type_: Type[T], default: Optional[T] = None
#     ) -> Optional[T]:
#         if key not in self.cfg:
#             return default
#         if not isinstance(self.cfg[key], type_):
#             raise PushkinSetupException(
#                 f"{key} is of incorrect type, please check that the entry for {key} is "
#                 f"formatted correctly in the config file. "
#             )
#         return self.cfg[key]
# 
#     def handles_appid(self, appid: str) -> bool:
#         """Checks whether the pushkin is responsible for the given app ID"""
#         return self.name == appid or self.appid_pattern.match(appid) is not None
# 
#     @abc.abstractmethod
#     async def dispatch_notification(
#         self, n: Notification, device: Device, context: "NotificationContext"
#     ) -> List[str]:
#         """
#         Args:
#             n: The notification to dispatch via this pushkin
#             device: The device to dispatch the notification for.
#             context: the request context
# 
#         Returns:
#             A list of rejected pushkeys, to be reported back to the homeserver
#         """
#         ...
# 
#     @classmethod
#     async def create(cls, name: str, sygnal: "Sygnal", config: Dict[str, Any]):
#         """
#         Override this if your pushkin needs to call async code in order to
#         be constructed. Otherwise, it defaults to just invoking the Python-standard
#         __init__ constructor.
# 
#         Returns:
#             an instance of this Pushkin
#         """
#         return cls(name, sygnal, config)


import copy
import importlib
import logging
import logging.config
import os
import sys
import opentracing
import prometheus_client
import yaml
            import sentry_sdk
                    import jaeger_client
from typing import Any, Dict, Set, cast
from opentracing import Tracer
from opentracing.scope_managers.asyncio import AsyncioScopeManager
from twisted.internet import asyncioreactor, defer
from twisted.internet.defer import ensureDeferred
from twisted.internet.interfaces import (
    IReactorCore,
    IReactorFDSet,
    IReactorPluggableNameResolver,
    IReactorTCP,
    IReactorTime,
)
from twisted.python import log as twisted_log
from twisted.python.failure import Failure
from zope.interface import Interface
from sygnal.http import PushGatewayApiServer
from sygnal.notifications import Pushkin
            kind_split = app_type.rsplit(".", 1)
            to_import = kind_split[0]
            to_construct = kind_split[1]
        else:
            to_import = f"sygnal.{app_type}pushkin"
            to_construct = f"{app_type.capitalize()}Pushkin"

        logger.info("Importing pushkin module: %s", to_import)
        pushkin_module = importlib.import_module(to_import)
        logger.info("Creating pushkin: %s", to_construct)
        clarse = getattr(pushkin_module, to_construct)
        return await clarse.create(app_name, self, app_config)

    async def make_pushkins_then_start(self) -> None:
        for app_id, app_cfg in self.config["apps"].items():
            try:
                self.pushkins[app_id] = await self._make_pushkin(app_id, app_cfg)
            except Exception:
                logger.error(
                    "Failed to load and create pushkin for kind '%s'" % app_cfg["type"]
                )
                raise

        if len(self.pushkins) == 0:
            raise RuntimeError(
                "No app IDs are configured. Edit sygnal.yaml to define some."
            )

        logger.info("Configured with app IDs: %r", self.pushkins.keys())


# Path: sygnal/http.py
# class PushGatewayApiServer(object):
#     def __init__(self, sygnal: "Sygnal"):
#         """
#         Initialises the /_matrix/push/* (Push Gateway API) server.
#         Args:
#             sygnal (Sygnal): the Sygnal object
#         """
#         root = Resource()
#         matrix = Resource()
#         push = Resource()
#         v1 = Resource()
# 
#         # Note that using plain strings here will lead to silent failure
#         root.putChild(b"_matrix", matrix)
#         matrix.putChild(b"push", push)
#         push.putChild(b"v1", v1)
#         v1.putChild(b"notify", V1NotifyHandler(sygnal))
# 
#         # add health
#         root.putChild(b"health", HealthHandler())
# 
#         use_x_forwarded_for = sygnal.config["log"]["access"]["x_forwarded_for"]
# 
#         log_formatter = (
#             proxiedLogFormatter if use_x_forwarded_for else combinedLogFormatter
#         )
# 
#         self.site = SygnalLoggedSite(
#             root,
#             reactor=sygnal.reactor,
#             log_formatter=log_formatter,
#             requestFactory=SizeLimitingRequest,
#         )
# 
# Path: sygnal/notifications.py
# class Pushkin(abc.ABC):
#     def __init__(self, name: str, sygnal: "Sygnal", config: Dict[str, Any]):
#         self.name = name
#         self.appid_pattern = glob_to_regex(name, ignore_case=False)
#         self.cfg = config
#         self.sygnal = sygnal
# 
#     @overload
#     def get_config(self, key: str, type_: Type[T], default: T) -> T:
#         ...
# 
#     @overload
#     def get_config(self, key: str, type_: Type[T], default: None = None) -> Optional[T]:
#         ...
# 
#     def get_config(
#         self, key: str, type_: Type[T], default: Optional[T] = None
#     ) -> Optional[T]:
#         if key not in self.cfg:
#             return default
#         if not isinstance(self.cfg[key], type_):
#             raise PushkinSetupException(
#                 f"{key} is of incorrect type, please check that the entry for {key} is "
#                 f"formatted correctly in the config file. "
#             )
#         return self.cfg[key]
# 
#     def handles_appid(self, appid: str) -> bool:
#         """Checks whether the pushkin is responsible for the given app ID"""
#         return self.name == appid or self.appid_pattern.match(appid) is not None
# 
#     @abc.abstractmethod
#     async def dispatch_notification(
#         self, n: Notification, device: Device, context: "NotificationContext"
#     ) -> List[str]:
#         """
#         Args:
#             n: The notification to dispatch via this pushkin
#             device: The device to dispatch the notification for.
#             context: the request context
# 
#         Returns:
#             A list of rejected pushkeys, to be reported back to the homeserver
#         """
#         ...
# 
#     @classmethod
#     async def create(cls, name: str, sygnal: "Sygnal", config: Dict[str, Any]):
#         """
#         Override this if your pushkin needs to call async code in order to
#         be constructed. Otherwise, it defaults to just invoking the Python-standard
#         __init__ constructor.
# 
#         Returns:
#             an instance of this Pushkin
#         """
#         return cls(name, sygnal, config)


# Path: sygnal/sygnal.py
import copy
import importlib
import logging
import logging.config
import os
import sys
import opentracing
import prometheus_client
import yaml
            import sentry_sdk
                    import jaeger_client
from typing import Any, Dict, Set, cast
from opentracing import Tracer
from opentracing.scope_managers.asyncio import AsyncioScopeManager
from twisted.internet import asyncioreactor, defer
from twisted.internet.defer import ensureDeferred
from twisted.internet.interfaces import (
    IReactorCore,
    IReactorFDSet,
    IReactorPluggableNameResolver,
    IReactorTCP,
    IReactorTime,
)
from twisted.python import log as twisted_log
from twisted.python.failure import Failure
from zope.interface import Interface
from sygnal.http import PushGatewayApiServer
from sygnal.notifications import Pushkin

            kind_split = app_type.rsplit(".", 1)
            to_import = kind_split[0]
            to_construct = kind_split[1]
        else:
            to_import = f"sygnal.{app_type}pushkin"
            to_construct = f"{app_type.capitalize()}Pushkin"

        logger.info("Importing pushkin module: %s", to_import)
        pushkin_module = importlib.import_module(to_import)
        logger.info("Creating pushkin: %s", to_construct)
        clarse = getattr(pushkin_module, to_construct)
        return await clarse.create(app_name, self, app_config)

    async def make_pushkins_then_start(self) -> None:
        for app_id, app_cfg in self.config["apps"].items():
            try:
                self.pushkins[app_id] = await self._make_pushkin(app_id, app_cfg)
            except Exception:
                logger.error(
                    "Failed to load and create pushkin for kind '%s'" % app_cfg["type"]
                )
                raise

        if len(self.pushkins) == 0:
            raise RuntimeError(
                "No app IDs are configured. Edit sygnal.yaml to define some."
            )

        logger.info("Configured with app IDs: %r", self.pushkins.keys())


        pushgateway_api = PushGatewayApiServer(self)