# Path: sygnal/exceptions.py
# class InvalidNotificationException(Exception):
#     pass
# 
# class NotificationDispatchException(Exception):
#     pass
# 
# class PushkinSetupException(Exception):
#     pass


import abc
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type, TypeVar, overload
from matrix_common.regex import glob_to_regex
from opentracing import Span
from prometheus_client import Counter
from sygnal.exceptions import (
    InvalidNotificationException,
    NotificationDispatchException,
    PushkinSetupException,
)
    from sygnal.sygnal import Sygnal
        self.sound: Optional[str] = get_key(raw, "sound", str)


class Device:
    def __init__(self, raw: Dict[str, Any]):
        if "app_id" not in raw or not isinstance(raw["app_id"], str):
            raise InvalidNotificationException(
                "Device with missing or non-string app_id"
            )
        self.app_id: str = raw["app_id"]
        if "pushkey" not in raw or not isinstance(raw["pushkey"], str):
            raise InvalidNotificationException(
                "Device with missing or non-string pushkey"
            )
        self.pushkey: str = raw["pushkey"]

        self.pushkey_ts: int = get_key(raw, "pushkey_ts", int, 0)
        self.data: Optional[Dict[str, Any]] = get_key(raw, "data", dict)
        self.tweaks = Tweaks(get_key(raw, "tweaks", dict, {}))


class Counts:
    def __init__(self, raw: Dict[str, Any]):
        self.unread: Optional[int] = get_key(raw, "unread", int)
        self.missed_calls: Optional[int] = get_key(raw, "missed_calls", int)


class Notification:
    def __init__(self, notif):
        # optional attributes

# Path: sygnal/exceptions.py
# class InvalidNotificationException(Exception):
#     pass
# 
# class NotificationDispatchException(Exception):
#     pass
# 
# class PushkinSetupException(Exception):
#     pass


# Path: sygnal/notifications.py
import abc
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type, TypeVar, overload
from matrix_common.regex import glob_to_regex
from opentracing import Span
from prometheus_client import Counter
from sygnal.exceptions import (
    InvalidNotificationException,
    NotificationDispatchException,
    PushkinSetupException,
)
    from sygnal.sygnal import Sygnal

        self.sound: Optional[str] = get_key(raw, "sound", str)


class Device:
    def __init__(self, raw: Dict[str, Any]):
        if "app_id" not in raw or not isinstance(raw["app_id"], str):
            raise InvalidNotificationException(
                "Device with missing or non-string app_id"
            )
        self.app_id: str = raw["app_id"]
        if "pushkey" not in raw or not isinstance(raw["pushkey"], str):
            raise InvalidNotificationException(
                "Device with missing or non-string pushkey"
            )
        self.pushkey: str = raw["pushkey"]

        self.pushkey_ts: int = get_key(raw, "pushkey_ts", int, 0)
        self.data: Optional[Dict[str, Any]] = get_key(raw, "data", dict)
        self.tweaks = Tweaks(get_key(raw, "tweaks", dict, {}))


class Counts:
    def __init__(self, raw: Dict[str, Any]):
        self.unread: Optional[int] = get_key(raw, "unread", int)
        self.missed_calls: Optional[int] = get_key(raw, "missed_calls", int)


class Notification:
    def __init__(self, notif):
        # optional attributes

        self.room_name: Optional[str] = notif.get("room_name")