From 1628f2c39a62741807c905c655482c36d35a947d Mon Sep 17 00:00:00 2001 From: okxlin Date: Sun, 12 May 2024 19:30:50 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=B7=BB=E5=8A=A0nitter=E5=88=B0=E5=88=97?= =?UTF-8?q?=E8=A1=A8#457?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/nitter/README.md | 20 +++ apps/nitter/data.yml | 19 ++ apps/nitter/latest/.env.sample | 30 ++++ apps/nitter/latest/data.yml | 238 ++++++++++++++++++++++++++ apps/nitter/latest/data/nitter.conf | 44 +++++ apps/nitter/latest/docker-compose.yml | 29 ++++ apps/nitter/latest/scripts/init.sh | 32 ++++ apps/nitter/logo.png | Bin 0 -> 1428 bytes 8 files changed, 412 insertions(+) create mode 100644 apps/nitter/README.md create mode 100644 apps/nitter/data.yml create mode 100644 apps/nitter/latest/.env.sample create mode 100644 apps/nitter/latest/data.yml create mode 100644 apps/nitter/latest/data/nitter.conf create mode 100644 apps/nitter/latest/docker-compose.yml create mode 100644 apps/nitter/latest/scripts/init.sh create mode 100644 apps/nitter/logo.png diff --git a/apps/nitter/README.md b/apps/nitter/README.md new file mode 100644 index 00000000..ad1ed7e1 --- /dev/null +++ b/apps/nitter/README.md @@ -0,0 +1,20 @@ +# Nitter + +[![Test Matrix](https://github.com/zedeus/nitter/workflows/Tests/badge.svg)](https://github.com/zedeus/nitter/actions/workflows/run-tests.yml) +[![Test Matrix](https://github.com/zedeus/nitter/workflows/Docker/badge.svg)](https://github.com/zedeus/nitter/actions/workflows/build-docker.yml) +[![License](https://img.shields.io/github/license/zedeus/nitter?style=flat)](#license) + +A free and open source alternative Twitter front-end focused on privacy and +performance. \ +Inspired by the [Invidious](https://github.com/iv-org/invidious) +project. + +- 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](https://nitter.net/nim_lang), 60KB vs 784KB from twitter.com) +- RSS feeds +- Themes +- Mobile support (responsive design) +- AGPLv3 licensed, no proprietary instances permitted \ No newline at end of file diff --git a/apps/nitter/data.yml b/apps/nitter/data.yml new file mode 100644 index 00000000..51077332 --- /dev/null +++ b/apps/nitter/data.yml @@ -0,0 +1,19 @@ +name: Nitter +tags: + - 实用工具 +title: 匿名浏览 Twitter +description: 匿名浏览 Twitter 的开源工具 +additionalProperties: + key: nitter + name: Nitter + tags: + - Tool + shortDescZh: 匿名浏览 Twitter 的开源工具 + shortDescEn: Alternative Twitter front-end + type: tool + crossVersionUpdate: true + limit: 0 + recommend: 0 + website: https://nitter.net + github: https://github.com/zedeus/nitter + document: https://github.com/zedeus/nitter diff --git a/apps/nitter/latest/.env.sample b/apps/nitter/latest/.env.sample new file mode 100644 index 00000000..52faee79 --- /dev/null +++ b/apps/nitter/latest/.env.sample @@ -0,0 +1,30 @@ +ADDRESS="0.0.0.0" +BASE64_MEDIA="false" +CONTAINER_NAME="nitter" +DATA_PATH="./data" +ENABLE_DEBUG="false" +ENABLE_RSS="true" +HLS_PLAYBACK="false" +HMAC_KEY="C7PPBcaNCL5B5Zkt6uHU" +HOSTNAME="nitter.net" +HTTPS="false" +HTTP_MAX_CONNECTIONS="100" +INFINITE_SCROLL="false" +LIST_MINUTES="240" +PANEL_APP_PORT_HTTP="40238" +PANEL_REDIS_ROOT_PASSWORD="E5TRJPM0U43WN8Ac7G7ks1cFzYgLyH" +PROXY="" +PROXY_AUTH="" +PROXY_VIDEOS="true" +REDIS_CONNECTIONS="20" +REDIS_HOST="redis" +REDIS_MAX_CONNECTIONS="30" +REDIS_PORT="6379" +REPLACE_REDDIT="teddit.net" +REPLACE_TWITTER="nitter.net" +REPLACE_YOUTUBE="piped.video" +RSS_MINUTES="10" +STATIC_DIR="./public" +THEME="Nitter" +TITLE="nitter" +TOKEN_COUNT="10" diff --git a/apps/nitter/latest/data.yml b/apps/nitter/latest/data.yml new file mode 100644 index 00000000..e1b0cd0b --- /dev/null +++ b/apps/nitter/latest/data.yml @@ -0,0 +1,238 @@ +additionalProperties: + formFields: + - default: "nitter.net" + edit: true + envKey: HOSTNAME + labelEn: Hostname + labelZh: 主机名 + required: true + type: text + - default: "nitter" + edit: true + envKey: TITLE + labelEn: Title + labelZh: 标题 + required: true + type: text + - default: "0.0.0.0" + edit: true + envKey: ADDRESS + labelEn: Listening Address (in container) + labelZh: 监听地址 (容器内) + required: true + type: text + - default: "40238" + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: HTTP Port + labelZh: HTTP 端口 + required: true + rule: paramPort + type: number + - default: ./data + disabled: true + envKey: DATA_PATH + labelEn: Data folder path + labelZh: 数据文件夹路径 + required: true + type: text + - default: "false" + edit: true + envKey: HTTPS + labelEn: HTTPS Enabled + labelZh: 启用 HTTPS + required: true + type: select + values: + - label: "True" + value: "true" + - label: "False" + value: "false" + - default: "100" + edit: true + envKey: HTTP_MAX_CONNECTIONS + labelEn: Max HTTP Connections + labelZh: 最大 HTTP 连接数 + required: true + type: number + - default: "./public" + edit: true + envKey: STATIC_DIR + labelEn: Static Directory + labelZh: 静态文件目录 + required: true + type: text + - default: "240" + edit: true + envKey: LIST_MINUTES + labelEn: List Cache Minutes + labelZh: 列表缓存分钟数 + required: true + type: number + - default: "10" + edit: true + envKey: RSS_MINUTES + labelEn: RSS Cache Minutes + labelZh: RSS 缓存分钟数 + required: true + type: number + - default: "" + edit: true + envKey: REDIS_HOST + key: redis + labelEn: Redis Service + labelZh: Redis服务 + required: true + type: service + - default: "6379" + edit: true + envKey: REDIS_PORT + labelEn: Redis Service Port + labelZh: Redis服务端口 + required: true + rule: paramPort + type: number + - default: "" + edit: true + envKey: PANEL_REDIS_ROOT_PASSWORD + labelEn: Redis Password + labelZh: Redis 密码 + required: true + type: password + - default: "20" + edit: true + envKey: REDIS_CONNECTIONS + labelEn: Redis Connections + labelZh: Redis 连接数 + required: true + type: number + - default: "30" + edit: true + envKey: REDIS_MAX_CONNECTIONS + labelEn: Redis Max Connections + labelZh: Redis 最大连接数 + required: true + type: number + - default: "C7PPBcaNCL5B5Zkt6uHU" + edit: true + envKey: HMAC_KEY + labelEn: Random key for cryptographic signing of video urls + labelZh: 用于视频网址加密签名的随机密钥 + required: true + type: text + - default: "false" + edit: true + envKey: BASE64_MEDIA + labelEn: Base64 Media + labelZh: Base64 媒体 + required: true + type: text + - default: "true" + edit: true + envKey: ENABLE_RSS + labelEn: Enable RSS + labelZh: 启用 RSS + required: true + type: select + values: + - label: "True" + value: "true" + - label: "False" + value: "false" + - default: "false" + edit: true + envKey: ENABLE_DEBUG + labelEn: Enable Debug + labelZh: 启用调试 + required: true + type: select + values: + - label: "True" + value: "true" + - label: "False" + value: "false" + - default: "" + edit: true + envKey: PROXY + labelEn: Proxy + labelZh: 代理 + required: false + type: text + - default: "" + edit: true + envKey: PROXY_AUTH + labelEn: Proxy Auth + labelZh: 代理认证 + required: false + type: text + - default: "10" + edit: true + envKey: TOKEN_COUNT + labelEn: Token Count + labelZh: Token 数量 + required: true + type: number + - default: "Nitter" + edit: true + envKey: THEME + labelEn: Theme + labelZh: 主题 + required: true + type: text + - default: "nitter.net" + edit: true + envKey: REPLACE_TWITTER + labelEn: Replace Twitter + labelZh: 替换 Twitter + required: true + type: text + - default: "piped.video" + edit: true + envKey: REPLACE_YOUTUBE + labelEn: Replace YouTube + labelZh: 替换 YouTube + required: true + type: text + - default: "teddit.net" + edit: true + envKey: REPLACE_REDDIT + labelEn: Replace Reddit + labelZh: 替换 Reddit + required: true + type: text + - default: "true" + edit: true + envKey: PROXY_VIDEOS + labelEn: Proxy Videos + labelZh: 代理视频 + required: true + type: select + values: + - label: "True" + value: "true" + - label: "False" + value: "false" + - default: "false" + edit: true + envKey: HLS_PLAYBACK + labelEn: HLS Playback + labelZh: HLS 播放 + required: true + type: select + values: + - label: "True" + value: "true" + - label: "False" + value: "false" + - default: "false" + edit: true + envKey: INFINITE_SCROLL + labelEn: Infinite Scroll + labelZh: 无限滚动 + required: true + type: select + values: + - label: "True" + value: "true" + - label: "False" + value: "false" diff --git a/apps/nitter/latest/data/nitter.conf b/apps/nitter/latest/data/nitter.conf new file mode 100644 index 00000000..ecce9eb9 --- /dev/null +++ b/apps/nitter/latest/data/nitter.conf @@ -0,0 +1,44 @@ +[Server] +hostname = "nitter.net" # for generating links, change this to your own domain/ip +title = "nitter" +address = "0.0.0.0" +port = 8080 +https = false # disable to enable cookies when not using https +httpMaxConnections = 100 +staticDir = "./public" + +[Cache] +listMinutes = 240 # how long to cache list info (not the tweets, so keep it high) +rssMinutes = 10 # how long to cache rss queries +redisHost = "localhost" # Change to "nitter-redis" if using docker-compose +redisPort = 6379 +redisPassword = "" +redisConnections = 20 # minimum open connections in pool +redisMaxConnections = 30 +# new connections are opened when none are available, but if the pool size +# goes above this, they're closed when released. don't worry about this unless +# you receive tons of requests per second + +[Config] +hmacKey = "secretkey" # random key for cryptographic signing of video urls +base64Media = false # use base64 encoding for proxied media urls +enableRSS = true # set this to false to disable RSS feeds +enableDebug = false # enable request logs and debug endpoints (/.tokens) +proxy = "" # http/https url, SOCKS proxies are not supported +proxyAuth = "" +tokenCount = 10 +# minimum amount of usable tokens. tokens are used to authorize API requests, +# but they expire after ~1 hour, and have a limit of 500 requests per endpoint. +# the limits reset every 15 minutes, and the pool is filled up so there's +# always at least `tokenCount` usable tokens. only increase this if you receive +# major bursts all the time and don't have a rate limiting setup via e.g. nginx + +# Change default preferences here, see src/prefs_impl.nim for a complete list +[Preferences] +theme = "Nitter" +replaceTwitter = "nitter.net" +replaceYouTube = "piped.video" +replaceReddit = "teddit.net" +proxyVideos = true +hlsPlayback = false +infiniteScroll = false \ No newline at end of file diff --git a/apps/nitter/latest/docker-compose.yml b/apps/nitter/latest/docker-compose.yml new file mode 100644 index 00000000..e5e809b7 --- /dev/null +++ b/apps/nitter/latest/docker-compose.yml @@ -0,0 +1,29 @@ +version: '3' +services: + nitter: + image: zedeus/nitter:latest + container_name: ${CONTAINER_NAME} + restart: always + networks: + - 1panel-network + ports: + - "${PANEL_APP_PORT_HTTP}:${PANEL_APP_PORT_HTTP}" + volumes: + - ${DATA_PATH}/nitter.conf:/src/nitter.conf:Z,ro + healthcheck: + test: wget -nv --tries=1 --spider http://127.0.0.1:${PANEL_APP_PORT_HTTP}/Jack/status/20 || exit 1 + interval: 30s + timeout: 5s + retries: 2 + user: "998:998" + read_only: true + security_opt: + - no-new-privileges:true + cap_drop: + - ALL + labels: + createdBy: "Apps" + +networks: + 1panel-network: + external: true diff --git a/apps/nitter/latest/scripts/init.sh b/apps/nitter/latest/scripts/init.sh new file mode 100644 index 00000000..3dffec4a --- /dev/null +++ b/apps/nitter/latest/scripts/init.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +source ./.env + +sed -i "s/hostname = \".*\"/hostname = \"${HOSTNAME}\"/" ./data/nitter.conf +sed -i "s/title = \".*\"/title = \"${TITLE}\"/" ./data/nitter.conf +sed -i "s/address = \".*\"/address = \"${ADDRESS}\"/" ./data/nitter.conf +sed -i "s/port = .*/port = ${PANEL_APP_PORT_HTTP}/" ./data/nitter.conf +sed -i "s/https = .*/https = ${HTTPS}/" ./data/nitter.conf +sed -i "s/httpMaxConnections = .*/httpMaxConnections = ${HTTP_MAX_CONNECTIONS}/" ./data/nitter.conf +sed -i "s/staticDir = \".*\"/staticDir = \"${STATIC_DIR}\"/" ./data/nitter.conf +sed -i "s/listMinutes = .*/listMinutes = ${LIST_MINUTES}/" ./data/nitter.conf +sed -i "s/rssMinutes = .*/rssMinutes = ${RSS_MINUTES}/" ./data/nitter.conf +sed -i "s/redisHost = \".*\"/redisHost = \"${REDIS_HOST}\"/" ./data/nitter.conf +sed -i "s/redisPort = .*/redisPort = ${REDIS_PORT}/" ./data/nitter.conf +sed -i "s/redisPassword = \".*\"/redisPassword = \"${PANEL_REDIS_ROOT_PASSWORD}\"/" ./data/nitter.conf +sed -i "s/redisConnections = .*/redisConnections = ${REDIS_CONNECTIONS}/" ./data/nitter.conf +sed -i "s/redisMaxConnections = .*/redisMaxConnections = ${REDIS_MAX_CONNECTIONS}/" ./data/nitter.conf +sed -i "s/hmacKey = \".*\"/hmacKey = \"${HMAC_KEY}\"/" ./data/nitter.conf +sed -i "s/base64Media = .*/base64Media = ${BASE64_MEDIA}/" ./data/nitter.conf +sed -i "s/enableRSS = .*/enableRSS = ${ENABLE_RSS}/" ./data/nitter.conf +sed -i "s/enableDebug = .*/enableDebug = ${ENABLE_DEBUG}/" ./data/nitter.conf +sed -i "s/proxy = \".*\"/proxy = \"${PROXY}\"/" ./data/nitter.conf +sed -i "s/proxyAuth = \".*\"/proxyAuth = \"${PROXY_AUTH}\"/" ./data/nitter.conf +sed -i "s/tokenCount = .*/tokenCount = ${TOKEN_COUNT}/" ./data/nitter.conf +sed -i "s/theme = \".*\"/theme = \"${THEME}\"/" ./data/nitter.conf +sed -i "s/replaceTwitter = \".*\"/replaceTwitter = \"${REPLACE_TWITTER}\"/" ./data/nitter.conf +sed -i "s/replaceYouTube = \".*\"/replaceYouTube = \"${REPLACE_YOUTUBE}\"/" ./data/nitter.conf +sed -i "s/replaceReddit = \".*\"/replaceReddit = \"${REPLACE_REDDIT}\"/" ./data/nitter.conf +sed -i "s/proxyVideos = .*/proxyVideos = ${PROXY_VIDEOS}/" ./data/nitter.conf +sed -i "s/hlsPlayback = .*/hlsPlayback = ${HLS_PLAYBACK}/" ./data/nitter.conf +sed -i "s/infiniteScroll = .*/infiniteScroll = ${INFINITE_SCROLL}/" ./data/nitter.conf diff --git a/apps/nitter/logo.png b/apps/nitter/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..22eb98834933d92c6ad405ea6ce5a31c126334eb GIT binary patch literal 1428 zcmbVMX;4#F6n+>=7J)Dkiar%?*Y7+$Wlln-!eaIYAJA@py_zA~_fUHLZiq5I zYBg$QqCC1@_}ofl942vORkUw}r|IrdD}gdDaK=aM3?7K#ty- zHKkNNXzum{XSO5};U-N{oda^o;if;>=_Iqn`W@j-=b{-J9TiD55}t++xd?T+=(w3Z za`eHhhN+c)SL6d(M~k;nsyv$O?2+2PKjfkefQ?DD0&uBcA!kHI&(p=|a#Ch=06xR?O%~x77p{pVlS{QqdR=Y)+Sl%W~SnsJH zqdL`eIP}*z@j^+}0wC)cN$tE`oZ7d##3iboWIrt9o=Jmv70GWnN>7P4V=~7|>|WsY z6Eb)?%jHZ+!)RB>JfGDtX!rBhKYD5UdwJ>gQT#_VVU-Bq8xf(MERNOn0%H`Rqosny z1yTvM=u=JqwkfV0mRc@vUSK4X=$4A?3-guW=uqdt%Xa196(=6|&gU>U!%!(Y-fv{& z(1h}yw~AujfE{@%i^GS#W7{jFsA6{dHtyLCCwV&KlRJ2bh5WYAqPQ{gJ4WOjQ{Il{ z?wE6Ip7eg9yZ@Lk%kDE5KAE=AlnTrk;x<@ia0rt_qQB`n*)yLOg4ACuH8IYmBe?1i zJtm5E>XDn_h6t!ioDO8U2{*+n#)3t>M-4{?#l~g*&jX|RogM|a}MAnLhCX161 zf?O(9N5r*+H2CpblPI=h3FDU?ha3O;5vZ&7AMMNmc5g3mOiM@^bt_0Of9l&mLaVX^ zaa^{B;;~>$R*<=*ImR({<~JWCO(X-!S5;hv6dZ`xu{|QhNTKY0jwfAn{m8!yN~-oVyggfuy3b7 zsB_$4#=-Y8AzOfo@Fhe7o!?prtD@X#*n8$N@FX^bBW4Hfk#~vaL^}S6DXjWzN8z|v zmY|EVGdMGjx9;}3FQdk4o6U!ZT4TkApzc>^3dd$0P5$;)CQWXddlFq_=!@W|!D<{R zY5BMgd37n7P=e}h$xLljwUTNt&wf>n14Z309PDbt)9M%@(Wt$m*uSY0;^eGX*qruC@4?mXJD5KcnB@D`BA_YfeGgMsapJm7IB!Syrrwm1 gi$QC611+e{FK<+R90+gn)NdN!< literal 0 HcmV?d00001