diff --git a/ntfy/bot.py b/ntfy/bot.py
index 918b9ab..297fee1 100644
--- a/ntfy/bot.py
+++ b/ntfy/bot.py
@@ -1,13 +1,14 @@
import asyncio
from html import escape
import json
-from typing import Any, Dict, Tuple, List, Awaitable, Callable
+from typing import Any, Dict, Tuple, List, Awaitable, Callable, NamedTuple
from aiohttp import ClientTimeout
from maubot import MessageEvent, Plugin
from maubot.handlers import command
from mautrix.types import (EventType, Format, MessageType,
- TextMessageEventContent, RoomID, EventID)
+ TextMessageEventContent, RoomID, EventID,
+ MediaMessageEventContent, ImageInfo, ContentURI)
from mautrix.util.async_db import UpgradeTable
from mautrix.util.config import BaseProxyConfig
from mautrix.util.formatter import parse_html
@@ -18,6 +19,13 @@ from .emoji import (EMOJI_FALLBACK, WHITE_CHECK_MARK, REPEAT, NO_ENTRY,
WARNING, parse_tags)
from .exceptions import SubscriptionError
+Media = NamedTuple("Media", [
+ ("name", str),
+ ("mime_type", str),
+ ("url", str),
+ ("size", int),
+])
+
async def build_notice(html_content) -> TextMessageEventContent:
"""
@@ -53,6 +61,18 @@ def ensure_permission(func: Callable):
return wrapper
+def extract_media(message) -> Media | None:
+ media = message.get("attachment", None)
+
+ if media:
+ return Media(name=media.get("name", None),
+ mime_type=media.get("type", None),
+ url=media.get("url", None),
+ size=media.get("size", None))
+
+ return
+
+
class NtfyBot(Plugin):
db: DB
config: Config
@@ -491,6 +511,8 @@ class NtfyBot(Plugin):
# Build matrix message
html_content = self.build_message_content(
topic.server, message)
+ media = extract_media(message)
+ media_content = None
text_content = await parse_html(html_content.strip())
content = TextMessageEventContent(
msgtype=MessageType.NOTICE,
@@ -498,15 +520,39 @@ class NtfyBot(Plugin):
formatted_body=html_content,
body=text_content,
)
+ if media and media.mime_type in ["image/jpeg", "image/png"]:
+ media_content = MediaMessageEventContent(
+ msgtype=MessageType.IMAGE,
+ url=ContentURI(media.url),
+ body=media.name,
+ info=ImageInfo(
+ mimetype=media.mime_type,
+ size=media.size,
+ ),
+ )
+ elif media:
+ media_content = MediaMessageEventContent(
+ msgtype=MessageType.FILE,
+ url=ContentURI(media.url),
+ body=media.name,
+ info=ImageInfo(
+ mimetype=media.mime_type,
+ size=media.size,
+ ),
+ )
# Broadcast the message to all subscribed rooms
subscriptions = await self.db.get_subscriptions_by_topic_id(
topic.id)
room_ids = [sub.room_id for sub in subscriptions]
await self.broadcast_to_rooms(room_ids, content)
+ if media_content:
+ await self.broadcast_to_rooms(room_ids, media_content)
- async def broadcast_to_rooms(self, room_ids: List[RoomID],
- content: TextMessageEventContent):
+ async def broadcast_to_rooms(self,
+ room_ids: List[RoomID],
+ content: (TextMessageEventContent |
+ MediaMessageEventContent)) -> None:
"""
Broadcast a message to multiple rooms concurrently.
:param room_ids:
@@ -614,7 +660,6 @@ class NtfyBot(Plugin):
title = message.get("title", None)
tags = message.get("tags", None)
click = message.get("click", None)
- attachment = message.get("attachment", None)
if tags:
(emoji, non_emoji) = parse_tags(self.log, tags)
@@ -648,12 +693,6 @@ class NtfyBot(Plugin):
html_content += "
Tags: %s" % escape(
tags)
- # build attachment
- if attachment:
- html_content += "
View %s" % (escape(
- attachment["url"]), escape(attachment["name"]))
- html_content += ""
-
return html_content
@classmethod