Compare commits

...

2 Commits

Author SHA1 Message Date
ngn
48b1d9e565
fix video playback
Some checks failed
Build and publish the docker image / build (push) Failing after 14s
Signed-off-by: ngn <ngn@ngn.tf>
2025-01-21 05:29:57 +03:00
ngn
96dad1e3a1
remove about page
Signed-off-by: ngn <ngn@ngn.tf>
2025-01-21 05:26:35 +03:00
11 changed files with 15 additions and 124 deletions

View File

@ -10,17 +10,16 @@ RUN nimble install -y --depsOnly
COPY . . COPY . .
RUN nimble build -d:danger -d:lto -d:strip RUN nimble build -d:danger -d:lto -d:strip
RUN nimble scss RUN nimble scss
RUN nimble md
FROM alpine:latest FROM debian:unstable-slim
RUN apk --no-cache add pcre ca-certificates RUN apk --no-cache add pcre ca-certificates
RUN useradd -d /src -u 1001 nitter RUN useradd -d /src -u 1001 nitter
WORKDIR /srv WORKDIR /srv
COPY --from=build /srv/nitter ./ COPY --from=build /src/nitter ./
COPY --from=build /srv/public ./public COPY --from=build /src/public ./public
USER nitter USER nitter
CMD ./nitter CMD ./nitter

View File

@ -15,7 +15,6 @@ requires "jester#baca3f"
requires "karax#5cf360c" requires "karax#5cf360c"
requires "sass#7dfdd03" requires "sass#7dfdd03"
requires "nimcrypto#a079df9" requires "nimcrypto#a079df9"
requires "markdown#158efe3"
requires "packedjson#9e6fbb6" requires "packedjson#9e6fbb6"
requires "supersnappy#6c94198" requires "supersnappy#6c94198"
requires "redpool#8b7c1db" requires "redpool#8b7c1db"
@ -29,6 +28,3 @@ requires "oauth#b8c163b"
task scss, "Generate css": task scss, "Generate css":
exec "nimble c --hint[Processing]:off -d:danger -r tools/gencss" exec "nimble c --hint[Processing]:off -d:danger -r tools/gencss"
task md, "Render md":
exec "nimble c --hint[Processing]:off -d:danger -r tools/rendermd"

File diff suppressed because one or more lines are too long

