Merge branch 'master' into next-native-replies
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# matrix-appservice-python - A Matrix Application Service framework written in Python.
|
# matrix-appservice-python - A Matrix Application Service framework written in Python.
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# matrix-appservice-python - A Matrix Application Service framework written in Python.
|
# matrix-appservice-python - A Matrix Application Service framework written in Python.
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
@@ -268,7 +269,7 @@ async def telegram_event_to_matrix(evt, source, native_replies=False, message_li
|
|||||||
sender = event['sender']
|
sender = event['sender']
|
||||||
puppet = p.Puppet.get_by_mxid(sender, create=False)
|
puppet = p.Puppet.get_by_mxid(sender, create=False)
|
||||||
displayname = puppet.displayname if puppet else sender
|
displayname = puppet.displayname if puppet else sender
|
||||||
reply_to_user = (f"<a href='https://matrix.to/#/{sender}'>{displayname}</a>")
|
reply_to_user = f"<a href='https://matrix.to/#/{sender}'>{displayname}</a>"
|
||||||
reply_to_msg = (("<a href='https://matrix.to/#/"
|
reply_to_msg = (("<a href='https://matrix.to/#/"
|
||||||
+ f"{msg.mx_room}/{msg.mxid}'>{reply_text}</a>")
|
+ f"{msg.mx_room}/{msg.mxid}'>{reply_text}</a>")
|
||||||
if message_link_in_reply else "Reply")
|
if message_link_in_reply else "Reply")
|
||||||
@@ -280,7 +281,7 @@ async def telegram_event_to_matrix(evt, source, native_replies=False, message_li
|
|||||||
else:
|
else:
|
||||||
html = quote + escape(text)
|
html = quote + escape(text)
|
||||||
|
|
||||||
if evt.post and evt.post_author:
|
if isinstance(evt, Message) and evt.post and evt.post_author:
|
||||||
if not html:
|
if not html:
|
||||||
html = escape(text)
|
html = escape(text)
|
||||||
text += f"\n- {evt.post_author}"
|
text += f"\n- {evt.post_author}"
|
||||||
@@ -360,10 +361,11 @@ def _telegram_to_matrix(text, entities):
|
|||||||
skip_entity = True
|
skip_entity = True
|
||||||
elif entity_type == MessageEntityEmail:
|
elif entity_type == MessageEntityEmail:
|
||||||
html.append(f"<a href='mailto:{entity_text}'>{entity_text}</a>")
|
html.append(f"<a href='mailto:{entity_text}'>{entity_text}</a>")
|
||||||
elif entity_type == MessageEntityUrl:
|
elif entity_type in {MessageEntityTextUrl, MessageEntityUrl}:
|
||||||
html.append(f"<a href='{entity_text}'>{entity_text}</a>")
|
url = escape(entity.url) if entity_type == MessageEntityTextUrl else entity_text
|
||||||
elif entity_type == MessageEntityTextUrl:
|
if not url.startswith(("https://", "http://", "ftp://", "magnet://")):
|
||||||
html.append(f"<a href='{escape(entity.url)}'>{entity_text}</a>")
|
url = "http://" + url
|
||||||
|
html.append(f"<a href='{url}'>{entity_text}</a>")
|
||||||
elif entity_type == MessageEntityBotCommand:
|
elif entity_type == MessageEntityBotCommand:
|
||||||
html.append(f"<font color='blue'>!{entity_text[1:]}")
|
html.append(f"<font color='blue'>!{entity_text[1:]}")
|
||||||
elif entity_type == MessageEntityHashtag:
|
elif entity_type == MessageEntityHashtag:
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
@@ -440,14 +441,13 @@ class Portal:
|
|||||||
del self.by_tgid[self.tgid_full]
|
del self.by_tgid[self.tgid_full]
|
||||||
del self.by_mxid[self.mxid]
|
del self.by_mxid[self.mxid]
|
||||||
elif source and source.tgid != user.tgid:
|
elif source and source.tgid != user.tgid:
|
||||||
target = await user.get_input_entity(source)
|
|
||||||
if self.peer_type == "chat":
|
if self.peer_type == "chat":
|
||||||
await source.client(DeleteChatUserRequest(chat_id=self.tgid, user_id=target))
|
await source.client(DeleteChatUserRequest(chat_id=self.tgid, user_id=user.tgid))
|
||||||
else:
|
else:
|
||||||
channel = await self.get_input_entity(source)
|
channel = await self.get_input_entity(source)
|
||||||
rights = ChannelBannedRights(datetime.fromtimestamp(0), True)
|
rights = ChannelBannedRights(datetime.fromtimestamp(0), True)
|
||||||
await source.client(EditBannedRequest(channel=channel,
|
await source.client(EditBannedRequest(channel=channel,
|
||||||
user_id=target,
|
user_id=user.tgid,
|
||||||
banned_rights=rights))
|
banned_rights=rights))
|
||||||
elif self.peer_type == "chat":
|
elif self.peer_type == "chat":
|
||||||
await user.client(DeleteChatUserRequest(chat_id=self.tgid, user_id=InputUserSelf()))
|
await user.client(DeleteChatUserRequest(chat_id=self.tgid, user_id=InputUserSelf()))
|
||||||
@@ -661,8 +661,7 @@ class Portal:
|
|||||||
await source.client(
|
await source.client(
|
||||||
AddChatUserRequest(chat_id=self.tgid, user_id=puppet.tgid, fwd_limit=0))
|
AddChatUserRequest(chat_id=self.tgid, user_id=puppet.tgid, fwd_limit=0))
|
||||||
elif self.peer_type == "channel":
|
elif self.peer_type == "channel":
|
||||||
target = await puppet.get_input_entity(source)
|
await source.client(InviteToChannelRequest(channel=self.peer, users=[puppet.tgid]))
|
||||||
await source.client(InviteToChannelRequest(channel=self.peer, users=[target]))
|
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid peer type for Telegram user invite")
|
raise ValueError("Invalid peer type for Telegram user invite")
|
||||||
|
|
||||||
@@ -689,7 +688,7 @@ class Portal:
|
|||||||
name = media.caption
|
name = media.caption
|
||||||
await intent.set_typing(self.mxid, is_typing=False)
|
await intent.set_typing(self.mxid, is_typing=False)
|
||||||
return await intent.send_image(self.mxid, uploaded["content_uri"], info=info,
|
return await intent.send_image(self.mxid, uploaded["content_uri"], info=info,
|
||||||
text=name, relates_to=relates_to)
|
text=name, relates_to=relates_to)
|
||||||
|
|
||||||
def convert_webp(self, file, to="png"):
|
def convert_webp(self, file, to="png"):
|
||||||
try:
|
try:
|
||||||
@@ -732,7 +731,7 @@ class Portal:
|
|||||||
type = "m.image"
|
type = "m.image"
|
||||||
await intent.set_typing(self.mxid, is_typing=False)
|
await intent.set_typing(self.mxid, is_typing=False)
|
||||||
return await intent.send_file(self.mxid, uploaded["content_uri"], info=info,
|
return await intent.send_file(self.mxid, uploaded["content_uri"], info=info,
|
||||||
text=name, file_type=type, relates_to=relates_to)
|
text=name, file_type=type, relates_to=relates_to)
|
||||||
|
|
||||||
def handle_telegram_location(self, source, intent, location, relates_to=None):
|
def handle_telegram_location(self, source, intent, location, relates_to=None):
|
||||||
long = location.long
|
long = location.long
|
||||||
@@ -770,7 +769,7 @@ class Portal:
|
|||||||
await intent.set_typing(self.mxid, is_typing=False)
|
await intent.set_typing(self.mxid, is_typing=False)
|
||||||
return await intent.send_text(self.mxid, text, html=html, relates_to=relates_to)
|
return await intent.send_text(self.mxid, text, html=html, relates_to=relates_to)
|
||||||
|
|
||||||
async def handle_telegram_edit(self, source, intent, evt):
|
async def handle_telegram_edit(self, source, sender, evt):
|
||||||
if not self.mxid:
|
if not self.mxid:
|
||||||
return
|
return
|
||||||
elif not config["bridge.edits_as_replies"]:
|
elif not config["bridge.edits_as_replies"]:
|
||||||
@@ -782,6 +781,7 @@ class Portal:
|
|||||||
config["bridge.native_replies"],
|
config["bridge.native_replies"],
|
||||||
config["bridge.link_in_reply"],
|
config["bridge.link_in_reply"],
|
||||||
self.main_intent, reply_text="Edit")
|
self.main_intent, reply_text="Edit")
|
||||||
|
intent = sender.intent if sender else self.main_intent
|
||||||
await intent.set_typing(self.mxid, is_typing=False)
|
await intent.set_typing(self.mxid, is_typing=False)
|
||||||
response = await intent.send_text(self.mxid, text, html=html, relates_to=relates_to)
|
response = await intent.send_text(self.mxid, text, html=html, relates_to=relates_to)
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
@@ -50,9 +51,6 @@ class Puppet:
|
|||||||
def tgid(self):
|
def tgid(self):
|
||||||
return self.id
|
return self.id
|
||||||
|
|
||||||
def get_input_entity(self, user):
|
|
||||||
return user.client.get_input_entity(PeerUser(user_id=self.tgid))
|
|
||||||
|
|
||||||
def to_db(self):
|
def to_db(self):
|
||||||
return self.db.merge(
|
return self.db.merge(
|
||||||
DBPuppet(id=self.id, username=self.username, displayname=self.displayname,
|
DBPuppet(id=self.id, username=self.username, displayname=self.displayname,
|
||||||
@@ -71,8 +69,6 @@ class Puppet:
|
|||||||
if self.username else 0)
|
if self.username else 0)
|
||||||
displayname_similarity = (SequenceMatcher(None, self.displayname, query).ratio()
|
displayname_similarity = (SequenceMatcher(None, self.displayname, query).ratio()
|
||||||
if self.displayname else 0)
|
if self.displayname else 0)
|
||||||
#phone_number_similarity = (SequenceMatcher(None, self.phone_number, query).ratio()
|
|
||||||
# if self.phone_number else 0)
|
|
||||||
similarity = max(username_similarity, displayname_similarity)
|
similarity = max(username_similarity, displayname_similarity)
|
||||||
return round(similarity * 1000) / 10
|
return round(similarity * 1000) / 10
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
@@ -45,8 +46,8 @@ class MautrixTelegramClient(TelegramClient):
|
|||||||
|
|
||||||
return self._get_response_message(request, result)
|
return self._get_response_message(request, result)
|
||||||
|
|
||||||
async def send_file(self, entity, file, mime_type=None, caption=None, attributes=None, file_name=None,
|
async def send_file(self, entity, file, mime_type=None, caption=None, attributes=None,
|
||||||
reply_to=None, **kwargs):
|
file_name=None, reply_to=None, **kwargs):
|
||||||
entity = await self.get_input_entity(entity)
|
entity = await self.get_input_entity(entity)
|
||||||
reply_to = self._get_reply_to(reply_to)
|
reply_to = self._get_reply_to(reply_to)
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: future_fstrings -*-
|
||||||
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
# Copyright (C) 2018 Tulir Asokan
|
# Copyright (C) 2018 Tulir Asokan
|
||||||
#
|
#
|
||||||
@@ -98,9 +99,6 @@ class User:
|
|||||||
else:
|
else:
|
||||||
self.portals = {}
|
self.portals = {}
|
||||||
|
|
||||||
def get_input_entity(self, user):
|
|
||||||
return user.client.get_input_entity(InputUser(user_id=self.tgid, access_hash=0))
|
|
||||||
|
|
||||||
# region Database conversion
|
# region Database conversion
|
||||||
|
|
||||||
def to_db(self):
|
def to_db(self):
|
||||||
@@ -142,14 +140,15 @@ class User:
|
|||||||
device_model=device)
|
device_model=device)
|
||||||
self.client.add_update_handler(self.update_catch)
|
self.client.add_update_handler(self.update_catch)
|
||||||
|
|
||||||
async def start(self):
|
async def start(self, delete_unless_authenticated=False):
|
||||||
self.connected = await self.client.connect()
|
self.connected = await self.client.connect()
|
||||||
if self.logged_in:
|
if self.logged_in:
|
||||||
asyncio.ensure_future(self.post_login(), loop=self.loop)
|
asyncio.ensure_future(self.post_login(), loop=self.loop)
|
||||||
else:
|
elif delete_unless_authenticated:
|
||||||
# User not logged in -> forget user
|
# User not logged in -> forget user
|
||||||
self.client.disconnect()
|
self.client.disconnect()
|
||||||
self.client.session.delete()
|
self.client.session.delete()
|
||||||
|
self.delete()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
async def post_login(self, info=None):
|
async def post_login(self, info=None):
|
||||||
@@ -471,4 +470,4 @@ def init(context):
|
|||||||
User.az, User.db, config, User.loop = context
|
User.az, User.db, config, User.loop = context
|
||||||
|
|
||||||
users = [User.from_db(user) for user in DBUser.query.all()]
|
users = [User.from_db(user) for user in DBUser.query.all()]
|
||||||
return [user.start() for user in users]
|
return [user.start(delete_unless_authenticated=True) for user in users]
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-r base.txt
|
||||||
|
-e git+https://github.com/tulir/Telethon@asyncio-3.5#egg=Telethon
|
||||||
@@ -3,6 +3,6 @@ ruamel.yaml
|
|||||||
python-magic
|
python-magic
|
||||||
SQLAlchemy
|
SQLAlchemy
|
||||||
alembic
|
alembic
|
||||||
-e git+https://github.com/LonamiWebs/Telethon@asyncio#egg=Telethon
|
|
||||||
Markdown
|
Markdown
|
||||||
Pillow
|
Pillow
|
||||||
|
future-fstrings
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-r base.txt
|
||||||
|
-e git+https://github.com/LonamiWebs/Telethon@asyncio#egg=Telethon
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import setuptools
|
import setuptools
|
||||||
|
import sys
|
||||||
import mautrix_telegram
|
import mautrix_telegram
|
||||||
|
|
||||||
setuptools.setup(
|
setuptools.setup(
|
||||||
@@ -21,10 +22,13 @@ setuptools.setup(
|
|||||||
"Markdown>=2.6.11,<3",
|
"Markdown>=2.6.11,<3",
|
||||||
"ruamel.yaml>=0.15.35,<0.16",
|
"ruamel.yaml>=0.15.35,<0.16",
|
||||||
"Pillow>=5.0.0,<6",
|
"Pillow>=5.0.0,<6",
|
||||||
|
"future-fstrings>=0.4.1",
|
||||||
"python-magic>=0.4.15,<0.5",
|
"python-magic>=0.4.15,<0.5",
|
||||||
],
|
],
|
||||||
dependency_links=[
|
dependency_links=[
|
||||||
"https://github.com/LonamiWebs/Telethon/tarball/7da092894b306d720cc60c04daa2bfba58f81946#egg=Telethon"
|
("https://github.com/LonamiWebs/Telethon/tarball/7da092894b306d720cc60c04daa2bfba58f81946#egg=Telethon"
|
||||||
|
if sys.version_info > (3, 5)
|
||||||
|
else "https://github.com/tulir/Telethon/tarball/ac46abc9680c5a74897fe6dbe9e585ad2577b1fa#egg=Telethon")
|
||||||
],
|
],
|
||||||
|
|
||||||
classifiers=[
|
classifiers=[
|
||||||
|
|||||||
Reference in New Issue
Block a user