mirror of
https://github.com/zedeus/nitter.git
synced 2026-03-05 13:30:19 -05:00
@@ -139,7 +139,10 @@ proc parseLegacyMediaEntities(js: JsonNode; result: var Tweet) =
|
|||||||
for m in jsMedia:
|
for m in jsMedia:
|
||||||
case m.getTypeName:
|
case m.getTypeName:
|
||||||
of "photo":
|
of "photo":
|
||||||
result.photos.add m{"media_url_https"}.getImageStr
|
result.photos.add Photo(
|
||||||
|
url: m{"media_url_https"}.getImageStr,
|
||||||
|
altText: m{"ext_alt_text"}.getStr
|
||||||
|
)
|
||||||
of "video":
|
of "video":
|
||||||
result.video = some(parseVideo(m))
|
result.video = some(parseVideo(m))
|
||||||
with user, m{"additional_media_info", "source_user"}:
|
with user, m{"additional_media_info", "source_user"}:
|
||||||
@@ -165,7 +168,10 @@ proc parseMediaEntities(js: JsonNode; result: var Tweet) =
|
|||||||
with mediaInfo, mediaEntity{"media_results", "result", "media_info"}:
|
with mediaInfo, mediaEntity{"media_results", "result", "media_info"}:
|
||||||
case mediaInfo.getTypeName
|
case mediaInfo.getTypeName
|
||||||
of "ApiImage":
|
of "ApiImage":
|
||||||
result.photos.add mediaInfo{"original_img_url"}.getImageStr
|
result.photos.add Photo(
|
||||||
|
url: mediaInfo{"original_img_url"}.getImageStr,
|
||||||
|
altText: mediaInfo{"alt_text"}.getStr
|
||||||
|
)
|
||||||
of "ApiVideo":
|
of "ApiVideo":
|
||||||
let status = mediaEntity{"media_results", "result", "media_availability_v2", "status"}
|
let status = mediaEntity{"media_results", "result", "media_availability_v2", "status"}
|
||||||
result.video = some Video(
|
result.video = some Video(
|
||||||
@@ -332,11 +338,13 @@ proc parseTweet(js: JsonNode; jsCard: JsonNode = newJNull()): Tweet =
|
|||||||
let name = jsCard{"name"}.getStr
|
let name = jsCard{"name"}.getStr
|
||||||
if "poll" in name:
|
if "poll" in name:
|
||||||
if "image" in name:
|
if "image" in name:
|
||||||
result.photos.add jsCard{"binding_values", "image_large"}.getImageVal
|
result.photos.add Photo(
|
||||||
|
url: jsCard{"binding_values", "image_large"}.getImageVal
|
||||||
|
)
|
||||||
|
|
||||||
result.poll = some parsePoll(jsCard)
|
result.poll = some parsePoll(jsCard)
|
||||||
elif name == "amplify":
|
elif name == "amplify":
|
||||||
result.video = some(parsePromoVideo(jsCard{"binding_values"}))
|
result.video = some parsePromoVideo(jsCard{"binding_values"})
|
||||||
else:
|
else:
|
||||||
result.card = some parseCard(jsCard, js{"entities", "urls"})
|
result.card = some parseCard(jsCard, js{"entities", "urls"})
|
||||||
|
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ proc expandNoteTweetEntities*(tweet: Tweet; js: JsonNode) =
|
|||||||
|
|
||||||
proc extractGalleryPhoto*(t: Tweet): GalleryPhoto =
|
proc extractGalleryPhoto*(t: Tweet): GalleryPhoto =
|
||||||
let url =
|
let url =
|
||||||
if t.photos.len > 0: t.photos[0]
|
if t.photos.len > 0: t.photos[0].url
|
||||||
elif t.video.isSome: get(t.video).thumb
|
elif t.video.isSome: get(t.video).thumb
|
||||||
elif t.gif.isSome: get(t.gif).thumb
|
elif t.gif.isSome: get(t.gif).thumb
|
||||||
elif t.card.isSome: get(t.card).image
|
elif t.card.isSome: get(t.card).image
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ proc createStatusRouter*(cfg: Config) =
|
|||||||
desc = conv.tweet.text
|
desc = conv.tweet.text
|
||||||
|
|
||||||
var
|
var
|
||||||
images = conv.tweet.photos
|
images = conv.tweet.photos.mapIt(it.url)
|
||||||
video = ""
|
video = ""
|
||||||
|
|
||||||
if conv.tweet.video.isSome():
|
if conv.tweet.video.isSome():
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
align-items: center;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-height: 379.5px;
|
max-height: 379.5px;
|
||||||
@@ -13,7 +12,7 @@
|
|||||||
|
|
||||||
.still-image {
|
.still-image {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
align-self: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +57,6 @@
|
|||||||
.still-image {
|
.still-image {
|
||||||
max-height: 379.5px;
|
max-height: 379.5px;
|
||||||
max-width: 533px;
|
max-width: 533px;
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
img {
|
img {
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
@@ -69,8 +67,37 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.alt-text {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 11px 7px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
left: 10px;
|
||||||
|
width: 2.98em;
|
||||||
|
max-height: 25px;
|
||||||
|
white-space: pre;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 10px;
|
||||||
|
color: var(--fg_color);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.alt-text:hover {
|
||||||
|
padding: 7px;
|
||||||
|
width: Min(230px, calc(100% - 10px * 2));
|
||||||
|
max-height: calc(100% - 10px);
|
||||||
|
line-height: 1.2em;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
transition-duration: 0.4s;
|
||||||
|
transition-property: max-height;
|
||||||
|
}
|
||||||
|
|
||||||
.image {
|
.image {
|
||||||
display: inline-block;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
// .single-image {
|
// .single-image {
|
||||||
|
|||||||
@@ -137,6 +137,10 @@ type
|
|||||||
url*: string
|
url*: string
|
||||||
thumb*: string
|
thumb*: string
|
||||||
|
|
||||||
|
Photo* = object
|
||||||
|
url*: string
|
||||||
|
altText*: string
|
||||||
|
|
||||||
GalleryPhoto* = object
|
GalleryPhoto* = object
|
||||||
url*: string
|
url*: string
|
||||||
tweetId*: string
|
tweetId*: string
|
||||||
@@ -217,7 +221,7 @@ type
|
|||||||
poll*: Option[Poll]
|
poll*: Option[Poll]
|
||||||
gif*: Option[Gif]
|
gif*: Option[Gif]
|
||||||
video*: Option[Video]
|
video*: Option[Video]
|
||||||
photos*: seq[string]
|
photos*: seq[Photo]
|
||||||
|
|
||||||
Tweets* = seq[Tweet]
|
Tweets* = seq[Tweet]
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc="";
|
|||||||
let opensearchUrl = getUrlPrefix(cfg) & "/opensearch"
|
let opensearchUrl = getUrlPrefix(cfg) & "/opensearch"
|
||||||
|
|
||||||
buildHtml(head):
|
buildHtml(head):
|
||||||
link(rel="stylesheet", type="text/css", href="/css/style.css?v=23")
|
link(rel="stylesheet", type="text/css", href="/css/style.css?v=24")
|
||||||
link(rel="stylesheet", type="text/css", href="/css/fontello.css?v=4")
|
link(rel="stylesheet", type="text/css", href="/css/fontello.css?v=4")
|
||||||
|
|
||||||
if theme.len > 0:
|
if theme.len > 0:
|
||||||
|
|||||||
@@ -97,9 +97,9 @@ proc genNumberInput*(pref, label, state, placeholder: string; class=""; autofocu
|
|||||||
label(`for`=pref): text label
|
label(`for`=pref): text label
|
||||||
input(name=pref, `type`="number", placeholder=p, value=state, autofocus=(autofocus and state.len == 0), min=min, step="1")
|
input(name=pref, `type`="number", placeholder=p, value=state, autofocus=(autofocus and state.len == 0), min=min, step="1")
|
||||||
|
|
||||||
proc genImg*(url: string; class=""): VNode =
|
proc genImg*(url: string; class=""; alt=""): VNode =
|
||||||
buildHtml():
|
buildHtml():
|
||||||
img(src=getPicUrl(url), class=class, alt="", loading="lazy")
|
img(src=getPicUrl(url), class=class, alt=alt, loading="lazy")
|
||||||
|
|
||||||
proc getTabClass*(query: Query; tab: QueryKind): string =
|
proc getTabClass*(query: Query; tab: QueryKind): string =
|
||||||
if query.kind == tab: "tab-item active"
|
if query.kind == tab: "tab-item active"
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ Twitter feed for: ${desc}. Generated by ${getUrlPrefix(cfg)}
|
|||||||
<p>${text.replace("\n", "<br>\n")}</p>
|
<p>${text.replace("\n", "<br>\n")}</p>
|
||||||
#if tweet.photos.len > 0:
|
#if tweet.photos.len > 0:
|
||||||
# for photo in tweet.photos:
|
# for photo in tweet.photos:
|
||||||
<img src="${urlPrefix}${getPicUrl(photo)}" style="max-width:250px;" />
|
<img src="${urlPrefix}${getPicUrl(photo.url)}" style="max-width:250px;" />
|
||||||
# end for
|
# end for
|
||||||
#elif tweet.video.isSome:
|
#elif tweet.video.isSome:
|
||||||
<a href="${urlPrefix}${tweet.getLink}">
|
<a href="${urlPrefix}${tweet.getLink}">
|
||||||
|
|||||||
@@ -50,10 +50,12 @@ proc renderAlbum(tweet: Tweet): VNode =
|
|||||||
for photo in photos:
|
for photo in photos:
|
||||||
tdiv(class="attachment image"):
|
tdiv(class="attachment image"):
|
||||||
let
|
let
|
||||||
named = "name=" in photo
|
named = "name=" in photo.url
|
||||||
small = if named: photo else: photo & smallWebp
|
small = if named: photo.url else: photo.url & smallWebp
|
||||||
a(href=getOrigPicUrl(photo), class="still-image", target="_blank"):
|
a(href=getOrigPicUrl(photo.url), class="still-image", target="_blank"):
|
||||||
genImg(small)
|
genImg(small, alt=photo.altText)
|
||||||
|
if photo.altText.len > 0:
|
||||||
|
p(class="alt-text"): text "ALT " & photo.altText
|
||||||
|
|
||||||
proc isPlaybackEnabled(prefs: Prefs; playbackType: VideoType): bool =
|
proc isPlaybackEnabled(prefs: Prefs; playbackType: VideoType): bool =
|
||||||
case playbackType
|
case playbackType
|
||||||
|
|||||||
Reference in New Issue
Block a user