wop commited on
Commit
0034562
·
verified ·
1 Parent(s): 26d901b

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +81 -31
main.py CHANGED
@@ -1,4 +1,4 @@
1
- from __future__ import annotations
2
 
3
  import json
4
  import os
@@ -92,13 +92,16 @@ def clamp_page(value: Any) -> int:
92
  return page if page > 0 else 1
93
 
94
 
95
- def build_list_query(status: str, q: str, page: int) -> str:
96
- params = {
97
- "status": status,
98
- "page": page,
99
- }
100
  if q:
101
  params["q"] = q
 
 
 
 
 
 
102
  return urlencode(params)
103
 
104
 
@@ -303,40 +306,61 @@ def conversation_summary(conversation: dict[str, Any]) -> dict[str, Any]:
303
  }
304
 
305
 
 
 
 
306
  def sort_conversations_for_queue(
307
  conversations: list[dict[str, Any]],
308
  status: str,
309
  query: str,
 
310
  ) -> list[dict[str, Any]]:
311
- status = clean_text(status).lower() or "unanswered"
312
- query = clean_text(query)
 
313
 
314
- if status == "unanswered" and not query:
315
- return sorted(
316
- conversations,
317
- key=lambda c: to_dt(c.get("created_at") or c.get("updated_at")),
318
- reverse=True,
319
- )
320
 
321
- def key(conversation: dict[str, Any]):
322
- has_answers = bool(conversation.get("answers"))
323
- best_length = answer_text_length(conversation) if has_answers else 0
324
- updated = to_dt(conversation.get("updated_at") or conversation.get("created_at"))
325
- return (
326
- 0 if not has_answers else 1,
327
- 0 if not has_answers else best_length,
328
- -updated.timestamp(),
329
- )
 
 
330
 
331
- return sorted(conversations, key=key)
 
 
 
 
332
 
 
 
333
 
334
- def list_questions(status: str = "unanswered", q: str = "", page: int = 1) -> dict[str, Any]:
 
335
  status = clean_text(status).lower() or "unanswered"
336
  if status not in {"unanswered", "answered", "all"}:
337
  status = "unanswered"
338
  q = clean_text(q)
339
  page = clamp_page(page)
 
 
 
 
 
 
 
 
 
 
 
340
 
341
  conversations = [normalize_conversation(c) for c in load_conversations()]
342
 
@@ -348,7 +372,12 @@ def list_questions(status: str = "unanswered", q: str = "", page: int = 1) -> di
348
  if q:
349
  conversations = [c for c in conversations if matches_query(c, q)]
350
 
351
- conversations = sort_conversations_for_queue(conversations, status=status, query=q)
 
 
 
 
 
352
  total = len(conversations)
353
  start = (page - 1) * PAGE_SIZE
354
  end = start + PAGE_SIZE
@@ -363,6 +392,9 @@ def list_questions(status: str = "unanswered", q: str = "", page: int = 1) -> di
363
  "has_next": end < total,
364
  "status": status,
365
  "q": q,
 
 
 
366
  }
367
 
368
 
@@ -535,8 +567,17 @@ def home(request: Request):
535
  q = clean_text(request.query_params.get("q"))
536
  page = clamp_page(request.query_params.get("page", 1))
537
  conversation_id = clean_text(request.query_params.get("conversation_id"))
 
 
 
 
 
 
 
 
 
538
 
539
- list_state = list_questions(status=status, q=q, page=page)
540
  detail = load_conversation(conversation_id) if conversation_id else None
541
 
542
  init = {
@@ -548,11 +589,14 @@ def home(request: Request):
548
  "q": list_state["q"],
549
  "page": list_state["page"],
550
  "page_size": list_state["page_size"],
 
 
 
551
  },
552
  "list": list_state,
553
  "detail": detail,
554
  "conversation_id": conversation_id,
555
- "back_query": build_list_query(list_state["status"], list_state["q"], list_state["page"]),
556
  }
