feat: web UI chat render, panels, presence + analytics
This commit is contained in:
1 parent
75425d1bee
commit
ed469ba8dd
83 files changed
+6034
-136
No files matched your search
@@ -0,0 +1,69 @@
|
||||
from datetime import UTC, datetime, timedelta
|
||||
|
||||
import asyncpg
|
||||
|
||||
from utils.read.accounts import self_user_id
|
||||
from utils.read.models import ResponseStats, VolumeBucket
|
||||
|
||||
|
||||
async def message_volume(
|
||||
pool: asyncpg.Pool, account_id: int, chat_id: int, *, days: int = 90
|
||||
) -> list[VolumeBucket]:
|
||||
self_id = await self_user_id(pool, account_id)
|
||||
rows = await pool.fetch(
|
||||
"SELECT date_trunc('day', date) AS bucket, count(*) AS total, "
|
||||
"count(*) FILTER (WHERE sender_id = $3) AS outgoing "
|
||||
"FROM messages "
|
||||
"WHERE account_id = $1 AND chat_id = $2 AND date >= $4 "
|
||||
"GROUP BY bucket ORDER BY bucket",
|
||||
account_id,
|
||||
chat_id,
|
||||
self_id,
|
||||
datetime.now(UTC) - timedelta(days=days),
|
||||
)
|
||||
return [
|
||||
VolumeBucket(
|
||||
bucket=row["bucket"],
|
||||
total=row["total"],
|
||||
outgoing=row["outgoing"],
|
||||
incoming=row["total"] - row["outgoing"],
|
||||
)
|
||||
for row in rows
|
||||
]
|
||||
|
||||
|
||||
async def response_stats(
|
||||
pool: asyncpg.Pool, account_id: int, chat_id: int
|
||||
) -> ResponseStats:
|
||||
self_id = await self_user_id(pool, account_id)
|
||||
rows = await pool.fetch(
|
||||
"WITH ordered AS ("
|
||||
"SELECT sender_id, date, "
|
||||
"lag(sender_id) OVER w AS prev_sender, "
|
||||
"lag(date) OVER w AS prev_date "
|
||||
"FROM messages "
|
||||
"WHERE account_id = $1 AND chat_id = $2 AND sender_id IS NOT NULL "
|
||||
"WINDOW w AS (ORDER BY date, message_id)), "
|
||||
"resp AS ("
|
||||
"SELECT (sender_id = $3) AS is_mine, "
|
||||
"EXTRACT(EPOCH FROM (date - prev_date)) AS secs "
|
||||
"FROM ordered "
|
||||
"WHERE prev_sender IS NOT NULL AND prev_sender <> sender_id) "
|
||||
"SELECT is_mine, count(*) AS n, "
|
||||
"percentile_cont(0.5) WITHIN GROUP (ORDER BY secs) AS median_secs "
|
||||
"FROM resp GROUP BY is_mine",
|
||||
account_id,
|
||||
chat_id,
|
||||
self_id,
|
||||
)
|
||||
stats = ResponseStats(
|
||||
mine_median_seconds=None, mine_count=0, their_median_seconds=None, their_count=0
|
||||
)
|
||||
for row in rows:
|
||||
if row["is_mine"]:
|
||||
stats.mine_median_seconds = row["median_secs"]
|
||||
stats.mine_count = row["n"]
|
||||
else:
|
||||
stats.their_median_seconds = row["median_secs"]
|
||||
stats.their_count = row["n"]
|
||||
return stats
|
||||
Reference in new issue
Block a user