nitter/src/routes/status.nim

164 lines
5.5 KiB
Nim

# SPDX-License-Identifier: AGPL-3.0-only
import json, asyncdispatch, strutils, sequtils, uri, options, sugar, strformat, times
import jester, karax/vdom
import router_utils
import ".."/[types, formatters, api]
import ../views/[general, status, search, mastoapi]
export json, uri, sequtils, options, sugar, times
export router_utils
export api, formatters
export status, mastoapi
proc createStatusRouter*(cfg: Config) =
router status:
get "/@name/status/@id/@reactors":
cond '.' notin @"name"
let id = @"id"
if id.len > 19 or id.any(c => not c.isDigit):
resp Http404, showError("Invalid tweet ID", cfg)
let prefs = cookiePrefs()
# used for the infinite scroll feature
if @"scroll".len > 0:
let replies = await getReplies(id, getCursor())
if replies.content.len == 0:
resp Http404, ""
resp $renderReplies(replies, prefs, getPath())
if @"reactors" == "favoriters":
resp renderMain(renderUserList(await getGraphFavoriters(id, getCursor()), prefs),
request, cfg, prefs)
elif @"reactors" == "retweeters":
resp renderMain(renderUserList(await getGraphRetweeters(id, getCursor()), prefs),
request, cfg, prefs)
get "/@name/status/@id/?":
cond '.' notin @"name"
var id = @"id"
var rawFile = false
if id.endsWith(".mp4"):
rawFile = true
id.removeSuffix(".mp4")
if request.headers.hasKey("Accept") and request.headers["Accept"] == "application/activity+json":
if id.len > 19 or id.any(c => not c.isDigit):
resp Http404, {"Content-Type": "application/json"}, """{"error":"Invalid record ID"}"""
let prefs = cookiePrefs()
let conv = await getTweet(id)
if conv == nil:
echo "nil conv"
if conv == nil or conv.tweet == nil or conv.tweet.id == 0:
var error = "Record not found"
if conv != nil and conv.tweet != nil and conv.tweet.tombstone.len > 0:
error = conv.tweet.tombstone
var errJson = newJObject()
errJson["error"] = %error
resp Http404, {"Content-Type": "application/json"}, $errJson
let postJson = getActivityStream(conv.tweet, cfg, prefs)
resp Http200, {"Content-Type": "application/json"}, $postJson
if id.len > 19 or id.any(c => not c.isDigit):
resp Http404, showError("Invalid tweet ID", cfg)
let prefs = cookiePrefs()
# used for the infinite scroll feature
if @"scroll".len > 0:
let replies = await getReplies(id, getCursor())
if replies.content.len == 0:
resp Http404, ""
resp $renderReplies(replies, prefs, getPath())
let conv = await getTweet(id, getCursor())
if conv == nil:
echo "nil conv"
if conv == nil or conv.tweet == nil or conv.tweet.id == 0:
var error = "Tweet not found"
if conv != nil and conv.tweet != nil and conv.tweet.tombstone.len > 0:
error = conv.tweet.tombstone
resp Http404, showError(error, cfg)
let
tweet = conv.tweet
title = pageTitle(tweet)
ogTitle = pageTitle(tweet.user)
desc = tweet.text
avatar = tweet.user.userPic
time = some(tweet.time)
var
images = tweet.photos
video = ""
context = ""
contextUrl = ""
if tweet.quote.isSome():
let
quote = get(tweet.quote)
quoteUser = quote.user
if tweet.replyId != 0:
let replyUser = await getGraphUser(tweet.replyHandle)
context = &"↩ {replyUser.fullname} (@{tweet.replyHandle})\n↘ {quoteUser.fullname} (@{quoteUser.username})"
contextUrl = &"{getUrlPrefix(cfg)}/i/status/{tweet.replyId}"
else:
context = &"↘ {quoteUser.fullname} (@{quoteUser.username})"
contextUrl = &"{getUrlPrefix(cfg)}/i/status/{quote.id}"
elif tweet.replyId != 0:
let replyUser = await getGraphUser(tweet.replyHandle)
context = &"↩ {replyUser.fullname} (@{tweet.replyHandle})"
contextUrl = &"{getUrlPrefix(cfg)}/i/status/{tweet.replyId}"
if tweet.video.isSome():
let videoObj = get(tweet.video)
images = @[Image(url:videoObj.thumb)]
let vars = videoObj.variants.filterIt(it.contentType == mp4)
# idk why this wont sort when it sorts everywhere else
#video = vars.sortedByIt(it.bitrate)[^1].url
video = vars[^1].url
elif tweet.gif.isSome():
let gif = get(tweet.gif)
images = @[Image(url:gif.thumb)]
video = getUrlPrefix(cfg) & getPicUrl(gif.url)
#elif tweet.card.isSome():
# let card = tweet.card.get()
# if card.image.len > 0:
# images = @[card.image]
# elif card.video.isSome():
# images = @[card.video.get().thumb]
if rawFile and video != "":
redirect(video)
let html = renderConversation(conv, prefs, getPath() & "#m")
resp renderMain(html, request, cfg, prefs, title, desc, ogTitle,
images=images, video=video, avatar=avatar, time=time,
context=context, contextUrl=contextUrl, id=id)
get "/@name/@s/@id/@m/?@i?":
cond @"s" in ["status", "statuses"]
cond @"m" in ["video", "photo"]
redirect("/$1/status/$2" % [@"name", @"id"])
get "/@name/statuses/@id/?":
redirect("/$1/status/$2" % [@"name", @"id"])
get "/i/web/status/@id":
redirect("/i/status/" & @"id")
get "/@name/thread/@id/?":
redirect("/$1/status/$2" % [@"name", @"id"])