search.nim 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. # SPDX-License-Identifier: AGPL-3.0-only
  2. import strutils, uri
  3. import jester
  4. import router_utils
  5. import ".."/[query, types, api, formatters]
  6. import ../views/[general, search]
  7. include "../views/opensearch.nimf"
  8. export search
  9. proc createSearchRouter*(cfg: Config) =
  10. router search:
  11. get "/search/?":
  12. let q = @"q"
  13. if q.len > 500:
  14. resp Http400, showError("Search input too long.", cfg)
  15. let
  16. prefs = requestPrefs()
  17. title = "Search" & (if q.len > 0: " (" & q & ")" else: "")
  18. var query = initQuery(params(request))
  19. # x.com URL compat: f=user and f=list map to our kind names
  20. # (f=live already falls back to tweets/Latest; f=media matches natively)
  21. if @"f" == "user":
  22. query.kind = users
  23. elif @"f" == "list":
  24. query.kind = lists
  25. # media searches support view modes, defaulting like /user/media
  26. if query.kind == QueryKind.media and
  27. query.view notin ["timeline", "grid", "gallery"]:
  28. query.view = prefs.mediaView.toLowerAscii
  29. case query.kind
  30. of users:
  31. if "," in q:
  32. redirect("/" & q)
  33. var users: Result[User]
  34. try:
  35. users = await getGraphUserSearch(query, getCursor())
  36. except InternalError:
  37. users = Result[User](beginning: true, query: query)
  38. resp renderMain(renderUserSearch(users, prefs), request, cfg, prefs, title)
  39. of tweets, top, QueryKind.media:
  40. let
  41. tweets = await getGraphTweetSearch(query, getCursor())
  42. rss = if cfg.enableRSSSearch: "/search/rss?" & genQueryUrl(query) else: ""
  43. resp renderMain(renderTweetSearch(tweets, prefs, getPath()),
  44. request, cfg, prefs, title, rss=rss)
  45. of lists:
  46. let listResults = await getGraphListSearch(query, getCursor())
  47. resp renderMain(renderListSearch(listResults, prefs, getPath()),
  48. request, cfg, prefs, title)
  49. else:
  50. resp Http404, showError("Invalid search", cfg)
  51. get "/hashtag/@hash":
  52. redirect("/search?f=tweets&q=" & encodeUrl("#" & @"hash"))
  53. get "/opensearch":
  54. let
  55. url = getUrlPrefix(cfg) & "/search?f=tweets&q="
  56. headers = {"Content-Type": "application/opensearchdescription+xml"}
  57. resp Http200, headers, generateOpenSearchXML(cfg.title, cfg.hostname, url)