99 lines
3.2 KiB
Python
99 lines
3.2 KiB
Python
import asyncpg
|
|
|
|
from userbot.modules.profiles.parse import ProfileFields
|
|
|
|
_GET_PEER = """
|
|
SELECT first_name, last_name, username, phone, photo_unique_id, is_deleted_account
|
|
FROM peers
|
|
WHERE account_id = $1 AND peer_id = $2
|
|
"""
|
|
|
|
_UPSERT_PEER = """
|
|
INSERT INTO peers AS p
|
|
(account_id, peer_id, first_name, last_name, username, phone,
|
|
photo_unique_id, is_deleted_account, raw, updated_at)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9::jsonb, now())
|
|
ON CONFLICT (account_id, peer_id) DO UPDATE SET
|
|
first_name = EXCLUDED.first_name,
|
|
last_name = EXCLUDED.last_name,
|
|
username = CASE WHEN 'username' = ANY($10::text[])
|
|
THEN COALESCE(EXCLUDED.username, p.username) ELSE EXCLUDED.username END,
|
|
phone = CASE WHEN 'phone' = ANY($10::text[])
|
|
THEN COALESCE(EXCLUDED.phone, p.phone) ELSE EXCLUDED.phone END,
|
|
photo_unique_id = EXCLUDED.photo_unique_id,
|
|
is_deleted_account = CASE WHEN 'is_deleted_account' = ANY($10::text[])
|
|
THEN p.is_deleted_account ELSE EXCLUDED.is_deleted_account END,
|
|
raw = EXCLUDED.raw,
|
|
updated_at = now()
|
|
"""
|
|
|
|
_INSERT_CHANGE = """
|
|
INSERT INTO peer_history
|
|
(account_id, peer_id, observed_at, first_name, last_name, username, phone,
|
|
photo_unique_id, is_deleted_account, raw)
|
|
SELECT account_id, peer_id, clock_timestamp(), first_name, last_name, username,
|
|
phone, photo_unique_id, is_deleted_account, raw
|
|
FROM peers p
|
|
WHERE account_id = $1 AND peer_id = $2
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM (
|
|
SELECT first_name, last_name, username, phone, photo_unique_id,
|
|
is_deleted_account
|
|
FROM peer_history
|
|
WHERE account_id = $1 AND peer_id = $2
|
|
ORDER BY observed_at DESC LIMIT 1
|
|
) latest
|
|
WHERE (latest.first_name, latest.last_name, latest.username, latest.phone,
|
|
latest.photo_unique_id, latest.is_deleted_account)
|
|
IS NOT DISTINCT FROM
|
|
(p.first_name, p.last_name, p.username, p.phone,
|
|
p.photo_unique_id, p.is_deleted_account)
|
|
)
|
|
ON CONFLICT DO NOTHING
|
|
"""
|
|
|
|
|
|
async def get_peer(
|
|
pool: asyncpg.Pool, account_id: int, peer_id: int
|
|
) -> ProfileFields | None:
|
|
row = await pool.fetchrow(_GET_PEER, account_id, peer_id)
|
|
if row is None:
|
|
return None
|
|
return ProfileFields(
|
|
first_name=row["first_name"],
|
|
last_name=row["last_name"],
|
|
username=row["username"],
|
|
phone=row["phone"],
|
|
photo_unique_id=row["photo_unique_id"],
|
|
is_deleted_account=row["is_deleted_account"],
|
|
)
|
|
|
|
|
|
async def write_profile( # noqa: PLR0913
|
|
pool: asyncpg.Pool,
|
|
account_id: int,
|
|
peer_id: int,
|
|
fields: ProfileFields,
|
|
raw: str,
|
|
*,
|
|
history: bool,
|
|
) -> bool:
|
|
async with pool.acquire() as conn, conn.transaction():
|
|
await conn.execute(
|
|
_UPSERT_PEER,
|
|
account_id,
|
|
peer_id,
|
|
fields.first_name,
|
|
fields.last_name,
|
|
fields.username,
|
|
fields.phone,
|
|
fields.photo_unique_id,
|
|
fields.is_deleted_account,
|
|
raw,
|
|
sorted(fields.unknown),
|
|
)
|
|
if not history:
|
|
return False
|
|
status = await conn.execute(_INSERT_CHANGE, account_id, peer_id)
|
|
return status == "INSERT 0 1"
|