557
  return templates.TemplateResponse(
558
  request,
@@ -593,11 +637,14 @@ async def api(request: Request):
593
  q = clean_text(payload.get("q"))
594
  page = clamp_page(payload.get("page", 1))
595
  conversation_id = clean_text(payload.get("conversation_id"))
 
 
 
596
  return JSONResponse(
597
  {
598
  "ok": True,
599
  "client_id": client_id,
600
- "list": list_questions(status=status, q=q, page=page),
601
  "detail": load_conversation(conversation_id) if conversation_id else None,
602
  }
603
  )
@@ -606,7 +653,10 @@ async def api(request: Request):
606
  status = clean_text(payload.get("status")).lower() or "unanswered"
607
  q = clean_text(payload.get("q"))
608
  page = clamp_page(payload.get("page", 1))
609
- return JSONResponse({"ok": True, **list_questions(status=status, q=q, page=page)})
 
 
 
610
 
611
  if action in {"get_question_detail", "get_conversation"}:
612
  conversation_id = clean_text(payload.get("conversation_id"))
@@ -670,4 +720,4 @@ async def api(request: Request):
670
  if __name__ == "__main__":
671
  import uvicorn
672
 
673
- uvicorn.run("main:app", host="0.0.0.0", port=7860, reload=False)
 
1
+ from __future__ import annotations
2
 
3
  import json
4
  import os
 
92
  return page if page > 0 else 1
93
 
94
 
95
+ def build_list_query(status: str, q: str, page: int, sort: str = "newest", min_words: int = 0, max_words: int = 0) -> str:
96
+ params: dict = {"status": status, "page": page}
 
 
 
97
  if q:
98
  params["q"] = q
99
+ if sort and sort != "newest":
100
+ params["sort"] = sort
101
+ if min_words > 0:
102
+ params["min_words"] = min_words
103
+ if max_words > 0:
104
+ params["max_words"] = max_words
105
  return urlencode(params)
106
 
107
 
 
306
  }
307
 
308
 
309
+ VALID_SORTS = {"newest", "oldest", "most_votes", "most_answers", "longest_answer", "shortest_answer"}
310
+
311
+
312
  def sort_conversations_for_queue(
313
  conversations: list[dict[str, Any]],
314
  status: str,
315
  query: str,
316
+ sort: str = "newest",
317
  ) -> list[dict[str, Any]]:
318
+ sort = clean_text(sort).lower()
319
+ if sort not in VALID_SORTS:
320
+ sort = "newest"
321
 
322
+ if sort == "oldest":
323
+ return sorted(conversations, key=lambda c: to_dt(c.get("created_at") or c.get("updated_at")))
 
 
 
 
324
 
325
+ if sort == "most_votes":
326
+ def vote_key(c: dict[str, Any]) -> int:
327
+ best = best_answer_payload(c)
328
+ return int(best.get("votes", 0)) if best else 0
329
+ return sorted(conversations, key=vote_key, reverse=True)
330
+
331
+ if sort == "most_answers":
332
+ return sorted(conversations, key=lambda c: len(c.get("answers", [])), reverse=True)
333
+
334
+ if sort == "longest_answer":
335
+ return sorted(conversations, key=answer_text_length, reverse=True)
336
 
337
+ if sort == "shortest_answer":
338
+ def short_key(c: dict[str, Any]) -> tuple:
339
+ length = answer_text_length(c)
340
+ return (0 if length == 0 else 1, length)
341
+ return sorted(conversations, key=short_key)
342
 
343
+ # newest (default)
344
+ return sorted(conversations, key=lambda c: to_dt(c.get("created_at") or c.get("updated_at")), reverse=True)
345
 
346
+
347
+ def list_questions(status: str = "unanswered", q: str = "", page: int = 1, sort: str = "newest", min_words: int = 0, max_words: int = 0) -> dict[str, Any]:
348
  status = clean_text(status).lower() or "unanswered"
349
  if status not in {"unanswered", "answered", "all"}:
350
  status = "unanswered"
351
  q = clean_text(q)
352
  page = clamp_page(page)
