示例#1
0
 def _filter_events(self, room_id: RoomID,
                    events: List[Dict]) -> Iterator[Event]:
     # We only want events about the custom puppet user, but we can't use
     # filters for typing and read receipt events.
     for event in events:
         event["room_id"] = room_id
         evt_type = EventType.find(event.get("type", None))
         event.setdefault("content", {})
         if evt_type == EventType.TYPING:
             is_typing = self.custom_mxid in event["content"].get(
                 "user_ids", [])
             event["content"]["user_ids"] = [self.custom_mxid
                                             ] if is_typing else []
         elif evt_type == EventType.RECEIPT:
             val = None
             evt = None
             for event_id in event["content"]:
                 try:
                     val = event["content"][event_id]["m.read"][
                         self.custom_mxid]
                     evt = event_id
                     break
                 except KeyError:
                     pass
             if val and evt:
                 event["content"] = {
                     evt: {
                         "m.read": {
                             self.custom_mxid: val
                         }
                     }
                 }
             else:
                 continue
         yield event
示例#2
0
 def _filter_events(self, room_id: RoomID,
                    events: List[Dict]) -> Iterator[Event]:
     for event in events:
         event["room_id"] = room_id
         if self.only_handle_own_synced_events:
             # We only want events about the custom puppet user, but we can't use
             # filters for typing and read receipt events.
             evt_type = EventType.find(event.get("type", None))
             event.setdefault("content", {})
             if evt_type == EventType.TYPING:
                 is_typing = self.custom_mxid in event["content"].get(
                     "user_ids", [])
                 event["content"]["user_ids"] = [self.custom_mxid
                                                 ] if is_typing else []
             elif evt_type == EventType.RECEIPT:
                 try:
                     event_id, receipt = event["content"].popitem()
                     data = receipt["m.read"][self.custom_mxid]
                     event["content"] = {
                         event_id: {
                             "m.read": {
                                 self.custom_mxid: data
                             }
                         }
                     }
                 except KeyError:
                     continue
         yield event
示例#3
0
 async def encrypt(
         self, room_id: RoomID, event_type: EventType,
         content: Union[Serializable, JSON]) -> Tuple[EventType, JSON]:
     serialized = content.serialize() if isinstance(
         content, Serializable) else content
     type_str = str(event_type)
     retries = 0
     while True:
         try:
             type_str, encrypted = self.client.encrypt(
                 room_id, type_str, serialized)
             break
         except GroupEncryptionError:
             if retries > 3:
                 self.log.error("Got GroupEncryptionError again, giving up")
                 raise
             retries += 1
             self.log.debug(
                 "Got GroupEncryptionError, sharing group session and trying again"
             )
             await self.client.share_group_session(
                 room_id, ignore_unverified_devices=True)
     event_type = EventType.find(type_str)
     try:
         encrypted["m.relates_to"] = serialized["m.relates_to"]
     except KeyError:
         pass
     return event_type, encrypted
示例#4
0
 def _make_template(self, name: str, tpl: Dict[str, Any]) -> Template:
     try:
         return Template(type=EventType.find(tpl.get("type", "m.room.message")),
                         variables=self._parse_variables(tpl),
                         content=self._parse_content(tpl.get("content", None))).init()
     except Exception as e:
         raise ConfigError(f"Failed to load {name}") from e
示例#5
0
def get_base_power_levels(portal: po.Portal,
                          levels: PowerLevelContent = None,
                          entity: TypeChat = None) -> PowerLevelContent:
    levels = levels or PowerLevelContent()
    if portal.peer_type == "user":
        overrides = portal.config["bridge.initial_power_level_overrides.user"]
        levels.ban = overrides.get("ban", 100)
        levels.kick = overrides.get("kick", 100)
        levels.invite = overrides.get("invite", 100)
        levels.redact = overrides.get("redact", 0)
        levels.events[EventType.ROOM_NAME] = 0
        levels.events[EventType.ROOM_AVATAR] = 0
        levels.events[EventType.ROOM_TOPIC] = 0
        levels.state_default = overrides.get("state_default", 0)
        levels.users_default = overrides.get("users_default", 0)
        levels.events_default = overrides.get("events_default", 0)
    else:
        overrides = portal.config["bridge.initial_power_level_overrides.group"]
        dbr = entity.default_banned_rights
        if not dbr:
            portal.log.debug(f"default_banned_rights is None in {entity}")
            dbr = ChatBannedRights(
                invite_users=True,
                change_info=True,
                pin_messages=True,
                send_stickers=False,
                send_messages=False,
                until_date=None,
            )
        levels.ban = overrides.get("ban", 50)
        levels.kick = overrides.get("kick", 50)
        levels.redact = overrides.get("redact", 50)
        levels.invite = overrides.get("invite", 50 if dbr.invite_users else 0)
        levels.events[
            EventType.ROOM_ENCRYPTION] = 50 if portal.matrix.e2ee else 99
        levels.events[EventType.ROOM_TOMBSTONE] = 99
        levels.events[EventType.ROOM_NAME] = 50 if dbr.change_info else 0
        levels.events[EventType.ROOM_AVATAR] = 50 if dbr.change_info else 0
        levels.events[EventType.ROOM_TOPIC] = 50 if dbr.change_info else 0
        levels.events[
            EventType.ROOM_PINNED_EVENTS] = 50 if dbr.pin_messages else 0
        levels.events[EventType.ROOM_POWER_LEVELS] = 75
        levels.events[EventType.ROOM_HISTORY_VISIBILITY] = 75
        levels.events[
            EventType.
            STICKER] = 50 if dbr.send_stickers else levels.events_default
        levels.state_default = overrides.get("state_default", 50)
        levels.users_default = overrides.get("users_default", 0)
        levels.events_default = overrides.get(
            "events_default",
            50 if (portal.peer_type == "channel" and not entity.megagroup
                   or entity.default_banned_rights.send_messages) else 0,
        )
    for evt_type, value in overrides.get("events", {}).items():
        levels.events[EventType.find(evt_type)] = value
    levels.users = overrides.get("users", {})
    if portal.main_intent.mxid not in levels.users:
        levels.users[portal.main_intent.mxid] = 100
    return levels
