Store puppet displayname quality and don't allow it to decrease

This commit is contained in:
Tulir Asokan
2021-03-23 20:13:06 +02:00
parent 79f8c520bd
commit abfefab545
3 changed files with 54 additions and 12 deletions
@@ -0,0 +1,32 @@
"""Store displayname quality in puppet table
Revision ID: bfc0a39bfe02
Revises: ec1d3dcc77e9
Create Date: 2021-03-23 20:03:08.825333
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = 'bfc0a39bfe02'
down_revision = 'ec1d3dcc77e9'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('puppet', schema=None) as batch_op:
batch_op.add_column(sa.Column('displayname_quality', sa.Integer(), server_default='0', nullable=False))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('puppet', schema=None) as batch_op:
batch_op.drop_column('displayname_quality')
# ### end Alembic commands ###
+2 -1
View File
@@ -15,7 +15,7 @@
# 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 Optional, Iterable from typing import Optional, Iterable
from sqlalchemy import Column, BigInteger, String, Text, Boolean from sqlalchemy import Column, Integer, BigInteger, String, Text, Boolean
from sqlalchemy.sql import expression, func from sqlalchemy.sql import expression, func
from mautrix.types import UserID, SyncToken from mautrix.types import UserID, SyncToken
@@ -35,6 +35,7 @@ class Puppet(Base):
displayname: str = Column(String, nullable=True) displayname: str = Column(String, nullable=True)
displayname_source: TelegramID = Column(BigInteger, nullable=True) displayname_source: TelegramID = Column(BigInteger, nullable=True)
displayname_contact: bool = Column(Boolean, nullable=False, server_default=expression.true()) displayname_contact: bool = Column(Boolean, nullable=False, server_default=expression.true())
displayname_quality: int = Column(Integer, nullable=False, server_default="0")
username: str = Column(String, nullable=True) username: str = Column(String, nullable=True)
photo_id: str = Column(String, nullable=True) photo_id: str = Column(String, nullable=True)
is_bot: bool = Column(Boolean, nullable=True) is_bot: bool = Column(Boolean, nullable=True)
+20 -11
View File
@@ -13,7 +13,7 @@
# #
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# 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, Any, Dict, Iterable, Optional, Union, TYPE_CHECKING from typing import Awaitable, Any, Dict, Iterable, Optional, Union, Tuple, TYPE_CHECKING
from difflib import SequenceMatcher from difflib import SequenceMatcher
import unicodedata import unicodedata
import asyncio import asyncio
@@ -66,6 +66,7 @@ class Puppet(BasePuppet):
displayname: Optional[str] displayname: Optional[str]
displayname_source: Optional[TelegramID] displayname_source: Optional[TelegramID]
displayname_contact: bool displayname_contact: bool
displayname_quality: int
photo_id: Optional[str] photo_id: Optional[str]
is_bot: bool is_bot: bool
is_registered: bool is_registered: bool
@@ -88,6 +89,7 @@ class Puppet(BasePuppet):
displayname: Optional[str] = None, displayname: Optional[str] = None,
displayname_source: Optional[TelegramID] = None, displayname_source: Optional[TelegramID] = None,
displayname_contact: bool = True, displayname_contact: bool = True,
displayname_quality: int = 0,
photo_id: Optional[str] = None, photo_id: Optional[str] = None,
is_bot: bool = False, is_bot: bool = False,
is_registered: bool = False, is_registered: bool = False,
@@ -104,6 +106,7 @@ class Puppet(BasePuppet):
self.displayname = displayname self.displayname = displayname
self.displayname_source = displayname_source self.displayname_source = displayname_source
self.displayname_contact = displayname_contact self.displayname_contact = displayname_contact
self.displayname_quality = displayname_quality
self.photo_id = photo_id self.photo_id = photo_id
self.is_bot = is_bot self.is_bot = is_bot
self.is_registered = is_registered self.is_registered = is_registered
@@ -168,7 +171,8 @@ class Puppet(BasePuppet):
return dict(access_token=self.access_token, next_batch=self._next_batch, return dict(access_token=self.access_token, next_batch=self._next_batch,
custom_mxid=self.custom_mxid, username=self.username, is_bot=self.is_bot, custom_mxid=self.custom_mxid, username=self.username, is_bot=self.is_bot,
displayname=self.displayname, displayname_source=self.displayname_source, displayname=self.displayname, displayname_source=self.displayname_source,
displayname_contact=self.displayname_contact, photo_id=self.photo_id, displayname_contact=self.displayname_contact,
displayname_quality=self.displayname_quality, photo_id=self.photo_id,
matrix_registered=self.is_registered, disable_updates=self.disable_updates, matrix_registered=self.is_registered, disable_updates=self.disable_updates,
base_url=str(self.base_url) if self.base_url else None) base_url=str(self.base_url) if self.base_url else None)
@@ -183,9 +187,9 @@ class Puppet(BasePuppet):
return Puppet(db_puppet.id, db_puppet.access_token, db_puppet.custom_mxid, return Puppet(db_puppet.id, db_puppet.access_token, db_puppet.custom_mxid,
db_puppet.next_batch, db_puppet.base_url, db_puppet.username, db_puppet.next_batch, db_puppet.base_url, db_puppet.username,
db_puppet.displayname, db_puppet.displayname_source, db_puppet.displayname, db_puppet.displayname_source,
db_puppet.displayname_contact, db_puppet.photo_id, db_puppet.is_bot, db_puppet.displayname_contact, db_puppet.displayname_quality,
db_puppet.matrix_registered, db_puppet.disable_updates, db_puppet.photo_id, db_puppet.is_bot, db_puppet.matrix_registered,
db_instance=db_puppet) db_puppet.disable_updates, db_instance=db_puppet)
# endregion # endregion
# region Info updating # region Info updating
@@ -209,7 +213,7 @@ class Puppet(BasePuppet):
return name return name
@classmethod @classmethod
def get_displayname(cls, info: User, enable_format: bool = True) -> str: def get_displayname(cls, info: User, enable_format: bool = True) -> Tuple[str, int]:
fn = cls._filter_name(info.first_name) fn = cls._filter_name(info.first_name)
ln = cls._filter_name(info.last_name) ln = cls._filter_name(info.last_name)
data = { data = {
@@ -222,19 +226,21 @@ class Puppet(BasePuppet):
} }
preferences = config["bridge.displayname_preference"] preferences = config["bridge.displayname_preference"]
name = None name = None
quality = 99
for preference in preferences: for preference in preferences:
name = data[preference] name = data[preference]
if name: if name:
break break
quality -= 1
if isinstance(info, User) and info.deleted: if isinstance(info, User) and info.deleted:
name = f"Deleted account {info.id}" name = f"Deleted account {info.id}"
quality = 99
elif not name: elif not name:
name = str(info.id) name = str(info.id)
quality = 0
if not enable_format: return cls.displayname_template.format_full(name) if enable_format else name, quality
return name
return cls.displayname_template.format_full(name)
async def try_update_info(self, source: 'AbstractUser', info: User) -> None: async def try_update_info(self, source: 'AbstractUser', info: User) -> None:
try: try:
@@ -287,13 +293,15 @@ class Puppet(BasePuppet):
else: else:
return False return False
displayname = self.get_displayname(info) displayname, quality = self.get_displayname(info)
if displayname != self.displayname: if displayname != self.displayname and quality >= self.displayname_quality:
allow_because = f"{allow_because} and quality {quality} >= {self.displayname_quality}"
self.log.debug(f"Updating displayname of {self.id} (src: {source.tgid}, allowed " self.log.debug(f"Updating displayname of {self.id} (src: {source.tgid}, allowed "
f"because {allow_because}) from {self.displayname} to {displayname}") f"because {allow_because}) from {self.displayname} to {displayname}")
self.log.trace("Displayname source data: %s", info) self.log.trace("Displayname source data: %s", info)
self.displayname = displayname self.displayname = displayname
self.displayname_source = source.tgid self.displayname_source = source.tgid
self.displayname_quality = quality
try: try:
await self.default_mxid_intent.set_displayname( await self.default_mxid_intent.set_displayname(
displayname[:config["bridge.displayname_max_length"]]) displayname[:config["bridge.displayname_max_length"]])
@@ -301,6 +309,7 @@ class Puppet(BasePuppet):
self.log.exception("Failed to set displayname") self.log.exception("Failed to set displayname")
self.displayname = "" self.displayname = ""
self.displayname_source = None self.displayname_source = None
self.displayname_quality = 0
return True return True
elif source.is_relaybot or self.displayname_source is None: elif source.is_relaybot or self.displayname_source is None:
self.displayname_source = source.tgid self.displayname_source = source.tgid