Add real-time bridge status push option
This commit is contained in:
@@ -10,6 +10,10 @@ homeserver:
|
|||||||
asmux: false
|
asmux: false
|
||||||
# Number of retries for all HTTP requests if the homeserver isn't reachable.
|
# Number of retries for all HTTP requests if the homeserver isn't reachable.
|
||||||
http_retry_count: 4
|
http_retry_count: 4
|
||||||
|
# The URL to push real-time bridge status to.
|
||||||
|
# If set, the bridge will make POST requests to this URL whenever a user's Telegram connection state changes.
|
||||||
|
# The bridge will use the appservice as_token to authorize requests.
|
||||||
|
status_endpoint: null
|
||||||
|
|
||||||
# Application service host/registration related details
|
# Application service host/registration related details
|
||||||
# Changing these values requires regeneration of the registration.
|
# Changing these values requires regeneration of the registration.
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
from typing import (Awaitable, Dict, List, Iterable, NamedTuple, Optional, Tuple, Any, cast,
|
from typing import (Awaitable, Dict, List, Iterable, NamedTuple, Optional, Tuple, Any, cast,
|
||||||
TYPE_CHECKING)
|
TYPE_CHECKING)
|
||||||
from collections import defaultdict
|
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
import logging
|
import logging
|
||||||
import asyncio
|
import asyncio
|
||||||
@@ -32,7 +31,7 @@ from telethon.tl.functions.account import UpdateStatusRequest
|
|||||||
from mautrix.client import Client
|
from mautrix.client import Client
|
||||||
from mautrix.errors import MatrixRequestError, MNotFound
|
from mautrix.errors import MatrixRequestError, MNotFound
|
||||||
from mautrix.types import UserID, RoomID, PushRuleScope, PushRuleKind, PushActionType, RoomTagInfo
|
from mautrix.types import UserID, RoomID, PushRuleScope, PushRuleKind, PushActionType, RoomTagInfo
|
||||||
from mautrix.bridge import BaseUser
|
from mautrix.bridge import BaseUser, BridgeState
|
||||||
from mautrix.util.logging import TraceLogger
|
from mautrix.util.logging import TraceLogger
|
||||||
from mautrix.util.opt_prometheus import Gauge
|
from mautrix.util.opt_prometheus import Gauge
|
||||||
|
|
||||||
@@ -52,6 +51,11 @@ SearchResult = NamedTuple('SearchResult', puppet='pu.Puppet', similarity=int)
|
|||||||
METRIC_LOGGED_IN = Gauge('bridge_logged_in', 'Users logged into bridge')
|
METRIC_LOGGED_IN = Gauge('bridge_logged_in', 'Users logged into bridge')
|
||||||
METRIC_CONNECTED = Gauge('bridge_connected', 'Users connected to Telegram')
|
METRIC_CONNECTED = Gauge('bridge_connected', 'Users connected to Telegram')
|
||||||
|
|
||||||
|
BridgeState.human_readable_errors.update({
|
||||||
|
"tg-not-connected": "Your Telegram connection failed",
|
||||||
|
"logged-out": "You're not logged into Telegram",
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class User(AbstractUser, BaseUser):
|
class User(AbstractUser, BaseUser):
|
||||||
log: TraceLogger = logging.getLogger("mau.user")
|
log: TraceLogger = logging.getLogger("mau.user")
|
||||||
@@ -74,8 +78,9 @@ class User(AbstractUser, BaseUser):
|
|||||||
saved_contacts: int = 0, is_bot: bool = False,
|
saved_contacts: int = 0, is_bot: bool = False,
|
||||||
db_portals: Optional[Iterable[Tuple[TelegramID, TelegramID]]] = None,
|
db_portals: Optional[Iterable[Tuple[TelegramID, TelegramID]]] = None,
|
||||||
db_instance: Optional[DBUser] = None) -> None:
|
db_instance: Optional[DBUser] = None) -> None:
|
||||||
super().__init__()
|
AbstractUser.__init__(self)
|
||||||
self.mxid = mxid
|
self.mxid = mxid
|
||||||
|
BaseUser.__init__(self)
|
||||||
self.tgid = tgid
|
self.tgid = tgid
|
||||||
self.is_bot = is_bot
|
self.is_bot = is_bot
|
||||||
self.username = username
|
self.username = username
|
||||||
@@ -87,12 +92,8 @@ class User(AbstractUser, BaseUser):
|
|||||||
self.db_portals = db_portals or []
|
self.db_portals = db_portals or []
|
||||||
self._db_instance = db_instance
|
self._db_instance = db_instance
|
||||||
self._ensure_started_lock = asyncio.Lock()
|
self._ensure_started_lock = asyncio.Lock()
|
||||||
self.dm_update_lock = asyncio.Lock()
|
|
||||||
self._metric_value = defaultdict(lambda: False)
|
|
||||||
self._track_connection_task = None
|
self._track_connection_task = None
|
||||||
|
|
||||||
self.command_status = None
|
|
||||||
|
|
||||||
(self.relaybot_whitelisted,
|
(self.relaybot_whitelisted,
|
||||||
self.whitelisted,
|
self.whitelisted,
|
||||||
self.puppet_whitelisted,
|
self.puppet_whitelisted,
|
||||||
@@ -104,8 +105,6 @@ class User(AbstractUser, BaseUser):
|
|||||||
if tgid:
|
if tgid:
|
||||||
self.by_tgid[tgid] = self
|
self.by_tgid[tgid] = self
|
||||||
|
|
||||||
self.log = self.log.getChild(self.mxid)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
return self.mxid
|
return self.mxid
|
||||||
@@ -219,6 +218,21 @@ class User(AbstractUser, BaseUser):
|
|||||||
connected = bool(self.client._sender._transport_connected
|
connected = bool(self.client._sender._transport_connected
|
||||||
if self.client and self.client._sender else False)
|
if self.client and self.client._sender else False)
|
||||||
self._track_metric(METRIC_CONNECTED, connected)
|
self._track_metric(METRIC_CONNECTED, connected)
|
||||||
|
await self.push_bridge_state(ok=connected, ttl=3600 if connected else 240,
|
||||||
|
error="tg-not-connected" if not connected else None)
|
||||||
|
|
||||||
|
async def fill_bridge_state(self, state: BridgeState) -> None:
|
||||||
|
await super().fill_bridge_state(state)
|
||||||
|
state.remote_id = str(self.tgid)
|
||||||
|
state.remote_name = self.human_tg_id
|
||||||
|
|
||||||
|
async def get_bridge_state(self) -> BridgeState:
|
||||||
|
if not self.client:
|
||||||
|
return BridgeState(ok=False, error="logged-out")
|
||||||
|
elif not self.client._sender or not self.client._sender._transport_connected:
|
||||||
|
return BridgeState(ok=False, error="tg-not-connected")
|
||||||
|
else:
|
||||||
|
return BridgeState(ok=True)
|
||||||
|
|
||||||
async def stop(self) -> None:
|
async def stop(self) -> None:
|
||||||
await super().stop()
|
await super().stop()
|
||||||
@@ -226,6 +240,7 @@ class User(AbstractUser, BaseUser):
|
|||||||
self._track_connection_task.cancel()
|
self._track_connection_task.cancel()
|
||||||
self._track_connection_task = None
|
self._track_connection_task = None
|
||||||
self._track_metric(METRIC_CONNECTED, False)
|
self._track_metric(METRIC_CONNECTED, False)
|
||||||
|
await self.push_bridge_state(ok=False, error="tg-not-connected")
|
||||||
|
|
||||||
async def post_login(self, info: TLUser = None, first_login: bool = False) -> None:
|
async def post_login(self, info: TLUser = None, first_login: bool = False) -> None:
|
||||||
if config["metrics.enabled"] and not self._track_connection_task:
|
if config["metrics.enabled"] and not self._track_connection_task:
|
||||||
@@ -330,6 +345,7 @@ class User(AbstractUser, BaseUser):
|
|||||||
self.delete()
|
self.delete()
|
||||||
await self.stop()
|
await self.stop()
|
||||||
self._track_metric(METRIC_LOGGED_IN, False)
|
self._track_metric(METRIC_LOGGED_IN, False)
|
||||||
|
await self.push_bridge_state(ok=False, error="logged-out")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _search_local(self, query: str, max_results: int = 5, min_similarity: int = 45
|
def _search_local(self, query: str, max_results: int = 5, min_similarity: int = 45
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ qrcode>=6,<7
|
|||||||
moviepy>=1,<2
|
moviepy>=1,<2
|
||||||
|
|
||||||
#/metrics
|
#/metrics
|
||||||
prometheus_client>=0.6,<0.11
|
prometheus_client>=0.6,<0.12
|
||||||
|
|
||||||
#/postgres
|
#/postgres
|
||||||
psycopg2-binary>=2,<3
|
psycopg2-binary>=2,<3
|
||||||
|
|
||||||
#/e2be
|
#/e2be
|
||||||
asyncpg>=0.20,<0.23
|
asyncpg>=0.20,<0.24
|
||||||
python-olm>=3,<4
|
python-olm>=3,<4
|
||||||
pycryptodome>=3,<4
|
pycryptodome>=3,<4
|
||||||
unpaddedbase64>=1,<2
|
unpaddedbase64>=1,<2
|
||||||
|
|||||||
+1
-1
@@ -5,6 +5,6 @@ python-magic>=0.4,<0.5
|
|||||||
commonmark>=0.8,<0.10
|
commonmark>=0.8,<0.10
|
||||||
aiohttp>=3,<4
|
aiohttp>=3,<4
|
||||||
yarl>=1,<2
|
yarl>=1,<2
|
||||||
mautrix>=0.9.1,<0.10
|
mautrix>=0.9.3,<0.10
|
||||||
telethon>=1.20,<1.22
|
telethon>=1.20,<1.22
|
||||||
telethon-session-sqlalchemy>=0.2.14,<0.3
|
telethon-session-sqlalchemy>=0.2.14,<0.3
|
||||||
|
|||||||
Reference in New Issue
Block a user