From f8a1e6f79c5d286f559b7f4ac85be15e18504c55 Mon Sep 17 00:00:00 2001 From: ngn Date: Mon, 20 Jan 2025 04:31:15 +0300 Subject: [PATCH] general cleanup Signed-off-by: ngn --- Dockerfile | 9 +++- Makefile | 38 ++++------------- README.md | 88 ++-------------------------------------- config.toml | 7 ++++ config/default.toml | 15 ------- libmedium.user.js | 70 -------------------------------- renovate.json | 13 ++---- scripts/coverage.sh | 88 ---------------------------------------- src/main.rs | 6 +-- src/proxy.rs | 2 +- src/settings.rs | 26 ++++-------- templates/index.html | 66 +++++++++--------------------- templates/main.css | 55 ++++++++++++++++++------- templates/post.html | 10 ++--- templates/post_meta.html | 4 +- 15 files changed, 108 insertions(+), 389 deletions(-) create mode 100644 config.toml delete mode 100644 config/default.toml delete mode 100644 libmedium.user.js delete mode 100755 scripts/coverage.sh diff --git a/Dockerfile b/Dockerfile index 01c662b..e46ac86 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,18 +1,25 @@ FROM rust:slim as rust + WORKDIR /src RUN apt-get update && apt-get install -y git pkg-config libssl-dev RUN mkdir src && echo "fn main() {}" > src/main.rs + COPY Cargo.toml . -RUN sed -i '/.*build.rs.*/d' Cargo.toml COPY Cargo.lock . + +RUN sed -i '/.*build.rs.*/d' Cargo.toml RUN cargo build --release + COPY . /src RUN cargo build --release FROM debian:bookworm-slim + RUN useradd -ms /bin/bash -u 1001 libmedium RUN apt-get update && apt-get install -y ca-certificates RUN mkdir /var/lib/libmedium && chown libmedium /var/lib/libmedium + COPY --from=rust /src/target/release/libmedium /usr/local/bin/ + USER libmedium ENTRYPOINT ["/usr/local/bin/libmedium"] diff --git a/Makefile b/Makefile index 29906ac..ab36ef2 100644 --- a/Makefile +++ b/Makefile @@ -1,42 +1,20 @@ -default: ## Debug build +all: cargo build -clean: ## Clean all build artifacts and dependencies - @cargo clean +clean: + cargo clean -check: ## Check for syntax errors on all workspaces +check: cargo check --workspace --tests --all-features - #cd utils/cache-bust && cargo check --tests --all-features -coverage: ## Generate HTML code coverage - ./scripts/coverage.sh --coverage - - -dev-env: ## Download development dependencies - cargo fetch - -doc: ## Prepare documentation - cargo doc --no-deps --workspace --all-features - -docker: ## Build docker images - docker build -t realaravinth/libmedium:master -t realaravinth/libmedium:latest . - -docker-publish: docker ## Build and publish docker images - docker push realaravinth/libmedium:master - docker push realaravinth/libmedium:latest - -lint: ## Lint codebase +lint: cargo fmt -v --all -- --emit files cargo clippy --workspace --tests --all-features -release: ## Release build - cargo build --release - -run: default ## Run debug build +run: cargo run -test: ## Run tests +test: cargo test --all-features --no-fail-fast -help: ## Prints help for targets with comments - @cat $(MAKEFILE_LIST) | grep -E '^[a-zA-Z_-]+:.*?## .*$$' | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' +.PHONY: clean check lint run test diff --git a/README.md b/README.md index 8b6d34a..88144e3 100644 --- a/README.md +++ b/README.md @@ -1,87 +1,5 @@ -
-

LibMedium

-

+# [ngn.tf] | libmedium -**Privacy-focused proxy for medium.com** +![](https://git.ngn.tf/ngn/libmedium/actions/workflows/build.yml/badge.svg) -

