general cleanup
Some checks failed
Build and publish the docker image / build (push) Failing after 13s
Some checks failed
Build and publish the docker image / build (push) Failing after 13s
Signed-off-by: ngn <ngn@ngn.tf>
This commit is contained in:
parent
7350155d2d
commit
62183646ae
28
.gitea/workflows/build.yml
Normal file
28
.gitea/workflows/build.yml
Normal file
@ -0,0 +1,28 @@
|
||||
name: Build and publish the docker image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["custom"]
|
||||
|
||||
env:
|
||||
REGISTRY: git.ngn.tf
|
||||
IMAGE: ${{gitea.repository}}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: "https://github.com/actions/checkout@v4"
|
||||
|
||||
- name: Login to container repo
|
||||
uses: "https://github.com/docker/login-action@v1"
|
||||
with:
|
||||
registry: ${{env.REGISTRY}}
|
||||
username: ${{gitea.actor}}
|
||||
password: ${{secrets.PACKAGES_TOKEN}}
|
||||
|
||||
- name: Build image
|
||||
run: |
|
||||
docker build . --tag ${{env.REGISTRY}}/${{env.IMAGE}}:latest
|
||||
docker push ${{env.REGISTRY}}/${{env.IMAGE}}:latest
|
3
.github/FUNDING.yml
vendored
3
.github/FUNDING.yml
vendored
@ -1,3 +0,0 @@
|
||||
github: zedeus
|
||||
liberapay: zedeus
|
||||
patreon: nitter
|
60
.github/workflows/build-publish-docker.yml
vendored
60
.github/workflows/build-publish-docker.yml
vendored
@ -1,60 +0,0 @@
|
||||
name: Build and Publish Docker
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master"]
|
||||
paths-ignore: ["README.md"]
|
||||
pull_request:
|
||||
branches: ["master"]
|
||||
paths-ignore: ["README.md"]
|
||||
|
||||
env:
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
id: qemu
|
||||
uses: docker/setup-qemu-action@v2
|
||||
with:
|
||||
platforms: arm64
|
||||
|
||||
- name: Setup Docker buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: |
|
||||
ghcr.io/${{ env.IMAGE_NAME }}
|
||||
|
||||
|
||||
- name: Build and push all platforms Docker image
|
||||
id: build-and-push
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
56
.github/workflows/run-tests.yml
vendored
56
.github/workflows/run-tests.yml
vendored
@ -1,56 +0,0 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
branches-ignore:
|
||||
- master
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: buildjet-2vcpu-ubuntu-2204
|
||||
strategy:
|
||||
matrix:
|
||||
nim:
|
||||
- "1.6.10"
|
||||
- "1.6.x"
|
||||
- "2.0.x"
|
||||
- "devel"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Cache nimble
|
||||
id: cache-nimble
|
||||
uses: buildjet/cache@v3
|
||||
with:
|
||||
path: ~/.nimble
|
||||
key: ${{ matrix.nim }}-nimble-${{ hashFiles('*.nimble') }}
|
||||
restore-keys: |
|
||||
${{ matrix.nim }}-nimble-
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.10"
|
||||
cache: "pip"
|
||||
- uses: jiro4989/setup-nim-action@v1
|
||||
with:
|
||||
nim-version: ${{ matrix.nim }}
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- run: nimble build -d:release -Y
|
||||
- run: pip install seleniumbase
|
||||
- run: seleniumbase install chromedriver
|
||||
- uses: supercharge/redis-github-action@1.5.0
|
||||
- name: Prepare Nitter
|
||||
run: |
|
||||
sudo apt install libsass-dev -y
|
||||
cp nitter.example.conf nitter.conf
|
||||
sed -i 's/enableDebug = false/enableDebug = true/g' nitter.conf
|
||||
nimble md
|
||||
nimble scss
|
||||
echo '${{ secrets.GUEST_ACCOUNTS }}' > ./guest_accounts.jsonl
|
||||
- name: Run tests
|
||||
run: |
|
||||
./nitter &
|
||||
pytest -n8 tests
|
20
.gitignore
vendored
20
.gitignore
vendored
@ -1,14 +1,16 @@
|
||||
nitter
|
||||
*.html
|
||||
*.db
|
||||
/tests/__pycache__
|
||||
/tests/geckodriver.log
|
||||
/tests/downloaded_files
|
||||
/tests/latest_logs
|
||||
/tools/gencss
|
||||
/tools/rendermd
|
||||
/public/css/style.css
|
||||
/public/md/*.html
|
||||
data
|
||||
tests/__pycache__
|
||||
tests/geckodriver.log
|
||||
tests/downloaded_files
|
||||
tests/latest_logs
|
||||
tools/gencss
|
||||
tools/rendermd
|
||||
public/css/style.css
|
||||
public/md/*.html
|
||||
nitter.conf
|
||||
guest_accounts.json*
|
||||
compose.yml
|
||||
accounts.*
|
||||
dump.rdb
|
||||
|
25
Dockerfile
25
Dockerfile
@ -1,25 +1,26 @@
|
||||
FROM nimlang/nim:2.0.0-alpine-regular as nim
|
||||
LABEL maintainer="setenforce@protonmail.com"
|
||||
FROM nimlang/nim:2.0.0-alpine-regular as build
|
||||
|
||||
RUN apk --no-cache add libsass-dev pcre
|
||||
|
||||
WORKDIR /src/nitter
|
||||
WORKDIR /src
|
||||
|
||||
COPY nitter.nimble .
|
||||
RUN nimble install -y --depsOnly
|
||||
|
||||
COPY . .
|
||||
RUN nimble build -d:danger -d:lto -d:strip \
|
||||
&& nimble scss \
|
||||
&& nimble md
|
||||
RUN nimble build -d:danger -d:lto -d:strip
|
||||
RUN nimble scss
|
||||
RUN nimble md
|
||||
|
||||
FROM alpine:latest
|
||||
WORKDIR /src/
|
||||
|
||||
RUN apk --no-cache add pcre ca-certificates
|
||||
COPY --from=nim /src/nitter/nitter ./
|
||||
COPY --from=nim /src/nitter/nitter.example.conf ./nitter.conf
|
||||
COPY --from=nim /src/nitter/public ./public
|
||||
EXPOSE 8080
|
||||
RUN adduser -h /src/ -D -s /bin/sh nitter
|
||||
RUN useradd -d /src -u 1001 nitter
|
||||
|
||||
WORKDIR /srv
|
||||
|
||||
COPY --from=build /srv/nitter ./
|
||||
COPY --from=build /srv/public ./public
|
||||
|
||||
USER nitter
|
||||
CMD ./nitter
|
||||
|
@ -1,25 +0,0 @@
|
||||
FROM alpine:3.18 as nim
|
||||
LABEL maintainer="setenforce@protonmail.com"
|
||||
|
||||
RUN apk --no-cache add libsass-dev pcre gcc git libc-dev "nim=1.6.14-r0" "nimble=0.13.1-r2"
|
||||
|
||||
WORKDIR /src/nitter
|
||||
|
||||
COPY nitter.nimble .
|
||||
RUN nimble install -y --depsOnly
|
||||
|
||||
COPY . .
|
||||
RUN nimble build -d:danger -d:lto -d:strip \
|
||||
&& nimble scss \
|
||||
&& nimble md
|
||||
|
||||
FROM alpine:3.18
|
||||
WORKDIR /src/
|
||||
RUN apk --no-cache add pcre ca-certificates openssl1.1-compat
|
||||
COPY --from=nim /src/nitter/nitter ./
|
||||
COPY --from=nim /src/nitter/nitter.example.conf ./nitter.conf
|
||||
COPY --from=nim /src/nitter/public ./public
|
||||
EXPOSE 8080
|
||||
RUN adduser -h /src/ -D -s /bin/sh nitter
|
||||
USER nitter
|
||||
CMD ./nitter
|
199
README.md
199
README.md
@ -1,198 +1,5 @@
|
||||
# Nitter
|
||||
# [ngn.tf] | 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)
|
||||
![](https://git.ngn.tf/ngn/nitter/actions/workflows/build.yml/badge.svg)
|
||||
|
||||
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
|
||||
|
||||
Liberapay: https://liberapay.com/zedeus \
|
||||
Patreon: https://patreon.com/nitter \
|
||||
BTC: bc1qp7q4qz0fgfvftm5hwz3vy284nue6jedt44kxya \
|
||||
ETH: 0x66d84bc3fd031b62857ad18c62f1ba072b011925 \
|
||||
LTC: ltc1qhsz5nxw6jw9rdtw9qssjeq2h8hqk2f85rdgpkr \
|
||||
XMR: 42hKayRoEAw4D6G6t8mQHPJHQcXqofjFuVfavqKeNMNUZfeJLJAcNU19i1bGdDvcdN6romiSscWGWJCczFLe9RFhM3d1zpL
|
||||
|
||||
## Roadmap
|
||||
|
||||
- Embeds
|
||||
- Account system with timeline support
|
||||
- Archiving tweets/profiles
|
||||
- Developer API
|
||||
|
||||
## New Features
|
||||
|
||||
- Likes tab
|
||||
|
||||
## Resources
|
||||
|
||||
The wiki contains
|
||||
[a list of instances](https://github.com/zedeus/nitter/wiki/Instances) and
|
||||
[browser extensions](https://github.com/zedeus/nitter/wiki/Extensions)
|
||||
maintained by the community.
|
||||
|
||||
## Why?
|
||||
|
||||
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.
|
||||
|
||||
## Screenshot
|
||||
|
||||
![nitter](/screenshot.png)
|
||||
|
||||
## Installation
|
||||
|
||||
### Dependencies
|
||||
|
||||
- libpcre
|
||||
- libsass
|
||||
- redis
|
||||
|
||||
To compile Nitter you need a Nim installation, see
|
||||
[nim-lang.org](https://nim-lang.org/install.html) for details. It is possible to
|
||||
install it system-wide or in the user directory you create below.
|
||||
|
||||
To compile the scss files, you need to install `libsass`. On Ubuntu and Debian,
|
||||
you can use `libsass-dev`.
|
||||
|
||||
Redis is required for caching and in the future for account info. It should be
|
||||
available on most distros as `redis` or `redis-server` (Ubuntu/Debian).
|
||||
Running it with the default config is fine, Nitter's default config is set to
|
||||
use the default Redis port and localhost.
|
||||
|
||||
Here's how to create a `nitter` user, clone the repo, and build the project
|
||||
along with the scss and md files.
|
||||
|
||||
```bash
|
||||
# useradd -m nitter
|
||||
# su nitter
|
||||
$ git clone https://github.com/zedeus/nitter
|
||||
$ cd nitter
|
||||
$ nimble build -d:release
|
||||
$ nimble scss
|
||||
$ nimble md
|
||||
$ cp nitter.example.conf nitter.conf
|
||||
```
|
||||
|
||||
Edit `twitter_oauth.sh` with your Twitter account name and password.
|
||||
|
||||
```
|
||||
$ ./twitter_oauth.sh | tee -a guest_accounts.jsonl
|
||||
```
|
||||
|
||||
Set your hostname, port, HMAC key, https (must be correct for cookies), and
|
||||
Redis info in `nitter.conf`. To run Redis, either run
|
||||
`redis-server --daemonize yes`, or `systemctl enable --now redis` (or
|
||||
redis-server depending on the distro). Run Nitter by executing `./nitter` or
|
||||
using the systemd service below. You should run Nitter behind a reverse proxy
|
||||
such as [Nginx](https://github.com/zedeus/nitter/wiki/Nginx) or
|
||||
[Apache](https://github.com/zedeus/nitter/wiki/Apache) for security and
|
||||
performance reasons.
|
||||
|
||||
### Docker
|
||||
|
||||
Page for the Docker image: https://hub.docker.com/r/zedeus/nitter
|
||||
|
||||
#### NOTE: For ARM64 support, please use the separate ARM64 docker image: [`zedeus/nitter:latest-arm64`](https://hub.docker.com/r/zedeus/nitter/tags).
|
||||
|
||||
To run Nitter with Docker, you'll need to install and run Redis separately
|
||||
before you can run the container. See below for how to also run Redis using
|
||||
Docker.
|
||||
|
||||
To build and run Nitter in Docker:
|
||||
|
||||
```bash
|
||||
docker build -t nitter:latest .
|
||||
docker run -v $(pwd)/nitter.conf:/src/nitter.conf -d --network host nitter:latest
|
||||
```
|
||||
|
||||
Note: For ARM64, use this Dockerfile: [`Dockerfile.arm64`](https://github.com/zedeus/nitter/blob/master/Dockerfile.arm64).
|
||||
|
||||
A prebuilt Docker image is provided as well:
|
||||
|
||||
```bash
|
||||
docker run -v $(pwd)/nitter.conf:/src/nitter.conf -d --network host zedeus/nitter:latest
|
||||
```
|
||||
|
||||
Using docker-compose to run both Nitter and Redis as different containers:
|
||||
Change `redisHost` from `localhost` to `nitter-redis` in `nitter.conf`, then run:
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
Note the Docker commands expect a `nitter.conf` file in the directory you run
|
||||
them.
|
||||
|
||||
### systemd
|
||||
|
||||
To run Nitter via systemd you can use this service file:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Nitter (An alternative Twitter front-end)
|
||||
After=syslog.target
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
|
||||
# set user and group
|
||||
User=nitter
|
||||
Group=nitter
|
||||
|
||||
# configure location
|
||||
WorkingDirectory=/home/nitter/nitter
|
||||
ExecStart=/home/nitter/nitter/nitter
|
||||
|
||||
Restart=always
|
||||
RestartSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Then enable and run the service:
|
||||
`systemctl enable --now nitter.service`
|
||||
|
||||
### Logging
|
||||
|
||||
Nitter currently prints some errors to stdout, and there is no real logging
|
||||
implemented. If you're running Nitter with systemd, you can check stdout like
|
||||
this: `journalctl -u nitter.service` (add `--follow` to see just the last 15
|
||||
lines). If you're running the Docker image, you can do this:
|
||||
`docker logs --follow *nitter container id*`
|
||||
|
||||
## Contact
|
||||
|
||||
Feel free to join our [Matrix channel](https://matrix.to/#/#nitter:matrix.org).
|
||||
You can email me at zedeus@pm.me if you wish to contact me personally.
|
||||
A fork of the [libmedium](https://github.com/PrivacyDevel/nitter) project, with my personal changes.
|
||||
|
32
compose.example.yml
Normal file
32
compose.example.yml
Normal file
@ -0,0 +1,32 @@
|
||||
services:
|
||||
nitter:
|
||||
container_name: nitter
|
||||
image: git.ngn.tf/ngn/nitter
|
||||
ports:
|
||||
- 80:8080
|
||||
volumes:
|
||||
- ./nitter.conf:/srv/nitter.conf:Z,ro
|
||||
- ./accounts.jsonl:/srv/accounts.jsonl:Z,ro
|
||||
depends_on:
|
||||
- nitter-redis
|
||||
restart: unless-stopped
|
||||
user: 998:998
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- ALL
|
||||
read_only: true
|
||||
|
||||
nitter_redis:
|
||||
container_name: nitter_redis
|
||||
image: redis:6-alpine
|
||||
command: redis-server --save 60 1 --loglevel warning
|
||||
volumes:
|
||||
- ./data:/data
|
||||
restart: unless-stopped
|
||||
user: 999:1000
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- ALL
|
||||
read_only: true
|
@ -1,47 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
|
||||
nitter:
|
||||
image: ghcr.io/privacydevel/nitter:master
|
||||
container_name: nitter
|
||||
ports:
|
||||
- "127.0.0.1:8080:8080" # Replace with "8080:8080" if you don't use a reverse proxy
|
||||
volumes:
|
||||
- ./nitter.conf:/src/nitter.conf:Z,ro
|
||||
depends_on:
|
||||
- nitter-redis
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: wget -nv --tries=1 --spider http://127.0.0.1:8080/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
|
||||
|
||||
nitter-redis:
|
||||
image: redis:6-alpine
|
||||
container_name: nitter-redis
|
||||
command: redis-server --save 60 1 --loglevel warning
|
||||
volumes:
|
||||
- nitter-redis:/data
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: redis-cli ping
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 2
|
||||
user: "999:1000"
|
||||
read_only: true
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- ALL
|
||||
|
||||
volumes:
|
||||
nitter-redis:
|
@ -1,4 +1,4 @@
|
||||
[Server]
|
||||
[server]
|
||||
hostname = "nitter.net" # for generating links, change this to your own domain/ip
|
||||
title = "nitter"
|
||||
address = "0.0.0.0"
|
||||
@ -6,8 +6,9 @@ port = 8080
|
||||
https = false # disable to enable cookies when not using https
|
||||
httpMaxConnections = 100
|
||||
staticDir = "./public"
|
||||
accountsFile = "./accounts.jsonl"
|
||||
|
||||
[Cache]
|
||||
[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
|
||||
@ -19,7 +20,7 @@ redisMaxConnections = 30
|
||||
# goes above this, they're closed when released. don't worry about this unless
|
||||
# you receive tons of requests per second
|
||||
|
||||
[Config]
|
||||
[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
|
||||
@ -34,7 +35,7 @@ tokenCount = 10
|
||||
# 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]
|
||||
[preferences]
|
||||
theme = "Nitter"
|
||||
replaceTwitter = "nitter.net"
|
||||
replaceYouTube = "piped.video"
|
||||
|
BIN
screenshot.png
BIN
screenshot.png
Binary file not shown.
Before Width: | Height: | Size: 797 KiB |
32
twitter_oauth.sh → scripts/oauth.sh
Normal file → Executable file
32
twitter_oauth.sh → scripts/oauth.sh
Normal file → Executable file
@ -1,15 +1,16 @@
|
||||
#!/bin/bash
|
||||
# Grab oauth token for use with Nitter (requires Twitter account).
|
||||
#!/bin/bash -e
|
||||
|
||||
# Grab oauth token for use with Nitter (requires Twitter account).
|
||||
# results: {"oauth_token":"xxxxxxxxxx-xxxxxxxxx","oauth_token_secret":"xxxxxxxxxxxxxxxxxxxxx"}
|
||||
|
||||
username=""
|
||||
password=""
|
||||
|
||||
if [[ -z "$username" || -z "$password" ]]; then
|
||||
echo "needs username and password"
|
||||
if [ $# -ne 2 ]; then
|
||||
echo "please specify a username and password"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
username="${1}"
|
||||
password="${2}"
|
||||
|
||||
bearer_token='AAAAAAAAAAAAAAAAAAAAAFXzAwAAAAAAMHCxpeSDG1gLNLghVe8d74hl6k4%3DRUMF4xAQLsbeBhTSRrCiQpJtxoGWeyHrDb5te2jpGskWDFW82F'
|
||||
guest_token=$(curl -s -XPOST https://api.twitter.com/1.1/guest/activate.json -H "Authorization: Bearer ${bearer_token}" | jq -r '.guest_token')
|
||||
base_url='https://api.twitter.com/1.1/onboarding/task.json'
|
||||
@ -22,15 +23,30 @@ flow_1=$(curl -si -XPOST "${base_url}?flow_name=login" "${header[@]}")
|
||||
att=$(sed -En 's/^att: (.*)\r/\1/p' <<< "${flow_1}")
|
||||
flow_token=$(sed -n '$p' <<< "${flow_1}" | jq -r .flow_token)
|
||||
|
||||
if [[ -z "$flow_1" || -z "$flow_token" ]]; then
|
||||
echo "Couldn't retrieve flow token (twitter not reachable?)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# username
|
||||
token_2=$(curl -s -XPOST "${base_url}" -H "att: ${att}" "${header[@]}" \
|
||||
-d '{"flow_token":"'"${flow_token}"'","subtask_inputs":[{"subtask_id":"LoginEnterUserIdentifierSSO","settings_list":{"setting_responses":[{"key":"user_identifier","response_data":{"text_data":{"result":"'"${username}"'"}}}],"link":"next_link"}}]}' | jq -r .flow_token)
|
||||
|
||||
if [[ -z "$token_2" || "$token_2" == "null" ]]; then
|
||||
echo "Couldn't retrieve user token (check if login is correct)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# password
|
||||
token_3=$(curl -s -XPOST "${base_url}" -H "att: ${att}" "${header[@]}" \
|
||||
-d '{"flow_token":"'"${token_2}"'","subtask_inputs":[{"enter_password":{"password":"'"${password}"'","link":"next_link"},"subtask_id":"LoginEnterPassword"}]}' | jq -r .flow_token)
|
||||
|
||||
if [[ -z "$token_3" || "$token_3" == "null" ]]; then
|
||||
echo "Couldn't retrieve user token (check if password is correct)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# finally print oauth_token and secret
|
||||
curl -s -XPOST "${base_url}" -H "att: ${att}" "${header[@]}" \
|
||||
-d '{"flow_token":"'"${token_3}"'","subtask_inputs":[{"check_logged_in_account":{"link":"AccountDuplicationCheck_false"},"subtask_id":"AccountDuplicationCheck"}]}' | \
|
||||
jq -c '.subtasks[0]|if(.open_account) then {oauth_token: .open_account.oauth_token, oauth_token_secret: .open_account.oauth_token_secret} else empty end'
|
||||
jq -c '.subtasks[0]|if(.open_account) then [{oauth_token: .open_account.oauth_token, oauth_token_secret: .open_account.oauth_token_secret}] else empty end'
|
24
src/auth.nim
24
src/auth.nim
@ -185,22 +185,22 @@ proc setRateLimit*(account: GuestAccount; api: Api; remaining, reset: int) =
|
||||
|
||||
account.apis[api] = RateLimit(remaining: remaining, reset: reset)
|
||||
|
||||
proc initAccountPool*(cfg: Config; path: string) =
|
||||
proc initAccountPool*(cfg: Config) =
|
||||
let path = cfg.accountsFile
|
||||
enableLogging = cfg.enableDebug
|
||||
|
||||
let jsonlPath = if path.endsWith(".json"): (path & 'l') else: path
|
||||
|
||||
if fileExists(jsonlPath):
|
||||
log "Parsing JSONL guest accounts file: ", jsonlPath
|
||||
for line in jsonlPath.lines:
|
||||
accountPool.add parseGuestAccount(line)
|
||||
elif fileExists(path):
|
||||
log "Parsing JSON guest accounts file: ", path
|
||||
accountPool = parseGuestAccounts(path)
|
||||
else:
|
||||
echo "[accounts] ERROR: ", path, " not found. This file is required to authenticate API requests."
|
||||
if !path.endswith(".jsonl"):
|
||||
log "Accounts file should be formated with JSONL"
|
||||
quit 1
|
||||
|
||||
if !fileExists(path):
|
||||
log "Failed to access the accounts file (", path, ")"
|
||||
quit 1
|
||||
|
||||
log "Parsing JSONL accounts file: ", path
|
||||
for line in path.lines:
|
||||
accountPool.add parseGuestAccount(line)
|
||||
|
||||
let accountsPrePurge = accountPool.len
|
||||
#accountPool.keepItIf(not it.hasExpired)
|
||||
|
||||
|
@ -16,32 +16,33 @@ proc getConfig*(path: string): (Config, parseCfg.Config) =
|
||||
|
||||
let conf = Config(
|
||||
# Server
|
||||
address: cfg.get("Server", "address", "0.0.0.0"),
|
||||
port: cfg.get("Server", "port", 8080),
|
||||
useHttps: cfg.get("Server", "https", true),
|
||||
httpMaxConns: cfg.get("Server", "httpMaxConnections", 100),
|
||||
staticDir: cfg.get("Server", "staticDir", "./public"),
|
||||
title: cfg.get("Server", "title", "Nitter"),
|
||||
hostname: cfg.get("Server", "hostname", "nitter.net"),
|
||||
address: cfg.get("server", "address", "0.0.0.0"),
|
||||
port: cfg.get("server", "port", 8080),
|
||||
useHttps: cfg.get("server", "https", true),
|
||||
httpMaxConns: cfg.get("server", "httpMaxConnections", 100),
|
||||
staticDir: cfg.get("server", "staticDir", "./public"),
|
||||
accountsFile: cfg.get("server", "accountsFile", "./accounts.jsonl"),
|
||||
title: cfg.get("server", "title", "Nitter"),
|
||||
hostname: cfg.get("server", "hostname", "nitter.net"),
|
||||
|
||||
# Cache
|
||||
listCacheTime: cfg.get("Cache", "listMinutes", 120),
|
||||
rssCacheTime: cfg.get("Cache", "rssMinutes", 10),
|
||||
listCacheTime: cfg.get("cache", "listMinutes", 120),
|
||||
rssCacheTime: cfg.get("cache", "rssMinutes", 10),
|
||||
|
||||
redisHost: cfg.get("Cache", "redisHost", "localhost"),
|
||||
redisPort: cfg.get("Cache", "redisPort", 6379),
|
||||
redisConns: cfg.get("Cache", "redisConnections", 20),
|
||||
redisMaxConns: cfg.get("Cache", "redisMaxConnections", 30),
|
||||
redisPassword: cfg.get("Cache", "redisPassword", ""),
|
||||
redisHost: cfg.get("cache", "redisHost", "localhost"),
|
||||
redisPort: cfg.get("cache", "redisPort", 6379),
|
||||
redisConns: cfg.get("cache", "redisConnections", 20),
|
||||
redisMaxConns: cfg.get("cache", "redisMaxConnections", 30),
|
||||
redisPassword: cfg.get("cache", "redisPassword", ""),
|
||||
|
||||
# Config
|
||||
hmacKey: cfg.get("Config", "hmacKey", "secretkey"),
|
||||
base64Media: cfg.get("Config", "base64Media", false),
|
||||
minTokens: cfg.get("Config", "tokenCount", 10),
|
||||
enableRss: cfg.get("Config", "enableRSS", true),
|
||||
enableDebug: cfg.get("Config", "enableDebug", false),
|
||||
proxy: cfg.get("Config", "proxy", ""),
|
||||
proxyAuth: cfg.get("Config", "proxyAuth", "")
|
||||
hmacKey: cfg.get("config", "hmacKey", "secretkey"),
|
||||
base64Media: cfg.get("config", "base64Media", false),
|
||||
minTokens: cfg.get("config", "tokenCount", 10),
|
||||
enableRss: cfg.get("config", "enableRSS", true),
|
||||
enableDebug: cfg.get("config", "enableDebug", false),
|
||||
proxy: cfg.get("config", "proxy", ""),
|
||||
proxyAuth: cfg.get("config", "proxyAuth", "")
|
||||
)
|
||||
|
||||
return (conf, cfg)
|
||||
|
@ -16,10 +16,7 @@ import routes/[
|
||||
const instancesUrl = "https://github.com/zedeus/nitter/wiki/Instances"
|
||||
const issuesUrl = "https://github.com/zedeus/nitter/issues"
|
||||
|
||||
let
|
||||
accountsPath = getEnv("NITTER_ACCOUNTS_FILE", "./guest_accounts.json")
|
||||
|
||||
initAccountPool(cfg, accountsPath)
|
||||
initAccountPool(cfg)
|
||||
|
||||
if not cfg.enableDebug:
|
||||
# Silence Jester's query warning
|
||||
|
@ -265,6 +265,7 @@ type
|
||||
title*: string
|
||||
hostname*: string
|
||||
staticDir*: string
|
||||
accountsFile*: string
|
||||
|
||||
hmacKey*: string
|
||||
base64Media*: bool
|
||||
|
Loading…
x
Reference in New Issue
Block a user