# Path: autopush/constants.py
# DEFAULT_ROUTER_TIMEOUT = 3
# 
# Path: autopush/exceptions.py
# class RouterException(AutopushException):
#     """Exception if routing has failed, may include a custom status_code and
#     body to write to the response.
# 
#     """
#     def __init__(self, message, status_code=500, response_body="",
#                  router_data=None, headers=None, log_exception=True,
#                  errno=None, logged_status=None, **kwargs):
#         """Create a new RouterException"""
#         super(AutopushException, self).__init__(message)
#         self.status_code = status_code
#         self.headers = {} if headers is None else headers
#         self.log_exception = log_exception
#         self.response_body = response_body or message
#         self.errno = errno
#         self.logged_status = logged_status
#         self.extra = kwargs
# 
# Path: autopush/metrics.py
# def make_tags(base=None, **kwargs):
#     # type: (Sequence[str], **Any) -> Sequence[str]
#     """Generate a list of tag values"""
#     tags = list(base or [])
#     tags.extend('{}:{}'.format(key, val) for key, val in kwargs.iteritems())
#     return tags
# 
# Path: autopush/router/interface.py
# class RouterResponse(object):
#     """Router response if routing has succeeded.
# 
#     If the router data needs to change as a result of this message, either the
#     router got invalidated, or needs updating, then the router_data should be
#     set.
# 
#     """
#     def __init__(self, status_code=200, response_body="", router_data=None,
#                  headers=None, errno=None, logged_status=None):
#         """Create a new RouterResponse"""
#         self.status_code = status_code
#         self.response_body = response_body
#         self.router_data = router_data
#         self.headers = {} if headers is None else headers
#         self.errno = errno
#         self.logged_status = logged_status
# 
# Path: autopush/types.py



import time
import requests
from typing import Any  # noqa
from requests.exceptions import ConnectionError, Timeout
from twisted.internet.threads import deferToThread
from twisted.logger import Logger
from autopush.constants import DEFAULT_ROUTER_TIMEOUT
from autopush.exceptions import RouterException
from autopush.metrics import make_tags
from autopush.router.interface import RouterResponse
from autopush.types import JSONDict  # noqa
            data["consolidationKey"] = collapseKey
        data["data"] = payload
        url = ("https://api.amazon.com/messaging/registrations"
               "/{}/messages".format(reg_id))
        resp = self._request.post(
            url,
            json=data,
            headers=headers,
            timeout=self._timeout,
        )
        # in fine tradition, the response message can sometimes be less than
        # helpful. Still, good idea to include it anyway.
        if resp.status_code != 200:
            self._logger.error("Could not send ADM message: " + resp.text)
            raise RouterException(resp.content)


class ADMRouter(object):
    """Amazon Device Messaging Router Implementation"""
    log = Logger()
    dryRun = 0
    collapseKey = None
    MAX_TTL = 2419200

    def __init__(self, conf, router_conf, metrics):
        """Create a new ADM router and connect to ADM"""
        self.conf = conf
        self.router_conf = router_conf
        self.metrics = metrics
        self.min_ttl = router_conf.get("ttl", 60)

# Path: autopush/constants.py
# DEFAULT_ROUTER_TIMEOUT = 3
# 
# Path: autopush/exceptions.py
# class RouterException(AutopushException):
#     """Exception if routing has failed, may include a custom status_code and
#     body to write to the response.
# 
#     """
#     def __init__(self, message, status_code=500, response_body="",
#                  router_data=None, headers=None, log_exception=True,
#                  errno=None, logged_status=None, **kwargs):
#         """Create a new RouterException"""
#         super(AutopushException, self).__init__(message)
#         self.status_code = status_code
#         self.headers = {} if headers is None else headers
#         self.log_exception = log_exception
#         self.response_body = response_body or message
#         self.errno = errno
#         self.logged_status = logged_status
#         self.extra = kwargs
# 
# Path: autopush/metrics.py
# def make_tags(base=None, **kwargs):
#     # type: (Sequence[str], **Any) -> Sequence[str]
#     """Generate a list of tag values"""
#     tags = list(base or [])
#     tags.extend('{}:{}'.format(key, val) for key, val in kwargs.iteritems())
#     return tags
# 
# Path: autopush/router/interface.py
# class RouterResponse(object):
#     """Router response if routing has succeeded.
# 
#     If the router data needs to change as a result of this message, either the
#     router got invalidated, or needs updating, then the router_data should be
#     set.
# 
#     """
#     def __init__(self, status_code=200, response_body="", router_data=None,
#                  headers=None, errno=None, logged_status=None):
#         """Create a new RouterResponse"""
#         self.status_code = status_code
#         self.response_body = response_body
#         self.router_data = router_data
#         self.headers = {} if headers is None else headers
#         self.errno = errno
#         self.logged_status = logged_status
# 
# Path: autopush/types.py



# Path: autopush/router/adm.py
import time
import requests
from typing import Any  # noqa
from requests.exceptions import ConnectionError, Timeout
from twisted.internet.threads import deferToThread
from twisted.logger import Logger
from autopush.constants import DEFAULT_ROUTER_TIMEOUT
from autopush.exceptions import RouterException
from autopush.metrics import make_tags
from autopush.router.interface import RouterResponse
from autopush.types import JSONDict  # noqa

            data["consolidationKey"] = collapseKey
        data["data"] = payload
        url = ("https://api.amazon.com/messaging/registrations"
               "/{}/messages".format(reg_id))
        resp = self._request.post(
            url,
            json=data,
            headers=headers,
            timeout=self._timeout,
        )
        # in fine tradition, the response message can sometimes be less than
        # helpful. Still, good idea to include it anyway.
        if resp.status_code != 200:
            self._logger.error("Could not send ADM message: " + resp.text)
            raise RouterException(resp.content)


class ADMRouter(object):
    """Amazon Device Messaging Router Implementation"""
    log = Logger()
    dryRun = 0
    collapseKey = None
    MAX_TTL = 2419200

    def __init__(self, conf, router_conf, metrics):
        """Create a new ADM router and connect to ADM"""
        self.conf = conf
        self.router_conf = router_conf
        self.metrics = metrics
        self.min_ttl = router_conf.get("ttl", 60)

        timeout = router_conf.get("timeout", DEFAULT_ROUTER_TIMEOUT)