async def user_has_power_level(room_id: RoomID, intent: IntentAPI, sender: u.User,
                               event: str) -> bool:
    if sender.is_admin:
        return True
    # Make sure the state store contains the power levels.
    try:
        await intent.get_power_levels(room_id)
    except MatrixRequestError:
        return False
    event_type = EventType.find(f"net.maunium.telegram.{event}", t_class=EventType.Class.STATE)
    return await intent.state_store.has_power_level(room_id, sender.mxid, event_type)
示例#7
0
 def _make_rule(self, name: str, rule: Dict[str, Any]) -> Rule:
     try:
         return Rule(rooms=set(rule.get("rooms", [])),
                     not_rooms=set(rule.get("not_rooms", [])),
                     matches=self._compile_all(rule["matches"]),
                     not_matches=self._compile_all(rule.get("not_matches", [])),
                     type=EventType.find(rule["type"]) if "type" in rule else None,
                     template=self.templates[rule["template"]],
                     variables=self._parse_variables(rule))
     except Exception as e:
         raise ConfigError(f"Failed to load {name}") from e
示例#8
0
 async def can_user_perform(self, user: '******', event: str) -> bool:
     if user.is_admin:
         return True
     if not self.mxid:
         # No room for anybody to perform actions in
         return False
     try:
         await self.main_intent.get_power_levels(self.mxid)
     except MatrixRequestError:
         return False
     evt_type = EventType.find(f"net.maunium.telegram.{event}", t_class=EventType.Class.STATE)
     return await self.main_intent.state_store.has_power_level(self.mxid, user.mxid, evt_type)
示例#9
0
 def _filter(self) -> Filter:
     all_events = EventType.find("*")
     return Filter(
         account_data=EventFilter(types=[all_events]),
         presence=EventFilter(not_types=[all_events]),
         room=RoomFilter(
             include_leave=False,
             state=StateFilter(not_types=[all_events]),
             timeline=RoomEventFilter(not_types=[all_events]),
             account_data=RoomEventFilter(not_types=[all_events]),
             ephemeral=RoomEventFilter(not_types=[all_events]),
         ),
     )
示例#10
0
 def _create_sync_filter(self) -> Awaitable[FilterID]:
     all_events = EventType.find("*")
     return self.intent.create_filter(
         Filter(
             account_data=EventFilter(types=[all_events]),
             presence=EventFilter(
                 types=[EventType.PRESENCE],
                 senders=[self.custom_mxid]
                 if self.only_handle_own_synced_events else None,
             ),
             room=RoomFilter(
                 include_leave=False,
                 state=StateFilter(not_types=[all_events]),
                 timeline=RoomEventFilter(not_types=[all_events]),
                 account_data=RoomEventFilter(not_types=[all_events]),
                 ephemeral=RoomEventFilter(types=[
                     EventType.TYPING,
                     EventType.RECEIPT,
                 ]),
             ),
         ))
示例#11
0
from mautrix.errors import MatrixError, MForbidden
from mautrix.util.simple_lock import SimpleLock

from .db import Portal as DBPortal, Message as DBMessage, Reaction as DBReaction
from .config import Config
from . import user as u, puppet as p, matrix as m

if TYPE_CHECKING:
    from .__main__ import TwitterBridge

try:
    from mautrix.crypto.attachments import encrypt_attachment, decrypt_attachment
except ImportError:
    encrypt_attachment = decrypt_attachment = None

StateBridge = EventType.find("m.bridge", EventType.Class.STATE)
StateHalfShotBridge = EventType.find("uk.half-shot.bridge",
                                     EventType.Class.STATE)
BackfillEntryTypes = Union[MessageEntry, ReactionCreateEntry,
                           ReactionDeleteEntry]
ReuploadedMediaInfo = NamedTuple('ReuploadedMediaInfo',
                                 mxc=Optional[ContentURI],
                                 decryption_info=Optional[EncryptedFile],
                                 mime_type=str,
                                 file_name=str,
                                 size=int)


class Portal(DBPortal, BasePortal):
    by_mxid: Dict[RoomID, 'Portal'] = {}
    by_twid: Dict[Tuple[str, int], 'Portal'] = {}
示例#12
0
文件: bot.py 项目: maubot/rss
from string import Template
import asyncio

import aiohttp
import hashlib
import feedparser

from mautrix.util.config import BaseProxyConfig, ConfigUpdateHelper
from mautrix.types import (StateEvent, EventType, MessageType, RoomID, EventID,
                           PowerLevelStateEventContent)
from maubot import Plugin, MessageEvent
from maubot.handlers import command, event

from .db import Database, Feed, Entry, Subscription

rss_change_level = EventType.find("xyz.maubot.rss", t_class=EventType.Class.STATE)


class Config(BaseProxyConfig):
    def do_update(self, helper: ConfigUpdateHelper) -> None:
        helper.copy("update_interval")
        helper.copy("max_backoff")
        helper.copy("spam_sleep")
        helper.copy("command_prefix")
        helper.copy("admins")


class BoolArgument(command.Argument):
    def __init__(self, name: str, label: str = None, *, required: bool = False) -> None:
        super().__init__(name, label, required=required, pass_raw=False)