refactor: show tg avatar in detached browser
This commit is contained in:
@@ -854,6 +854,14 @@ async def _sync_panel_identity_for_user(request: web.Request, user: User) -> Non
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _telegram_photo_url_value(telegram_user: Dict[str, Any]) -> Optional[str]:
|
||||||
|
raw_value = telegram_user.get("photo_url")
|
||||||
|
if not raw_value:
|
||||||
|
return None
|
||||||
|
value = str(raw_value).strip()
|
||||||
|
return value or None
|
||||||
|
|
||||||
|
|
||||||
def _apply_telegram_profile_to_user(
|
def _apply_telegram_profile_to_user(
|
||||||
user: User,
|
user: User,
|
||||||
telegram_user: Dict[str, Any],
|
telegram_user: Dict[str, Any],
|
||||||
@@ -868,6 +876,9 @@ def _apply_telegram_profile_to_user(
|
|||||||
user.first_name = sanitize_display_name(telegram_user.get("first_name"))
|
user.first_name = sanitize_display_name(telegram_user.get("first_name"))
|
||||||
user.last_name = sanitize_display_name(telegram_user.get("last_name"))
|
user.last_name = sanitize_display_name(telegram_user.get("last_name"))
|
||||||
user.language_code = language_code
|
user.language_code = language_code
|
||||||
|
telegram_photo_url = _telegram_photo_url_value(telegram_user)
|
||||||
|
if telegram_photo_url:
|
||||||
|
user.telegram_photo_url = telegram_photo_url
|
||||||
|
|
||||||
|
|
||||||
async def _link_telegram_to_user(
|
async def _link_telegram_to_user(
|
||||||
@@ -1067,6 +1078,9 @@ async def _ensure_user_from_telegram(
|
|||||||
"last_name": sanitize_display_name(telegram_user.get("last_name")),
|
"last_name": sanitize_display_name(telegram_user.get("last_name")),
|
||||||
"language_code": language_code,
|
"language_code": language_code,
|
||||||
}
|
}
|
||||||
|
telegram_photo_url = _telegram_photo_url_value(telegram_user)
|
||||||
|
if telegram_photo_url:
|
||||||
|
update_data["telegram_photo_url"] = telegram_photo_url
|
||||||
|
|
||||||
db_user = await user_dal.get_user_by_telegram_id(session, user_id)
|
db_user = await user_dal.get_user_by_telegram_id(session, user_id)
|
||||||
if not db_user:
|
if not db_user:
|
||||||
@@ -1153,6 +1167,7 @@ async def _build_user_payload(request: web.Request, user_id: int) -> Dict[str, A
|
|||||||
"email_verified": bool(db_user.email_verified_at),
|
"email_verified": bool(db_user.email_verified_at),
|
||||||
"telegram_id": db_user.telegram_id,
|
"telegram_id": db_user.telegram_id,
|
||||||
"telegram_linked": bool(_telegram_id_for_user(db_user)),
|
"telegram_linked": bool(_telegram_id_for_user(db_user)),
|
||||||
|
"telegram_photo_url": db_user.telegram_photo_url,
|
||||||
"first_name": db_user.first_name,
|
"first_name": db_user.first_name,
|
||||||
"language_code": lang,
|
"language_code": lang,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -615,7 +615,7 @@ const MOCK = (() => {
|
|||||||
script.src = TELEGRAM_LOGIN_WIDGET_URL;
|
script.src = TELEGRAM_LOGIN_WIDGET_URL;
|
||||||
script.setAttribute('data-telegram-login', botUsername);
|
script.setAttribute('data-telegram-login', botUsername);
|
||||||
script.setAttribute('data-size', 'large');
|
script.setAttribute('data-size', 'large');
|
||||||
script.setAttribute('data-userpic', 'false');
|
script.setAttribute('data-userpic', 'true');
|
||||||
script.setAttribute('data-request-access', 'write');
|
script.setAttribute('data-request-access', 'write');
|
||||||
script.setAttribute('data-onauth', 'onTelegramAuth(user)');
|
script.setAttribute('data-onauth', 'onTelegramAuth(user)');
|
||||||
script.onerror = () => setAuthStatus(t('telegram_auth_unavailable'), true);
|
script.onerror = () => setAuthStatus(t('telegram_auth_unavailable'), true);
|
||||||
@@ -1003,7 +1003,8 @@ const MOCK = (() => {
|
|||||||
const telegramLinked = Boolean(user.telegram_linked);
|
const telegramLinked = Boolean(user.telegram_linked);
|
||||||
const displayName = getUserDisplayName(user);
|
const displayName = getUserDisplayName(user);
|
||||||
const secondary = getUserSecondaryText(user, emailLinked, telegramLinked);
|
const secondary = getUserSecondaryText(user, emailLinked, telegramLinked);
|
||||||
const avatar = getUserAvatarSrc(user, emailLinked);
|
const avatarSrc = getUserAvatarSrc(user);
|
||||||
|
const avatarFallback = buildIdenticon(getUserAvatarSeed(user, emailLinked));
|
||||||
|
|
||||||
const chipName = document.getElementById('user-chip-name');
|
const chipName = document.getElementById('user-chip-name');
|
||||||
const chipAvatar = document.getElementById('user-chip-avatar');
|
const chipAvatar = document.getElementById('user-chip-avatar');
|
||||||
@@ -1014,10 +1015,8 @@ const MOCK = (() => {
|
|||||||
const telegramStatus = document.getElementById('user-dropdown-telegram-status');
|
const telegramStatus = document.getElementById('user-dropdown-telegram-status');
|
||||||
|
|
||||||
chipName.textContent = displayName;
|
chipName.textContent = displayName;
|
||||||
chipAvatar.src = avatar;
|
setAvatarWithFallback(chipAvatar, avatarSrc, avatarFallback, displayName);
|
||||||
chipAvatar.alt = displayName;
|
setAvatarWithFallback(dropAvatar, avatarSrc, avatarFallback, displayName);
|
||||||
dropAvatar.src = avatar;
|
|
||||||
dropAvatar.alt = displayName;
|
|
||||||
dropName.textContent = displayName;
|
dropName.textContent = displayName;
|
||||||
dropSub.textContent = secondary;
|
dropSub.textContent = secondary;
|
||||||
dropSub.classList.toggle('hidden', !secondary);
|
dropSub.classList.toggle('hidden', !secondary);
|
||||||
@@ -1059,6 +1058,19 @@ const MOCK = (() => {
|
|||||||
return tg.initDataUnsafe.user;
|
return tg.initDataUnsafe.user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getUserAvatarSeed(user, emailLinked) {
|
||||||
|
const tgUser = getTelegramInitUser();
|
||||||
|
if (emailLinked && user && user.email) return user.email.trim().toLowerCase();
|
||||||
|
return String((user && user.id) || (user && user.telegram_id) || (tgUser && tgUser.id) || 'guest');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUserAvatarSrc(user) {
|
||||||
|
const tgUser = getTelegramInitUser();
|
||||||
|
if (tgUser && tgUser.photo_url) return tgUser.photo_url;
|
||||||
|
if (user && user.telegram_photo_url) return user.telegram_photo_url;
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
function getUserDisplayName(user) {
|
function getUserDisplayName(user) {
|
||||||
const tgUser = getTelegramInitUser();
|
const tgUser = getTelegramInitUser();
|
||||||
if (tgUser && tgUser.first_name) return tgUser.first_name;
|
if (tgUser && tgUser.first_name) return tgUser.first_name;
|
||||||
@@ -1075,13 +1087,21 @@ const MOCK = (() => {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUserAvatarSrc(user, emailLinked) {
|
function setAvatarWithFallback(img, avatarSrc, avatarFallback, altText) {
|
||||||
const tgUser = getTelegramInitUser();
|
if (!img) return;
|
||||||
if (tgUser && tgUser.photo_url) return tgUser.photo_url;
|
|
||||||
const seed = (emailLinked && user.email)
|
img.alt = altText || '';
|
||||||
? user.email.trim().toLowerCase()
|
if (!avatarSrc) {
|
||||||
: String(user.id || user.telegram_id || tgUser && tgUser.id || 'guest');
|
img.onerror = null;
|
||||||
return buildIdenticon(seed);
|
img.src = avatarFallback;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.onerror = () => {
|
||||||
|
img.onerror = null;
|
||||||
|
img.src = avatarFallback;
|
||||||
|
};
|
||||||
|
img.src = avatarSrc;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildIdenticon(seed) {
|
function buildIdenticon(seed) {
|
||||||
@@ -1460,7 +1480,7 @@ const MOCK = (() => {
|
|||||||
script.src = TELEGRAM_LOGIN_WIDGET_URL;
|
script.src = TELEGRAM_LOGIN_WIDGET_URL;
|
||||||
script.setAttribute('data-telegram-login', botUsername);
|
script.setAttribute('data-telegram-login', botUsername);
|
||||||
script.setAttribute('data-size', 'large');
|
script.setAttribute('data-size', 'large');
|
||||||
script.setAttribute('data-userpic', 'false');
|
script.setAttribute('data-userpic', 'true');
|
||||||
script.setAttribute('data-request-access', 'write');
|
script.setAttribute('data-request-access', 'write');
|
||||||
script.setAttribute('data-onauth', 'onTelegramLinkAuth(user)');
|
script.setAttribute('data-onauth', 'onTelegramLinkAuth(user)');
|
||||||
script.onerror = () => setTelegramLinkStatus(t('telegram_auth_unavailable'), true);
|
script.onerror = () => setTelegramLinkStatus(t('telegram_auth_unavailable'), true);
|
||||||
|
|||||||
+1
-1
@@ -287,7 +287,7 @@ async def merge_users(
|
|||||||
if referral_code_to_move:
|
if referral_code_to_move:
|
||||||
target.referral_code = referral_code_to_move
|
target.referral_code = referral_code_to_move
|
||||||
|
|
||||||
for attr in ("username", "first_name", "last_name", "language_code"):
|
for attr in ("username", "first_name", "last_name", "language_code", "telegram_photo_url"):
|
||||||
if not getattr(target, attr) and getattr(source, attr):
|
if not getattr(target, attr) and getattr(source, attr):
|
||||||
setattr(target, attr, getattr(source, attr))
|
setattr(target, attr, getattr(source, attr))
|
||||||
if not target.referred_by_id and source.referred_by_id != target_user_id:
|
if not target.referred_by_id and source.referred_by_id != target_user_id:
|
||||||
|
|||||||
@@ -239,6 +239,18 @@ def _migration_0006_add_security_throttles(connection: Connection) -> None:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _migration_0007_add_telegram_photo_url(connection: Connection) -> None:
|
||||||
|
inspector = inspect(connection)
|
||||||
|
columns: Set[str] = {col["name"] for col in inspector.get_columns("users")}
|
||||||
|
if "telegram_photo_url" in columns:
|
||||||
|
return
|
||||||
|
|
||||||
|
connection.execute(
|
||||||
|
text("ALTER TABLE users ADD COLUMN telegram_photo_url TEXT")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
MIGRATIONS: List[Migration] = [
|
MIGRATIONS: List[Migration] = [
|
||||||
Migration(
|
Migration(
|
||||||
id="0001_add_channel_subscription_fields",
|
id="0001_add_channel_subscription_fields",
|
||||||
@@ -270,6 +282,11 @@ MIGRATIONS: List[Migration] = [
|
|||||||
description="Add generic lockout tracking for brute-force protection",
|
description="Add generic lockout tracking for brute-force protection",
|
||||||
upgrade=_migration_0006_add_security_throttles,
|
upgrade=_migration_0006_add_security_throttles,
|
||||||
),
|
),
|
||||||
|
Migration(
|
||||||
|
id="0007_add_telegram_photo_url",
|
||||||
|
description="Store Telegram profile photo URLs for linked users",
|
||||||
|
upgrade=_migration_0007_add_telegram_photo_url,
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ class User(Base):
|
|||||||
email = Column(String, nullable=True, unique=True, index=True)
|
email = Column(String, nullable=True, unique=True, index=True)
|
||||||
email_verified_at = Column(DateTime(timezone=True), nullable=True)
|
email_verified_at = Column(DateTime(timezone=True), nullable=True)
|
||||||
telegram_id = Column(BigInteger, nullable=True, unique=True, index=True)
|
telegram_id = Column(BigInteger, nullable=True, unique=True, index=True)
|
||||||
|
telegram_photo_url = Column(Text, nullable=True)
|
||||||
first_name = Column(String, nullable=True)
|
first_name = Column(String, nullable=True)
|
||||||
last_name = Column(String, nullable=True)
|
last_name = Column(String, nullable=True)
|
||||||
language_code = Column(String, default="ru")
|
language_code = Column(String, default="ru")
|
||||||
|
|||||||
Reference in New Issue
Block a user