353
+ sort = clean_text(sort).lower()
354
+ if sort not in VALID_SORTS:
355
+ sort = "newest"
356
+ try:
357
+ min_words = max(0, int(min_words))
358
+ except Exception:
359
+ min_words = 0
360
+ try:
361
+ max_words = max(0, int(max_words))
362
+ except Exception:
363
+ max_words = 0
364
 
365
  conversations = [normalize_conversation(c) for c in load_conversations()]
366
 
 
372
  if q:
373
  conversations = [c for c in conversations if matches_query(c, q)]
374
 
375
+ if min_words > 0:
376
+ conversations = [c for c in conversations if len(clean_text(c.get("question")).split()) >= min_words]
377
+ if max_words > 0:
378
+ conversations = [c for c in conversations if len(clean_text(c.get("question")).split()) <= max_words]
379
+
380
+ conversations = sort_conversations_for_queue(conversations, status=status, query=q, sort=sort)
381
  total = len(conversations)
382
  start = (page - 1) * PAGE_SIZE
383
  end = start + PAGE_SIZE
 
392
  "has_next": end < total,
393
  "status": status,
394
  "q": q,
395
+ "sort": sort,
396
+ "min_words": min_words,
397
+ "max_words": max_words,
398
  }
399
 
400
 
 
567
  q = clean_text(request.query_params.get("q"))
568
  page = clamp_page(request.query_params.get("page", 1))
569
  conversation_id = clean_text(request.query_params.get("conversation_id"))
570
+ sort = clean_text(request.query_params.get("sort")) or "newest"
571
+ try:
572
+ min_words = max(0, int(request.query_params.get("min_words", 0)))
573
+ except Exception:
574
+ min_words = 0
575
+ try:
576
+ max_words = max(0, int(request.query_params.get("max_words", 0)))
577
+ except Exception:
578
+ max_words = 0
579
 
580
+ list_state = list_questions(status=status, q=q, page=page, sort=sort, min_words=min_words, max_words=max_words)
581
  detail = load_conversation(conversation_id) if conversation_id else None
582
 
583
  init = {
 
589
  "q": list_state["q"],
590
  "page": list_state["page"],
591
  "page_size": list_state["page_size"],
592
+ "sort": list_state["sort"],
593
+ "min_words": list_state["min_words"],
594
+ "max_words": list_state["max_words"],
595
  },
596
  "list": list_state,
597
  "detail": detail,
598
  "conversation_id": conversation_id,
599
+ "back_query": build_list_query(list_state["status"], list_state["q"], list_state["page"], list_state["sort"], list_state["min_words"], list_state["max_words"]),
600
  }
601
  return templates.TemplateResponse(
602
  request,
 
637
  q = clean_text(payload.get("q"))
638
  page = clamp_page(payload.get("page", 1))
639
  conversation_id = clean_text(payload.get("conversation_id"))
640
+ sort = clean_text(payload.get("sort")) or "newest"
641
+ min_words = int(payload.get("min_words", 0) or 0)
642
+ max_words = int(payload.get("max_words", 0) or 0)
643
  return JSONResponse(
644
  {
645
  "ok": True,
646
  "client_id": client_id,
647
+ "list": list_questions(status=status, q=q, page=page, sort=sort, min_words=min_words, max_words=max_words),
648
  "detail": load_conversation(conversation_id) if conversation_id else None,
649
  }
650
  )
 
653
  status = clean_text(payload.get("status")).lower() or "unanswered"
654
  q = clean_text(payload.get("q"))
655
  page = clamp_page(payload.get("page", 1))
656
+ sort = clean_text(payload.get("sort")) or "newest"
657
+ min_words = int(payload.get("min_words", 0) or 0)
658
+ max_words = int(payload.get("max_words", 0) or 0)
659
+ return JSONResponse({"ok": True, **list_questions(status=status, q=q, page=page, sort=sort, min_words=min_words, max_words=max_words)})
660
 
661
  if action in {"get_question_detail", "get_conversation"}:
662
  conversation_id = clean_text(payload.get("conversation_id"))
 
720
  if __name__ == "__main__":
721
  import uvicorn
722
 
723
+ uvicorn.run("main:app", host="0.0.0.0", port=7860, reload=False)