2
public/js/hls.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,54 +0,0 @@
# About
Nitter is a free and open source alternative Twitter front-end focused on
privacy and performance. The source is available on GitHub at
<https://github.com/zedeus/nitter>
* No JavaScript or ads
* All requests go through the backend, client never talks to Twitter
* Prevents Twitter from tracking your IP or JavaScript fingerprint
* Uses Twitter's unofficial API (no rate limits or developer account required)
* Lightweight (for [@nim_lang](/nim_lang), 60KB vs 784KB from twitter.com)
* RSS feeds
* Themes
* Mobile support (responsive design)
* AGPLv3 licensed, no proprietary instances permitted
Nitter's GitHub wiki contains
[instances](https://github.com/zedeus/nitter/wiki/Instances) and
[browser extensions](https://github.com/zedeus/nitter/wiki/Extensions)
maintained by the community.
## Why use Nitter?
It's impossible to use Twitter without JavaScript enabled. For privacy-minded
folks, preventing JavaScript analytics and IP-based tracking is important, but
apart from using a VPN and uBlock/uMatrix, it's impossible. Despite being behind
a VPN and using heavy-duty adblockers, you can get accurately tracked with your
[browser's fingerprint](https://restoreprivacy.com/browser-fingerprinting/),
[no JavaScript required](https://noscriptfingerprint.com/). This all became
particularly important after Twitter [removed the
ability](https://www.eff.org/deeplinks/2020/04/twitter-removes-privacy-option-and-shows-why-we-need-strong-privacy-laws)
for users to control whether their data gets sent to advertisers.
Using an instance of Nitter (hosted on a VPS for example), you can browse
Twitter without JavaScript while retaining your privacy. In addition to
respecting your privacy, Nitter is on average around 15 times lighter than
Twitter, and in most cases serves pages faster (eg. timelines load 2-4x faster).
In the future a simple account system will be added that lets you follow Twitter
users, allowing you to have a clean chronological timeline without needing a
Twitter account.
## Donating
Liberapay: <https://liberapay.com/zedeus> \
Patreon: <https://patreon.com/nitter> \
BTC: bc1qp7q4qz0fgfvftm5hwz3vy284nue6jedt44kxya \
ETH: 0x66d84bc3fd031b62857ad18c62f1ba072b011925 \
LTC: ltc1qhsz5nxw6jw9rdtw9qssjeq2h8hqk2f85rdgpkr \
XMR: 42hKayRoEAw4D6G6t8mQHPJHQcXqofjFuVfavqKeNMNUZfeJLJAcNU19i1bGdDvcdN6romiSscWGWJCczFLe9RFhM3d1zpL
## Contact
Feel free to join our [Matrix channel](https://matrix.to/#/#nitter:matrix.org).

View File

@ -35,7 +35,7 @@ proc shortLink*(text: string; length=28): string =
result = text.replace(wwwRegex, "") result = text.replace(wwwRegex, "")
if result.len > length: if result.len > length:
result = result[0 ..< length] & "" result = result[0 ..< length] & ""
proc stripHtml*(text: string; shorten=false): string = proc stripHtml*(text: string; shorten=false): string =
var html = parseHtml(text) var html = parseHtml(text)
for el in html.findAll("a"): for el in html.findAll("a"):
@ -82,6 +82,8 @@ proc proxifyVideo*(manifest: string; proxy: bool): string =
for line in manifest.splitLines: for line in manifest.splitLines:
let url = let url =
if line.startsWith("#EXT-X-MAP:URI"): line[16 .. ^2] if line.startsWith("#EXT-X-MAP:URI"): line[16 .. ^2]
elif line.startsWith("#EXT-X-MEDIA") and "URI=" in line:
line[line.find("URI=") + 5 .. -1 + line.find("\"", start= 5 + line.find("URI="))]
else: line else: line
if url.startsWith('/'): if url.startsWith('/'):
let path = "https://video.twimg.com" & url let path = "https://video.twimg.com" & url

View File

@ -8,14 +8,11 @@ from os import getEnv
import jester import jester
import types, config, prefs, formatters, redis_cache, http_pool, auth import types, config, prefs, formatters, redis_cache, http_pool, auth
import views/[general, about] import views/[general]
import routes/[ import routes/[
preferences, timeline, status, media, search, rss, list, debug, preferences, timeline, status, media, search, rss, list, debug,
unsupported, embed, resolver, router_utils] unsupported, embed, resolver, router_utils]
const instancesUrl = "https://github.com/zedeus/nitter/wiki/Instances"
const issuesUrl = "https://github.com/zedeus/nitter/issues"
initAccountPool(cfg) initAccountPool(cfg)
if not cfg.enableDebug: if not cfg.enableDebug:
@ -32,7 +29,6 @@ setHmacKey(cfg.hmacKey)
setProxyEncoding(cfg.base64Media) setProxyEncoding(cfg.base64Media)
setMaxHttpConns(cfg.httpMaxConns) setMaxHttpConns(cfg.httpMaxConns)
setHttpProxy(cfg.proxy, cfg.proxyAuth) setHttpProxy(cfg.proxy, cfg.proxyAuth)
initAboutPage(cfg.staticDir)
waitFor initRedisPool(cfg) waitFor initRedisPool(cfg)
stdout.write &"Connected to Redis at {cfg.redisHost}:{cfg.redisPort}\n" stdout.write &"Connected to Redis at {cfg.redisHost}:{cfg.redisPort}\n"
@ -60,15 +56,6 @@ routes:
get "/": get "/":
resp renderMain(renderSearch(), request, cfg, themePrefs()) resp renderMain(renderSearch(), request, cfg, themePrefs())
get "/about":
resp renderMain(renderAbout(), request, cfg, themePrefs())
get "/explore":
redirect("/about")
get "/help":
redirect("/about")
get "/i/redirect": get "/i/redirect":
let url = decodeUrl(@"url") let url = decodeUrl(@"url")
if url.len == 0: resp Http404 if url.len == 0: resp Http404
@ -79,18 +66,17 @@ routes:
error InternalError: error InternalError:
echo error.exc.name, ": ", error.exc.msg echo error.exc.name, ": ", error.exc.msg
const link = a("open a GitHub issue", href = issuesUrl) const link = a("https://git.ngn.tf/ngn/nitter", href = "https://git.ngn.tf/ngn/nitter")
resp Http500, showError( resp Http500, showError(
&"An error occurred, please {link} with the URL you tried to visit.", cfg) &"An error occurred, please report to {link}", cfg)
error BadClientError: error BadClientError:
echo error.exc.name, ": ", error.exc.msg echo error.exc.name, ": ", error.exc.msg
resp Http500, showError("Network error occurred, please try again.", cfg) resp Http500, showError("Network error occurred, please try again.", cfg)
error RateLimitError: error RateLimitError:
const link = a("another instance", href = instancesUrl)
resp Http429, showError( resp Http429, showError(
&"Instance has been rate limited.<br>Use {link} or try again later.", cfg) &"Instance has been rate limited.", cfg)
extend rss, "" extend rss, ""
extend status, "" extend status, ""

View File

@ -12,11 +12,10 @@ proc createUnsupportedRouter*(cfg: Config) =
template feature {.dirty.} = template feature {.dirty.} =
resp renderMain(renderFeature(), request, cfg, themePrefs()) resp renderMain(renderFeature(), request, cfg, themePrefs())
get "/about/feature": feature()
get "/login/?@i?": feature() get "/login/?@i?": feature()
get "/@name/lists/?": feature() get "/@name/lists/?": feature()
get "/intent/?@i?": get "/intent/?@i?":
cond @"i" notin ["user"] cond @"i" notin ["user"]
feature() feature()

View File

@ -1,26 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-only
import os, strformat
import karax/[karaxdsl, vdom]
const
date = staticExec("git show -s --format=\"%cd\" --date=format:\"%Y.%m.%d\"")
hash = staticExec("git show -s --format=\"%h\"")
link = "https://github.com/zedeus/nitter/commit/" & hash
version = &"{date}-{hash}"
var aboutHtml: string
proc initAboutPage*(dir: string) =
try:
aboutHtml = readFile(dir/"md/about.html")
except IOError:
stderr.write (dir/"md/about.html") & " not found, please run `nimble md`\n"
aboutHtml = "<h1>About page is missing</h1><br><br>"
proc renderAbout*(): VNode =
buildHtml(tdiv(class="overlay-panel")):
verbatim aboutHtml
h2: text "Instance info"
p:
text "Version "
a(href=link): text version

View File

@ -6,9 +6,3 @@ proc renderFeature*(): VNode =
h1: text "Unsupported feature" h1: text "Unsupported feature"
p: p:
text "Nitter doesn't support this feature yet, but it might in the future. " text "Nitter doesn't support this feature yet, but it might in the future. "
text "You can check for an issue and open one if needed here: "
a(href="https://github.com/zedeus/nitter/issues"):
text "https://github.com/zedeus/nitter/issues"
p:
text "To find out more about the Nitter project, see the "
a(href="/about"): text "About page"

View File

@ -31,9 +31,7 @@ proc renderNavbar(cfg: Config; req: Request; rss, canonical: string): VNode =
icon "search", title="Search", href="/search" icon "search", title="Search", href="/search"
if cfg.enableRss and rss.len > 0: if cfg.enableRss and rss.len > 0:
icon "rss-feed", title="RSS Feed", href=rss icon "rss-feed", title="RSS Feed", href=rss
icon "bird", title="Open in Twitter", href=canonical
a(href="https://liberapay.com/zedeus"): verbatim lp a(href="https://liberapay.com/zedeus"): verbatim lp
icon "info", title="About", href="/about"
icon "cog", title="Preferences", href=("/settings?referer=" & encodeUrl(path)) icon "cog", title="Preferences", href=("/settings?referer=" & encodeUrl(path))
proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc=""; proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc="";
@ -42,7 +40,7 @@ proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc="";
var theme = prefs.theme.toTheme var theme = prefs.theme.toTheme
if "theme" in req.params: if "theme" in req.params:
theme = req.params["theme"].toTheme theme = req.params["theme"].toTheme
let ogType = let ogType =
if video.len > 0: "video" if video.len > 0: "video"
elif rss.len > 0: "object" elif rss.len > 0: "object"
@ -73,7 +71,7 @@ proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc="";
link(rel="alternate", type="application/rss+xml", href=rss, title="RSS feed") link(rel="alternate", type="application/rss+xml", href=rss, title="RSS feed")
if prefs.hlsPlayback: if prefs.hlsPlayback:
script(src="/js/hls.light.min.js", `defer`="") script(src="/js/hls.min.js", `defer`="")
script(src="/js/hlsPlayback.js", `defer`="") script(src="/js/hlsPlayback.js", `defer`="")
if prefs.infiniteScroll: if prefs.infiniteScroll: