matplobbot-shared 0.1.24__py3-none-any.whl → 0.1.26__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of matplobbot-shared might be problematic. Click here for more details.
- {matplobbot_shared-0.1.24.dist-info → matplobbot_shared-0.1.26.dist-info}/METADATA +1 -1
- {matplobbot_shared-0.1.24.dist-info → matplobbot_shared-0.1.26.dist-info}/RECORD +5 -5
- shared_lib/database.py +60 -1
- {matplobbot_shared-0.1.24.dist-info → matplobbot_shared-0.1.26.dist-info}/WHEEL +0 -0
- {matplobbot_shared-0.1.24.dist-info → matplobbot_shared-0.1.26.dist-info}/top_level.txt +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
shared_lib/__init__.py,sha256=Wxuw1wbvCOsKqs6WfIQ05cx_vndhPs6rH2krMatFRqA,45
|
|
2
|
-
shared_lib/database.py,sha256=
|
|
2
|
+
shared_lib/database.py,sha256=CjjJ9HX_70IXOJ6aIS8xoD63Srj3Y-WHUqZ0zPCJsYc,15554
|
|
3
3
|
shared_lib/i18n.py,sha256=VBWQWVF-k_HDiidYo_RUPyUCM7oL897z5hOw9jvOoYY,1762
|
|
4
4
|
shared_lib/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
shared_lib/services/schedule_service.py,sha256=tKXgwZQWeaagQeqG_tKP2gLflWo_6kxKZOhW9PFvbK4,1835
|
|
6
6
|
shared_lib/services/university_api.py,sha256=Ui-zjfKOHCCf2Imh8CNtVOWegwuep7IB8gO9IKNUrrE,1898
|
|
7
|
-
matplobbot_shared-0.1.
|
|
8
|
-
matplobbot_shared-0.1.
|
|
9
|
-
matplobbot_shared-0.1.
|
|
10
|
-
matplobbot_shared-0.1.
|
|
7
|
+
matplobbot_shared-0.1.26.dist-info/METADATA,sha256=SEK0yxxYSavWzGQSx2C9EcgYaWdNL9TB3sdI2orLF8k,395
|
|
8
|
+
matplobbot_shared-0.1.26.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
9
|
+
matplobbot_shared-0.1.26.dist-info/top_level.txt,sha256=L8mrC50YWCe19jmh_zrUZFvXSkhsnES5K6y027G1838,11
|
|
10
|
+
matplobbot_shared-0.1.26.dist-info/RECORD,,
|
shared_lib/database.py
CHANGED
|
@@ -282,4 +282,63 @@ async def get_user_profile_data_from_db(db_conn, user_id: int, page: int = 1, pa
|
|
|
282
282
|
user_details = {k: first_row[k] for k in ["user_id", "full_name", "username", "avatar_pic_url"]}
|
|
283
283
|
actions = [dict(r) for r in rows if r["action_id"] is not None]
|
|
284
284
|
|
|
285
|
-
return {"user_details": user_details, "actions": actions, "total_actions": first_row["total_actions"]}
|
|
285
|
+
return {"user_details": user_details, "actions": actions, "total_actions": first_row["total_actions"]}
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
async def get_users_for_action(db_conn, action_type: str, action_details: str, page: int = 1, page_size: int = 15, sort_by: str = 'full_name', sort_order: str = 'asc'):
|
|
289
|
+
"""Извлекает пагинированный список уникальных пользователей, совершивших определенное действие."""
|
|
290
|
+
# Note: action_type for messages is 'text_message' in the DB
|
|
291
|
+
db_action_type = 'text_message' if action_type == 'message' else action_type
|
|
292
|
+
offset = (page - 1) * page_size
|
|
293
|
+
|
|
294
|
+
# --- Безопасная сортировка ---
|
|
295
|
+
allowed_sort_columns = ['user_id', 'full_name', 'username'] # These are u columns
|
|
296
|
+
if sort_by not in allowed_sort_columns:
|
|
297
|
+
sort_by = 'full_name' # Значение по умолчанию
|
|
298
|
+
sort_order = 'DESC' if sort_order.lower() == 'desc' else 'ASC' # Безопасное определение порядка
|
|
299
|
+
order_by_clause = f"ORDER BY u.{sort_by} {sort_order}"
|
|
300
|
+
|
|
301
|
+
# Query for total count of distinct users
|
|
302
|
+
count_query = """
|
|
303
|
+
SELECT COUNT(DISTINCT u.user_id)
|
|
304
|
+
FROM users u
|
|
305
|
+
JOIN user_actions ua ON u.user_id = ua.user_id
|
|
306
|
+
WHERE ua.action_type = $1 AND ua.action_details = $2;
|
|
307
|
+
"""
|
|
308
|
+
total_users = await db_conn.fetchval(count_query, db_action_type, action_details)
|
|
309
|
+
|
|
310
|
+
# Query for the paginated list of users
|
|
311
|
+
users_query = f"""
|
|
312
|
+
SELECT DISTINCT
|
|
313
|
+
u.user_id,
|
|
314
|
+
u.full_name,
|
|
315
|
+
COALESCE(u.username, 'Нет username') AS username
|
|
316
|
+
FROM users u
|
|
317
|
+
JOIN user_actions ua ON u.user_id = ua.user_id
|
|
318
|
+
WHERE ua.action_type = $1 AND ua.action_details = $2
|
|
319
|
+
{order_by_clause}
|
|
320
|
+
LIMIT $3 OFFSET $4;
|
|
321
|
+
"""
|
|
322
|
+
rows = await db_conn.fetch(users_query, db_action_type, action_details, page_size, offset)
|
|
323
|
+
users = [dict(row) for row in rows]
|
|
324
|
+
|
|
325
|
+
return {
|
|
326
|
+
"users": users,
|
|
327
|
+
"total_users": total_users
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
async def get_all_user_actions(db_conn, user_id: int):
|
|
332
|
+
"""Извлекает ВСЕ действия для указанного пользователя без пагинации."""
|
|
333
|
+
query = """
|
|
334
|
+
SELECT
|
|
335
|
+
id,
|
|
336
|
+
action_type,
|
|
337
|
+
action_details,
|
|
338
|
+
TO_CHAR(timestamp, 'YYYY-MM-DD HH24:MI:SS') AS timestamp
|
|
339
|
+
FROM user_actions
|
|
340
|
+
WHERE user_id = $1
|
|
341
|
+
ORDER BY timestamp DESC;
|
|
342
|
+
"""
|
|
343
|
+
rows = await db_conn.fetch(query, user_id)
|
|
344
|
+
return [dict(row) for row in rows]
|
|
File without changes
|
|
File without changes
|