- -[![Awesome Humane Tech](https://raw.githubusercontent.com/humanetech-community/awesome-humane-tech/main/humane-tech-badge.svg?sanitize=true)](https://github.com/humanetech-community/awesome-humane-tech) -[![status-badge](https://ci.batsense.net/api/badges/realaravinth/libmedium/status.svg)](https://ci.batsense.net/realaravinth/libmedium) -[![codecov](https://codecov.io/gh/realaravinth/libmedium/branch/master/graph/badge.svg)](https://codecov.io/gh/realaravinth/libmedium) - -
- -## Status - -Usable. Should you run into a `HTTP 500 Internal Server Error`, please -file a bug report with the URL of the post you were trying to read and -the git commit hash of the build. Git commit hash can be obtained from -[/api/v1/meta/build](https://libmedium.batsense.net/api/v1/meta/build). - -This proxy works by interacting with Medium's undocumented(probably -private but unauthenticated) API. So I've had to make assumptions and -tweak API schematics as I run into errors. - -## Features - -- [x] proxy images -- [x] proxy GitHub gists -- [x] render posts -- [x] syntax highlighting for gists -- [ ] user pages(WIP) -- [ ] RSS feeds - -## Why? - -Knowledge is the true wealth of humanity. If it weren't for our -ancestors, who chose to pass down their knowledge and experiences, we -would still be a primitive species. Whatever advancement that we as -a species have achieved is because we chose to share information. - -To put a paywall on knowledge like that is both obscene and goes against -the very nature of humanity. - -It is possible to run a sustainable publication business while still -respecting freedom. [LWN.net](https://lwn.net) is one of my favourite -publications that has been around forever. So it is possible. I hope -medium.com comes up with other, non-harmful ways to run a sustainable -business. - -## Instances - -| Instance | Country | Provider | Host | -| ------------------------------------------------------------------------- | ------- | ---------- | -------------------------------------- | -| https://libmedium.batsense.net | India | Airtel | @realaravinth | -| https://md.vern.cc | US | Hetzner | [~vern](https://vern.cc) | -| http://md.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion/ | N/A | Hetzner | [~vern](https://vern.cc) | -| http://vernaqj2qr2pijpgvf3od6ssc3ulz3nv52gwr3hba5l6humuzmgq.b32.i2p/ | N/A | Hetzner | [~vern](https://vern.cc) | -| https://medium.hostux.net | France | Gandi | [hostux](https://hostux.net) | -| https://r.sudovanilla.org | US | Selfhosted | [SudoVanilla](https://sudovanilla.org) | -| https://libmedium.ducks.party | DE | Datalix | [ducks.party](https://ducks.party) | -## Deploy - -1. Grab [`./config/default.toml`](./config/default.toml) and make - necessary changes - -2. AMD64 pre-compiled images are available on DockerHub. - -``` -docker run -d \ - -v ./config/default.toml:/etc/libmedium/config.toml \ - -p 8082:7000 \ - --restart always \ - --name libmedium \ - realaravinth/libmedium -``` - -If you are on a different architecture, run make docker and then run the -above command. - -``` -make docker -``` - ---- - -Inspired by [Scribe - An Alternative Medium Frontend](https://sr.ht/~edwardloveall/scribe) +A fork of the [libmedium](https://github.com/realaravinth/libmedium) project, with my personal changes. diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..9d39b27 --- /dev/null +++ b/config.toml @@ -0,0 +1,7 @@ +debug = true +#cache = "/var/lib/libmedium" +port = 7000 +ip= "0.0.0.0" +domain = "example.com" +proxy_has_tls = false +#workers = 2 diff --git a/config/default.toml b/config/default.toml deleted file mode 100644 index 70d3797..0000000 --- a/config/default.toml +++ /dev/null @@ -1,15 +0,0 @@ -debug = true -source_code = "https://git.batsense.net/realaravinth/libmedium" -#cache = "/var/lib/libmedium" - -[server] -# The port at which you want authentication to listen to -# takes a number, choose from 1000-10000 if you dont know what you are doing -port = 7000 -#IP address. Enter 0.0.0.0 to listen on all availale addresses -ip= "0.0.0.0" -# enter your hostname, eg: example.com -domain = "localhost" -allow_registration = true -proxy_has_tls = false -#workers = 2 diff --git a/libmedium.user.js b/libmedium.user.js deleted file mode 100644 index 71b09d4..0000000 --- a/libmedium.user.js +++ /dev/null @@ -1,70 +0,0 @@ -// ==UserScript== -// @name LibMedium proxy -// @version 0.1.1 -// @description Re-writes medium.com URLs in point to libmedium -// @author Aravinth Manivannan -// @match https://*/* -// @match http://*/* -// @grant AGPLv3 or above -// ==/UserScript== - -// websites to be proxied -const blacklist = [ - "medium.com", - "blog.discord.com", - "uxdesign.cc", - "towardsdatascience.com", - "hackernoon.com", - "medium.freecodecamp.org", - "psiloveyou.xyz", - "betterhumans.coach.me", - "codeburst.io", - "theascent.pub", - "medium.mybridge.co", - "uxdesign.cc", - "levelup.gitconnected.com", - "itnext.io", - "entrepreneurshandbook.co", - "proandroiddev.com", - "blog.prototypr.io", - "thebolditalic.com", - "blog.usejournal.com", -]; - -// Location of the proxy -const libmediumHost = new URL("https://libmedium.batsense.net"); - -const isMedium = (url) => { - url = new URL(url); - - if (blacklist.find((bl) => url.host.includes(bl))) { - return true; - } - - let componenets = url.host.split("."); - let len = componenets.length; - if ( - len > 1 && - componenets[len - 1] == "com" && - componenets[len - 2] == "medium" - ) { - return true; - } -}; - -(function () { - "use strict"; - - if (!window.location.href.includes(libmediumHost.host)) { - let urls = document.links; - for (let i = 0; i < urls.length; i++) { - if (isMedium(urls[i])) { - let url = urls[i]; - let path = url.pathname.split("-"); - urls[i].pathname = `/utils/post/${path[path.length - 1]}`; - urls[i].host = libmediumHost.host; - urls[i].search = ""; - } - } - } -})(); diff --git a/renovate.json b/renovate.json index 8d9a86c..604175e 100644 --- a/renovate.json +++ b/renovate.json @@ -1,12 +1,5 @@ { - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": ["config:recommended", ":dependencyDashboard"], - "labels": ["renovate-bot"], - "prHourlyLimit": 0, - "timezone": "Asia/kolkata", - "prCreation": "immediate", - "vulnerabilityAlerts": { - "enabled": true, - "labels": ["renovate-bot", "renovate-security", "security"] - } + "extends": ["config:recommended"], + "timezone": "Europe/Istanbul", + "prHourlyLimit": 20 } diff --git a/scripts/coverage.sh b/scripts/coverage.sh deleted file mode 100755 index bea11e6..0000000 --- a/scripts/coverage.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/bin/bash -readonly GRCOV_DOWNLOAD="https://github.com/mozilla/grcov/releases/download/v0.8.2/grcov-linux-x86_64.tar.bz2" -readonly TMP_DIR=$(pwd)/tmp -readonly PROJECT_ROOT=$(pwd) -readonly GRCOV_TARBAL="$TMP_DIR/grcov.tar.bz2" -readonly GRCOV="$TMP_DIR/grcov" - -clean_up() { - cd $PROJECT_ROOT - /bin/rm default.profraw lcov.info *.profraw || true - cd target - /bin/rm default.profraw lcov.info *.profraw || true - cargo clean -} - -check_arg(){ - if [ -z $1 ] - then - help - exit 1 - fi -} - -match_arg() { - if [ $1 == $2 ] || [ $1 == $3 ] - then - return 0 - else - return 1 - fi -} - - -download() { - if [ ! -e $GRCOV ]; - then - echo "[*] Downloading grcov" - wget --quiet --output-doc=$GRCOV_TARBAL $GRCOV_DOWNLOAD; - cd $TMP_DIR - tar -xf $GRCOV_TARBAL; - cd $PROJECT_ROOT - fi -} - -build_and_test() { - export RUSTFLAGS="-Zinstrument-coverage" - cd $PROJECT_ROOT - - echo "[*] Building project" - cargo build - - export LLVM_PROFILE_FILE="target/libmedium-%p-%m.profraw" - - echo "[*] Running tests" - cargo test - - echo "[*] Generating coverage" - $GRCOV target/ --binary-path \ - ./target/debug/ \ - -s . -t lcov --branch \ - --ignore-not-existing \ - --ignore "../*" -o target/lcov.info - - $GRCOV target/ --binary-path \ - ./target/debug/ \ - -s . -t html --branch \ - --ignore-not-existing \ - --ignore "../*" -o target/coverage.html - -} - -run_coverage() { - cd $PROJECT_ROOT - mkdir $TMP_DIR || true - clean_up - download - build_and_test -} - -check_arg $1 - -if match_arg $1 'c' '--coverage' -then - run_coverage -else - echo "undefined option" - exit 1 -fi diff --git a/src/main.rs b/src/main.rs index b282197..e899e9f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -60,7 +60,7 @@ async fn main() -> std::io::Result<()> { PKG_NAME, PKG_DESCRIPTION, PKG_HOMEPAGE, VERSION, GIT_COMMIT_HASH ); - println!("Starting server on: http://{}", SETTINGS.server.get_ip()); + println!("Starting server on: http://{}", SETTINGS.get_ip()); let data = Data::new(); @@ -79,8 +79,8 @@ async fn main() -> std::io::Result<()> { .app_data(data.clone()) .configure(routes::services) }) - .workers(SETTINGS.server.workers.unwrap_or_else(num_cpus::get)) - .bind(SETTINGS.server.get_ip()) + .workers(SETTINGS.workers.unwrap_or_else(num_cpus::get)) + .bind(SETTINGS.get_ip()) .unwrap() .run() .await diff --git a/src/proxy.rs b/src/proxy.rs index 310039b..c7480e8 100644 --- a/src/proxy.rs +++ b/src/proxy.rs @@ -133,7 +133,7 @@ const INDEX: &str = include_str!("../templates/index.html"); async fn index() -> impl Responder { HttpResponse::Ok() .content_type("text/html; charset=utf-8") - .body(INDEX.replace("SOURCE_CODE_REPLACE", &crate::SETTINGS.source_code)) + .body(INDEX) } #[actix_web_codegen_const_routes::get(path = "crate::V1_API_ROUTES.proxy.asset")] diff --git a/src/settings.rs b/src/settings.rs index 3ffe7bb..5fef6b4 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -24,7 +24,9 @@ use serde::Deserialize; use url::Url; #[derive(Debug, Clone, Deserialize)] -pub struct Server { +pub struct Settings { + pub debug: bool, + pub cache: Option, pub port: u32, pub domain: String, pub ip: String, @@ -32,28 +34,13 @@ pub struct Server { pub workers: Option, } -impl Server { - #[cfg(not(tarpaulin_include))] - pub fn get_ip(&self) -> String { - format!("{}:{}", self.ip, self.port) - } -} - -#[derive(Debug, Clone, Deserialize)] -pub struct Settings { - pub debug: bool, - pub cache: Option, - pub server: Server, - pub source_code: String, -} - #[cfg(not(tarpaulin_include))] impl Settings { pub fn new() -> Result { let mut s = Config::builder(); // setting default values - const CURRENT_DIR: &str = "./config/default.toml"; + const CURRENT_DIR: &str = "./config.toml"; const ETC: &str = "/etc/libmedium/config.toml"; if let Ok(path) = env::var("LIBMEDIUM") { @@ -105,4 +92,9 @@ impl Settings { fn check_url(&self) { Url::parse(&self.source_code).expect("Please enter a URL for source_code in settings"); } + + #[cfg(not(tarpaulin_include))] + pub fn get_ip(&self) -> String { + format!("{}:{}", self.ip, self.port) + } } diff --git a/templates/index.html b/templates/index.html index f63268f..59d1dac 100644 --- a/templates/index.html +++ b/templates/index.html @@ -6,59 +6,31 @@ LibMedium -
+

LibMedium

A free and privacy-respecting medium proxy

-

- Demo Article - | Source Code -

+
diff --git a/templates/main.css b/templates/main.css index c3a2497..0ee89b2 100644 --- a/templates/main.css +++ b/templates/main.css @@ -3,21 +3,48 @@ padding: 0; } - body { width: 100%; - display: flex; + min-height: 100vh; + display: block; + background: #000; } -main { +.index { + display: flex; + flex-direction: column; + align-items: center; + width: 80%; + height: 100vh; + margin: auto; + justify-content: space-between; +} + +.index .center { + margin: auto; + display: flex; + flex-direction: column; + align-items: center; +} + +.index .center h1 { + font-size: 3rem; +} + +@media screen and (max-width: 1200px) { + .index { + width: 90%; + } +} + +.post { width: 35em; margin: auto; display: flex; flex-direction: column; + margin-top: 20px; } - - h1, h2, h3, @@ -25,27 +52,25 @@ h4, h5, h6 { font-family: sohne, "Helvetica Neue", Helvetica, Arial, sans-serif !important; + font-weight: 900; } a { - color: rgb(0, 86, 179); + color: #02eded; text-decoration: none; } -a:visited { - color: rgb(0, 86, 179); -} - a:hover { text-decoration: underline; } html { - color: #333; + color: #fff; font-family: charter, Georgia, Cambria, "Times New Roman", Times, serif; font-size: 26px; line-height: 1.55rem; } + p { margin: 20px 0; } @@ -83,11 +108,10 @@ pre { line-height: 1rem; padding: 20px; border-radius: 6px; - background-color: rgba(175, 184, 193, 0.2); + background: #101010; } - -.code-block { +post.code-block { display: block; margin: 5px 0; padding: 20px; @@ -105,7 +129,8 @@ iframe { font-size: 16px; line-height: 1.5rem; } - main { + + .post { width: 90%; } diff --git a/templates/post.html b/templates/post.html index ae2a498..89e5715 100644 --- a/templates/post.html +++ b/templates/post.html @@ -5,11 +5,11 @@ <. let mut open_list = false ; .> -
+

<.= data.title .>

- <.= data.creator.name .> on <.= &date .> · <.= reading_time .> min read ·  - Open post in medium.com

@@ -27,7 +27,7 @@ <.- p .> <.}.> -
+