1 """Pushbullet platform for notify component."""
3 from __future__
import annotations
7 from typing
import TYPE_CHECKING, Any
9 from pushbullet
import PushBullet, PushError
10 from pushbullet.channel
import Channel
11 from pushbullet.device
import Device
12 import voluptuous
as vol
19 BaseNotificationService,
25 from .api
import PushBulletNotificationProvider
26 from .const
import ATTR_FILE, ATTR_FILE_URL, ATTR_URL, DOMAIN
28 _LOGGER = logging.getLogger(__name__)
34 discovery_info: DiscoveryInfoType |
None =
None,
35 ) -> PushBulletNotificationService |
None:
36 """Get the Pushbullet notification service."""
38 assert discovery_info
is not None
39 pb_provider: PushBulletNotificationProvider = hass.data[DOMAIN][
40 discovery_info[
"entry_id"]
46 """Implement the notification service for Pushbullet."""
48 def __init__(self, hass: HomeAssistant, pushbullet: PushBullet) ->
None:
49 """Initialize the service."""
54 def pbtargets(self) -> dict[str, dict[str, Device | Channel]]:
55 """Return device and channel detected targets."""
57 "device": {tgt.nickname.lower(): tgt
for tgt
in self.
pushbulletpushbullet.devices},
59 tgt.channel_tag.lower(): tgt
for tgt
in self.
pushbulletpushbullet.channels
64 """Send a message to a specified target.
66 If no target specified, a 'normal' push will be sent to all devices
67 linked to the Pushbullet account.
68 Email is special, these are assumed to always exist. We use a special
69 call which doesn't require a push object.
71 targets: list[str] = kwargs.get(ATTR_TARGET, [])
72 title: str = kwargs.get(ATTR_TITLE, ATTR_TITLE_DEFAULT)
73 data: dict[str, Any] = kwargs[ATTR_DATA]
or {}
78 _LOGGER.debug(
"Sent notification to self")
85 for target
in targets:
87 ttype, tname = target.split(
"/", 1)
88 except ValueError
as err:
89 raise ValueError(f
"Invalid target syntax: '{target}'")
from err
95 _LOGGER.debug(
"Sent notification to email %s", tname)
101 message, title, data, self.
pushbulletpushbullet, phonenumber=tname
103 _LOGGER.debug(
"Sent sms notification to %s", tname)
107 raise ValueError(f
"Invalid target syntax: {target}")
109 tname = tname.lower()
111 if tname
not in self.
pbtargetspbtargets[ttype]:
112 raise ValueError(f
"Target: {target} doesn't exist")
117 _LOGGER.debug(
"Sent notification to %s/%s", ttype, tname)
123 data: dict[str, Any],
125 email: str |
None =
None,
126 phonenumber: str |
None =
None,
128 """Create the message content."""
129 kwargs = {
"body": message,
"title": title}
131 kwargs[
"email"] = email
134 if phonenumber
and pusher.devices:
135 pusher.push_sms(pusher.devices[0], phonenumber, message)
137 if url := data.get(ATTR_URL):
138 pusher.push_link(url=url, **kwargs)
140 if filepath := data.get(ATTR_FILE):
141 if not self.
hasshass.config.is_allowed_path(filepath):
142 raise ValueError(
"Filepath is not valid or allowed")
143 with open(filepath,
"rb")
as fileh:
144 filedata = self.
pushbulletpushbullet.upload_file(fileh, filepath)
145 if filedata.get(
"file_type") ==
"application/x-empty":
146 raise ValueError(
"Cannot send an empty file")
147 kwargs.update(filedata)
148 pusher.push_file(**kwargs)
149 elif (file_url := data.get(ATTR_FILE_URL))
and vol.Url(file_url):
153 file_type=(mimetypes.guess_type(file_url)[0]),
157 pusher.push_note(**kwargs)
158 except PushError
as err:
dict[str, dict[str, Device|Channel]] pbtargets(self)
None __init__(self, HomeAssistant hass, PushBullet pushbullet)
None _push_data(self, str message, str title, dict[str, Any] data, PushBullet pusher, str|None email=None, str|None phonenumber=None)
None send_message(self, str message, **Any kwargs)
None open(self, **Any kwargs)
PushBulletNotificationService|None async_get_service(HomeAssistant hass, ConfigType config, DiscoveryInfoType|None discovery_info=None)