Support Top, Latest, Media, and Lists search

Fixes #1335
This commit is contained in:
Zed 2026-07-08 18:56:12 +02:00
commit 61246df9de
14 changed files with 475 additions and 78 deletions

View file

@ -263,12 +263,19 @@ proc getGraphTweetSearch*(query: Query; after=""): Future[Timeline] {.async.} =
if q.len == 0 or q == emptyQuery:
return Timeline(query: query, beginning: true)
let product =
case query.kind
of top: "Top"
# profile media feeds (RSS, multi-user timelines) must stay chronological
of media: (if query.fromUser.len == 0: "Media" else: "Latest")
else: "Latest"
var
variables = %*{
"rawQuery": q,
"count": 20,
"querySource": "typed_query",
"product": "Latest",
"product": product,
"withGrokTranslatedBio":true,
"withQuickPromoteEligibilityTweetFields":false
}
@ -283,33 +290,40 @@ proc getGraphTweetSearch*(query: Query; after=""): Future[Timeline] {.async.} =
# when no more items are available the API just returns the last page in
# full. this detects that and clears the page instead.
if after.len > 0 and result.bottom.len > 0 and maxId.len == 0 and
after[0..<64] == result.bottom[0..<64]:
let prefix = min(64, min(after.len, result.bottom.len))
if prefix > 0 and maxId.len == 0 and
after[0..<prefix] == result.bottom[0..<prefix]:
result.content.setLen(0)
proc getGraphUserSearch*(query: Query; after=""): Future[Result[User]] {.async.} =
proc getGraphProductSearch[T](query: Query; product: string;
after=""): Future[Result[T]] {.async.} =
if query.text.len == 0:
return Result[User](query: query, beginning: true)
return Result[T](query: query, beginning: true)
var
variables = %*{
"rawQuery": query.text,
"count": 20,
"querySource": "typed_query",
"product": "People",
"product": product,
"withGrokTranslatedBio":true,
"withQuickPromoteEligibilityTweetFields":false
}
if after.len > 0:
variables["cursor"] = % after
result.beginning = false
let
let
url = apiReq(graphSearchTimeline, $variables)
js = await fetch(url)
result = parseGraphSearch[User](js, after)
result = parseGraphSearch[T](js, after)
result.query = query
proc getGraphUserSearch*(query: Query; after=""): Future[Result[User]] =
getGraphProductSearch[User](query, "People", after)
proc getGraphListSearch*(query: Query; after=""): Future[Result[ListSearchResult]] =
getGraphProductSearch[ListSearchResult](query, "Lists", after)
proc getPhotoRail*(id: string): Future[PhotoRail] {.async.} =
if id.len == 0: return
let js = await fetch(mediaUrl(id, "", 30))