Compare commits
16 Commits
v0.2.0-rc2
...
v0.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 005daa9ee2 | |||
| 7029102c0f | |||
| 708110eb08 | |||
| c0da861562 | |||
| 844cf14bcd | |||
| fe32475e10 | |||
| f28f5915a4 | |||
| 1aa80c1a8f | |||
| 5d9b94fa5f | |||
| 6ef31599e9 | |||
| e961e0bcc6 | |||
| dc85754b1e | |||
| 04e2c03dae | |||
| 42d54dac5b | |||
| 767a51f994 | |||
| 313b5e5d07 |
+8
-8
@@ -7,12 +7,14 @@ COPY . /opt/mautrixtelegram
|
|||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache \
|
||||||
python3-dev \
|
python3-dev \
|
||||||
py3-virtualenv \
|
py3-virtualenv \
|
||||||
|
py3-pillow \
|
||||||
|
py3-aiohttp \
|
||||||
|
py3-lxml \
|
||||||
|
py3-magic \
|
||||||
|
py3-numpy \
|
||||||
|
py3-asn1crypto \
|
||||||
|
py3-sqlalchemy \
|
||||||
build-base \
|
build-base \
|
||||||
zlib-dev \
|
|
||||||
jpeg-dev \
|
|
||||||
libxslt-dev \
|
|
||||||
libxml2-dev \
|
|
||||||
libmagic \
|
|
||||||
ffmpeg \
|
ffmpeg \
|
||||||
bash \
|
bash \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
@@ -21,9 +23,7 @@ RUN apk add --no-cache \
|
|||||||
&& cd /opt/mautrixtelegram \
|
&& cd /opt/mautrixtelegram \
|
||||||
&& cp -r docker/root/* / \
|
&& cp -r docker/root/* / \
|
||||||
&& rm docker -rf \
|
&& rm docker -rf \
|
||||||
&& virtualenv -p /usr/bin/python3 .venv \
|
&& pip3 install -r requirements.txt -r optional-requirements.txt
|
||||||
&& source .venv/bin/activate \
|
|
||||||
&& pip install -r requirements.txt -r optional-requirements.txt
|
|
||||||
|
|
||||||
VOLUME /data
|
VOLUME /data
|
||||||
|
|
||||||
|
|||||||
@@ -35,9 +35,6 @@ script_location = alembic
|
|||||||
# are written from script.py.mako
|
# are written from script.py.mako
|
||||||
# output_encoding = utf-8
|
# output_encoding = utf-8
|
||||||
|
|
||||||
sqlalchemy.url = sqlite:///mautrix-telegram.db
|
|
||||||
|
|
||||||
|
|
||||||
# Logging configuration
|
# Logging configuration
|
||||||
[loggers]
|
[loggers]
|
||||||
keys = root,sqlalchemy,alembic
|
keys = root,sqlalchemy,alembic
|
||||||
|
|||||||
+7
-1
@@ -1,4 +1,3 @@
|
|||||||
from __future__ import with_statement
|
|
||||||
from alembic import context
|
from alembic import context
|
||||||
from sqlalchemy import engine_from_config, pool
|
from sqlalchemy import engine_from_config, pool
|
||||||
from logging.config import fileConfig
|
from logging.config import fileConfig
|
||||||
@@ -8,12 +7,19 @@ from os.path import abspath, dirname
|
|||||||
sys.path.insert(0, dirname(dirname(abspath(__file__))))
|
sys.path.insert(0, dirname(dirname(abspath(__file__))))
|
||||||
|
|
||||||
from mautrix_telegram.base import Base
|
from mautrix_telegram.base import Base
|
||||||
|
from mautrix_telegram.config import Config
|
||||||
import mautrix_telegram.db
|
import mautrix_telegram.db
|
||||||
|
|
||||||
# this is the Alembic Config object, which provides
|
# this is the Alembic Config object, which provides
|
||||||
# access to the values within the .ini file in use.
|
# access to the values within the .ini file in use.
|
||||||
config = context.config
|
config = context.config
|
||||||
|
|
||||||
|
mxtg_config_path = context.get_x_argument(as_dictionary=True).get("config", "config.yaml")
|
||||||
|
mxtg_config = Config(mxtg_config_path, None, None)
|
||||||
|
mxtg_config.load()
|
||||||
|
config.set_main_option("sqlalchemy.url",
|
||||||
|
mxtg_config.get("appservice.database", "sqlite:///mautrix-telegram.db"))
|
||||||
|
|
||||||
# Interpret the config file for Python logging.
|
# Interpret the config file for Python logging.
|
||||||
# This line sets up loggers basically.
|
# This line sets up loggers basically.
|
||||||
fileConfig(config.config_file_name)
|
fileConfig(config.config_file_name)
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
"""Add cascade rules to UserPortal
|
||||||
|
|
||||||
|
Revision ID: 2228d49c383f
|
||||||
|
Revises: bcfefa1f1299
|
||||||
|
Create Date: 2018-05-31 11:11:59.482112
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '2228d49c383f'
|
||||||
|
down_revision = 'bcfefa1f1299'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
try:
|
||||||
|
with op.batch_alter_table("user_portal") as batch_op:
|
||||||
|
batch_op.drop_constraint("user_portal_user_fkey", type_="foreignkey")
|
||||||
|
batch_op.drop_constraint("user_portal_portal_fkey", type_="foreignkey")
|
||||||
|
batch_op.create_foreign_key("user_portal_user_fkey", "user", ["user"], ["tgid"],
|
||||||
|
onupdate="CASCADE", ondelete="CASCADE")
|
||||||
|
batch_op.create_foreign_key("user_portal_portal_fkey", "portal",
|
||||||
|
["portal", "portal_receiver"], ["tgid", "tg_receiver"],
|
||||||
|
onupdate="CASCADE", ondelete="CASCADE")
|
||||||
|
except ValueError:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
try:
|
||||||
|
with op.batch_alter_table("user_portal") as batch_op:
|
||||||
|
batch_op.drop_constraint("user_portal_user_fkey", type_="foreignkey")
|
||||||
|
batch_op.drop_constraint("user_portal_portal_fkey", type_="foreignkey")
|
||||||
|
batch_op.create_foreign_key("user_portal_user_fkey", "portal",
|
||||||
|
["portal", "portal_receiver"], ["tgid", "tg_receiver"])
|
||||||
|
batch_op.create_foreign_key("user_portal_portal_fkey", "user", ["user"], ["tgid"])
|
||||||
|
except ValueError:
|
||||||
|
return
|
||||||
@@ -19,31 +19,31 @@ depends_on = None
|
|||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
Session = op.create_table('telethon_sessions',
|
Session = op.create_table('telethon_sessions',
|
||||||
sa.Column('session_id', sa.VARCHAR(), nullable=False),
|
sa.Column('session_id', sa.String, nullable=False),
|
||||||
sa.Column('dc_id', sa.INTEGER(), nullable=False),
|
sa.Column('dc_id', sa.Integer, nullable=False),
|
||||||
sa.Column('server_address', sa.VARCHAR(), nullable=True),
|
sa.Column('server_address', sa.String, nullable=True),
|
||||||
sa.Column('port', sa.INTEGER(), nullable=True),
|
sa.Column('port', sa.Integer, nullable=True),
|
||||||
sa.Column('auth_key', sa.BLOB(), nullable=True),
|
sa.Column('auth_key', sa.LargeBinary, nullable=True),
|
||||||
sa.PrimaryKeyConstraint('session_id', 'dc_id'))
|
sa.PrimaryKeyConstraint('session_id', 'dc_id'))
|
||||||
SentFile = op.create_table('telethon_sent_files',
|
SentFile = op.create_table('telethon_sent_files',
|
||||||
sa.Column('session_id', sa.VARCHAR(), nullable=False),
|
sa.Column('session_id', sa.String, nullable=False),
|
||||||
sa.Column('md5_digest', sa.BLOB(), nullable=False),
|
sa.Column('md5_digest', sa.LargeBinary, nullable=False),
|
||||||
sa.Column('file_size', sa.INTEGER(), nullable=False),
|
sa.Column('file_size', sa.Integer, nullable=False),
|
||||||
sa.Column('type', sa.INTEGER(), nullable=False),
|
sa.Column('type', sa.Integer, nullable=False),
|
||||||
sa.Column('id', sa.INTEGER(), nullable=True),
|
sa.Column('id', sa.BigInteger, nullable=True),
|
||||||
sa.Column('hash', sa.INTEGER(), nullable=True),
|
sa.Column('hash', sa.BigInteger, nullable=True),
|
||||||
sa.PrimaryKeyConstraint('session_id', 'md5_digest', 'file_size',
|
sa.PrimaryKeyConstraint('session_id', 'md5_digest', 'file_size',
|
||||||
'type'))
|
'type'))
|
||||||
Entity = op.create_table('telethon_entities',
|
Entity = op.create_table('telethon_entities',
|
||||||
sa.Column('session_id', sa.VARCHAR(), nullable=False),
|
sa.Column('session_id', sa.String, nullable=False),
|
||||||
sa.Column('id', sa.INTEGER(), nullable=False),
|
sa.Column('id', sa.Integer, nullable=False),
|
||||||
sa.Column('hash', sa.INTEGER(), nullable=False),
|
sa.Column('hash', sa.Integer, nullable=False),
|
||||||
sa.Column('username', sa.VARCHAR(), nullable=True),
|
sa.Column('username', sa.String, nullable=True),
|
||||||
sa.Column('phone', sa.INTEGER(), nullable=True),
|
sa.Column('phone', sa.Integer, nullable=True),
|
||||||
sa.Column('name', sa.VARCHAR(), nullable=True),
|
sa.Column('name', sa.String, nullable=True),
|
||||||
sa.PrimaryKeyConstraint('session_id', 'id'))
|
sa.PrimaryKeyConstraint('session_id', 'id'))
|
||||||
Version = op.create_table('telethon_version',
|
Version = op.create_table('telethon_version',
|
||||||
sa.Column('version', sa.INTEGER(), nullable=False),
|
sa.Column('version', sa.Integer, nullable=False),
|
||||||
sa.PrimaryKeyConstraint('version'))
|
sa.PrimaryKeyConstraint('version'))
|
||||||
conn = op.get_bind()
|
conn = op.get_bind()
|
||||||
sessions = [os.path.basename(f) for f in os.listdir(".") if f.endswith(".session")]
|
sessions = [os.path.basename(f) for f in os.listdir(".") if f.endswith(".session")]
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ depends_on = None
|
|||||||
def upgrade():
|
def upgrade():
|
||||||
op.add_column('telegram_file',
|
op.add_column('telegram_file',
|
||||||
sa.Column('timestamp', sa.BigInteger(), nullable=False, default=0,
|
sa.Column('timestamp', sa.BigInteger(), nullable=False, default=0,
|
||||||
server_default="true"))
|
server_default="0"))
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ def upgrade():
|
|||||||
sa.UniqueConstraint('mxid'))
|
sa.UniqueConstraint('mxid'))
|
||||||
op.create_table('user',
|
op.create_table('user',
|
||||||
sa.Column('mxid', sa.String),
|
sa.Column('mxid', sa.String),
|
||||||
sa.Column('tgid', sa.Integer, nullable=True),
|
sa.Column('tgid', sa.Integer, nullable=True, unique=True),
|
||||||
sa.Column('tg_username', sa.String, nullable=True),
|
sa.Column('tg_username', sa.String, nullable=True),
|
||||||
sa.Column('saved_contacts', sa.Integer, nullable=False, default=0),
|
sa.Column('saved_contacts', sa.Integer, nullable=False, default=0),
|
||||||
sa.PrimaryKeyConstraint('mxid'))
|
sa.PrimaryKeyConstraint('mxid'))
|
||||||
@@ -50,9 +50,13 @@ def upgrade():
|
|||||||
sa.Column('portal', sa.Integer),
|
sa.Column('portal', sa.Integer),
|
||||||
sa.Column('portal_receiver', sa.Integer),
|
sa.Column('portal_receiver', sa.Integer),
|
||||||
sa.PrimaryKeyConstraint('user', 'portal', 'portal_receiver'),
|
sa.PrimaryKeyConstraint('user', 'portal', 'portal_receiver'),
|
||||||
sa.ForeignKeyConstraint(("user",), ("user.tgid",)),
|
sa.ForeignKeyConstraint(("user",), ("user.tgid",),
|
||||||
|
name="user_portal_user_fkey",
|
||||||
|
onupdate="CASCADE", ondelete="CASCADE"),
|
||||||
sa.ForeignKeyConstraint(("portal", "portal_receiver"),
|
sa.ForeignKeyConstraint(("portal", "portal_receiver"),
|
||||||
("portal.tgid", "portal.tg_receiver")))
|
("portal.tgid", "portal.tg_receiver"),
|
||||||
|
name="user_portal_portal_fkey",
|
||||||
|
onupdate="CASCADE", ondelete="CASCADE"))
|
||||||
op.create_table('message',
|
op.create_table('message',
|
||||||
sa.Column('mxid', sa.String),
|
sa.Column('mxid', sa.String),
|
||||||
sa.Column('mx_room', sa.String),
|
sa.Column('mx_room', sa.String),
|
||||||
|
|||||||
@@ -8,14 +8,13 @@ function fixperms {
|
|||||||
|
|
||||||
# Go into env
|
# Go into env
|
||||||
cd /opt/mautrixtelegram
|
cd /opt/mautrixtelegram
|
||||||
source .venv/bin/activate
|
export FFMPEG_BINARY=/usr/bin/ffmpeg
|
||||||
|
|
||||||
# Replace database path in alembic.ini
|
# Replace database path in config.
|
||||||
sed -i "s#sqlite:///mautrix-telegram.db#sqlite:////data/mautrix-telegram.db#" alembic.ini
|
|
||||||
sed -i "s#sqlite:///mautrix-telegram.db#sqlite:////data/mautrix-telegram.db#" /data/config.yaml
|
sed -i "s#sqlite:///mautrix-telegram.db#sqlite:////data/mautrix-telegram.db#" /data/config.yaml
|
||||||
|
|
||||||
# Check that database is in the right state
|
# Check that database is in the right state
|
||||||
alembic upgrade head
|
alembic -x config=/data/config.yaml upgrade head
|
||||||
|
|
||||||
if [[ ! -f /data/config.yaml ]]; then
|
if [[ ! -f /data/config.yaml ]]; then
|
||||||
cp example-config.yaml /data/config.yaml
|
cp example-config.yaml /data/config.yaml
|
||||||
@@ -28,7 +27,7 @@ if [[ ! -f /data/config.yaml ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! -f /data/registration.yaml ]]; then
|
if [[ ! -f /data/registration.yaml ]]; then
|
||||||
python -m mautrix_telegram -g -c /data/config.yaml -r /data/registration.yaml
|
python3 -m mautrix_telegram -g -c /data/config.yaml -r /data/registration.yaml
|
||||||
echo "Didn't find a registration file."
|
echo "Didn't find a registration file."
|
||||||
echo "Generated ode for you."
|
echo "Generated ode for you."
|
||||||
echo "Copy that over to synapses app service directory."
|
echo "Copy that over to synapses app service directory."
|
||||||
@@ -36,7 +35,5 @@ if [[ ! -f /data/registration.yaml ]]; then
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export FFMPEG_BINARY=/usr/bin/ffmpeg
|
|
||||||
|
|
||||||
fixperms
|
fixperms
|
||||||
exec su-exec ${UID}:${GID} python -m mautrix_telegram -c /data/config.yaml
|
exec su-exec ${UID}:${GID} python3 -m mautrix_telegram -c /data/config.yaml
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
__version__ = "0.2.0rc2"
|
__version__ = "0.2.0"
|
||||||
__author__ = "Tulir Asokan <tulir@maunium.net>"
|
__author__ = "Tulir Asokan <tulir@maunium.net>"
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ from alchemysession import AlchemySessionContainer
|
|||||||
from mautrix_appservice import AppService
|
from mautrix_appservice import AppService
|
||||||
|
|
||||||
from .base import Base
|
from .base import Base
|
||||||
from .config import Config, DictWithRecursion
|
from .config import Config
|
||||||
from .matrix import MatrixHandler
|
from .matrix import MatrixHandler
|
||||||
|
|
||||||
from .db import init as init_db
|
from .db import init as init_db
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ class Bot(AbstractUser):
|
|||||||
if not self.mxid_regex.match(mxid):
|
if not self.mxid_regex.match(mxid):
|
||||||
return await reply("That doesn't look like a Matrix ID.")
|
return await reply("That doesn't look like a Matrix ID.")
|
||||||
user = await u.User.get_by_mxid(mxid).ensure_started()
|
user = await u.User.get_by_mxid(mxid).ensure_started()
|
||||||
if not user.whitelisted:
|
if not user.relaybot_whitelisted:
|
||||||
return await reply("That user is not whitelisted to use the bridge.")
|
return await reply("That user is not whitelisted to use the bridge.")
|
||||||
elif user.logged_in:
|
elif user.logged_in:
|
||||||
displayname = f"@{user.username}" if user.username else user.displayname
|
displayname = f"@{user.username}" if user.username else user.displayname
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
from telethon.errors import *
|
from telethon.errors import *
|
||||||
|
from telethon.tl.types import ChatForbidden, ChannelForbidden
|
||||||
from mautrix_appservice import MatrixRequestError
|
from mautrix_appservice import MatrixRequestError
|
||||||
|
|
||||||
from .. import portal as po
|
from .. import portal as po
|
||||||
@@ -102,7 +103,7 @@ def _get_portal_murder_function(action, room_id, function, command, completed_me
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@command_handler()
|
@command_handler(needs_auth=False)
|
||||||
async def delete_portal(evt: CommandEvent):
|
async def delete_portal(evt: CommandEvent):
|
||||||
portal, ok = await _get_portal_and_check_permission(evt, "delete_portal")
|
portal, ok = await _get_portal_and_check_permission(evt, "delete_portal")
|
||||||
if not ok:
|
if not ok:
|
||||||
@@ -114,10 +115,14 @@ async def delete_portal(evt: CommandEvent):
|
|||||||
return await evt.reply("Please confirm deletion of portal "
|
return await evt.reply("Please confirm deletion of portal "
|
||||||
f"[{portal.alias or portal.mxid}](https://matrix.to/#/{portal.mxid}) "
|
f"[{portal.alias or portal.mxid}](https://matrix.to/#/{portal.mxid}) "
|
||||||
f"to Telegram chat \"{portal.title}\" "
|
f"to Telegram chat \"{portal.title}\" "
|
||||||
"by typing `$cmdprefix+sp confirm-delete`")
|
"by typing `$cmdprefix+sp confirm-delete`"
|
||||||
|
"\n\n"
|
||||||
|
"**WARNING:** If the bridge bot has the power level to do so, **this "
|
||||||
|
"will kick ALL users** in the room. If you just want to remove the "
|
||||||
|
"bridge, use `$cmdprefix+sp unbridge` instead.")
|
||||||
|
|
||||||
|
|
||||||
@command_handler()
|
@command_handler(needs_auth=False)
|
||||||
async def unbridge(evt: CommandEvent):
|
async def unbridge(evt: CommandEvent):
|
||||||
portal, ok = await _get_portal_and_check_permission(evt, "unbridge_room")
|
portal, ok = await _get_portal_and_check_permission(evt, "unbridge_room")
|
||||||
if not ok:
|
if not ok:
|
||||||
@@ -131,7 +136,7 @@ async def unbridge(evt: CommandEvent):
|
|||||||
"by typing `$cmdprefix+sp confirm-unbridge`")
|
"by typing `$cmdprefix+sp confirm-unbridge`")
|
||||||
|
|
||||||
|
|
||||||
@command_handler()
|
@command_handler(needs_auth=False)
|
||||||
async def bridge(evt: CommandEvent):
|
async def bridge(evt: CommandEvent):
|
||||||
if len(evt.args) == 0:
|
if len(evt.args) == 0:
|
||||||
return await evt.reply("**Usage:** "
|
return await evt.reply("**Usage:** "
|
||||||
@@ -247,14 +252,31 @@ async def confirm_bridge(evt: CommandEvent):
|
|||||||
return await evt.reply("Please use `$cmdprefix+sp continue` to confirm the bridging or "
|
return await evt.reply("Please use `$cmdprefix+sp continue` to confirm the bridging or "
|
||||||
"`$cmdprefix+sp cancel` to cancel.")
|
"`$cmdprefix+sp cancel` to cancel.")
|
||||||
|
|
||||||
|
user = evt.sender if evt.sender.logged_in else evt.tgbot
|
||||||
|
try:
|
||||||
|
entity = await user.client.get_entity(portal.peer)
|
||||||
|
except Exception:
|
||||||
|
evt.log.exception("Failed to get_entity(%s) for manual bridging.", portal.peer)
|
||||||
|
if evt.sender.logged_in:
|
||||||
|
return await evt.reply("Failed to get info of telegram chat. "
|
||||||
|
"You are logged in, are you in that chat?")
|
||||||
|
else:
|
||||||
|
return await evt.reply("Failed to get info of telegram chat. "
|
||||||
|
"You're not logged in, is the relay bot in the chat?")
|
||||||
|
if isinstance(entity, (ChatForbidden, ChannelForbidden)):
|
||||||
|
if evt.sender.logged_in:
|
||||||
|
return await evt.reply("You don't seem to be in that chat.")
|
||||||
|
else:
|
||||||
|
return await evt.reply("The bot doesn't seem to be in that chat.")
|
||||||
|
|
||||||
|
direct = False
|
||||||
|
|
||||||
portal.mxid = bridge_to_mxid
|
portal.mxid = bridge_to_mxid
|
||||||
portal.title, portal.about, levels = await _get_initial_state(evt)
|
portal.title, portal.about, levels = await _get_initial_state(evt)
|
||||||
portal.photo_id = ""
|
portal.photo_id = ""
|
||||||
portal.save()
|
portal.save()
|
||||||
|
|
||||||
entity = await evt.sender.client.get_entity(portal.peer)
|
asyncio.ensure_future(portal.update_matrix_room(user, entity, direct, levels=levels),
|
||||||
direct = False
|
|
||||||
asyncio.ensure_future(portal.update_matrix_room(evt.sender, entity, direct, levels=levels),
|
|
||||||
loop=evt.loop)
|
loop=evt.loop)
|
||||||
|
|
||||||
return await evt.reply("Bridging complete. Portal synchronization should begin momentarily.")
|
return await evt.reply("Bridging complete. Portal synchronization should begin momentarily.")
|
||||||
|
|||||||
@@ -57,12 +57,14 @@ class UserPortal(Base):
|
|||||||
query = None
|
query = None
|
||||||
__tablename__ = "user_portal"
|
__tablename__ = "user_portal"
|
||||||
|
|
||||||
user = Column(Integer, ForeignKey("user.tgid"), primary_key=True)
|
user = Column(Integer, ForeignKey("user.tgid", onupdate="CASCADE", ondelete="CASCADE"),
|
||||||
|
primary_key=True)
|
||||||
portal = Column(Integer, primary_key=True)
|
portal = Column(Integer, primary_key=True)
|
||||||
portal_receiver = Column(Integer, primary_key=True)
|
portal_receiver = Column(Integer, primary_key=True)
|
||||||
|
|
||||||
__table_args__ = (ForeignKeyConstraint(("portal", "portal_receiver"),
|
__table_args__ = (ForeignKeyConstraint(("portal", "portal_receiver"),
|
||||||
("portal.tgid", "portal.tg_receiver")),)
|
("portal.tgid", "portal.tg_receiver"),
|
||||||
|
onupdate="CASCADE", ondelete="CASCADE"),)
|
||||||
|
|
||||||
|
|
||||||
class User(Base):
|
class User(Base):
|
||||||
@@ -70,7 +72,7 @@ class User(Base):
|
|||||||
__tablename__ = "user"
|
__tablename__ = "user"
|
||||||
|
|
||||||
mxid = Column(String, primary_key=True)
|
mxid = Column(String, primary_key=True)
|
||||||
tgid = Column(Integer, nullable=True)
|
tgid = Column(Integer, nullable=True, unique=True)
|
||||||
tg_username = Column(String, nullable=True)
|
tg_username = Column(String, nullable=True)
|
||||||
saved_contacts = Column(Integer, default=0)
|
saved_contacts = Column(Integer, default=0)
|
||||||
contacts = relationship("Contact", uselist=True,
|
contacts = relationship("Contact", uselist=True,
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ class MatrixHandler:
|
|||||||
|
|
||||||
puppet = Puppet.get_by_mxid(user)
|
puppet = Puppet.get_by_mxid(user)
|
||||||
if sender and puppet:
|
if sender and puppet:
|
||||||
await portal.leave_matrix(puppet, sender)
|
await portal.leave_matrix(puppet, sender, event_id)
|
||||||
|
|
||||||
user = User.get_by_mxid(user, create=False)
|
user = User.get_by_mxid(user, create=False)
|
||||||
if not user:
|
if not user:
|
||||||
|
|||||||
@@ -1318,6 +1318,8 @@ class Portal:
|
|||||||
await intent.redact(self.mxid, mxid)
|
await intent.redact(self.mxid, mxid)
|
||||||
|
|
||||||
async def _create_room_on_action(self, source, action):
|
async def _create_room_on_action(self, source, action):
|
||||||
|
if source.is_relaybot:
|
||||||
|
return False
|
||||||
create_and_exit = (MessageActionChatCreate, MessageActionChannelCreate)
|
create_and_exit = (MessageActionChatCreate, MessageActionChannelCreate)
|
||||||
create_and_continue = (MessageActionChatAddUser, MessageActionChatJoinedByLink)
|
create_and_continue = (MessageActionChatAddUser, MessageActionChatJoinedByLink)
|
||||||
if isinstance(action, create_and_exit + create_and_continue):
|
if isinstance(action, create_and_exit + create_and_continue):
|
||||||
@@ -1331,7 +1333,7 @@ class Portal:
|
|||||||
action = update.action
|
action = update.action
|
||||||
should_ignore = ((not self.mxid and not await self._create_room_on_action(source, action))
|
should_ignore = ((not self.mxid and not await self._create_room_on_action(source, action))
|
||||||
or self.is_duplicate_action(update))
|
or self.is_duplicate_action(update))
|
||||||
if should_ignore:
|
if should_ignore or not self.mxid:
|
||||||
return
|
return
|
||||||
# TODO figure out how to see changes to about text / channel username
|
# TODO figure out how to see changes to about text / channel username
|
||||||
if isinstance(action, MessageActionChatEditTitle):
|
if isinstance(action, MessageActionChatEditTitle):
|
||||||
|
|||||||
Reference in New Issue
Block a user