Compare commits
2 commits
5a4af45700
...
1916ea0efe
Author | SHA1 | Date | |
---|---|---|---|
Gabriel Simmer | 1916ea0efe | ||
Gabriel Simmer | 30f6673c89 |
1528
Cargo.lock
generated
Normal file
1528
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
19
Cargo.toml
Normal file
19
Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "hn-rss"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
reqwest = "0.11"
|
||||
rss = "2.0"
|
||||
regex = "1.5"
|
||||
worker = "0.0.18"
|
||||
getrandom = { version = "0.2", features = ["js"] }
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
strip = true
|
||||
codegen-units = 1
|
183
flake.lock
Normal file
183
flake.lock
Normal file
|
@ -0,0 +1,183 @@
|
|||
{
|
||||
"nodes": {
|
||||
"crane": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"rust-overlay": "rust-overlay"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1692750383,
|
||||
"narHash": "sha256-n5P5HOXuu23UB1h9PuayldnRRVQuXJLpoO+xqtMO3ws=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "ef5d11e3c2e5b3924eb0309dba2e1fea2d9062ae",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1673956053,
|
||||
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1689068808,
|
||||
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1692799911,
|
||||
"narHash": "sha256-3eihraek4qL744EvQXsK1Ha6C3CR7nnT8X2qWap4RNk=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "f9e7cf818399d17d347f847525c5a5a8032e4e44",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1693060755,
|
||||
"narHash": "sha256-KNsbfqewEziFJEpPR0qvVz4rx0x6QXxw1CcunRhlFdk=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c66ccfa00c643751da2fd9290e096ceaa30493fc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"crane": "crane",
|
||||
"flake-utils": "flake-utils_2",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"rust-overlay": "rust-overlay_2"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"crane",
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"crane",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1691374719,
|
||||
"narHash": "sha256-HCodqnx1Mi2vN4f3hjRPc7+lSQy18vRn8xWW68GeQOg=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "b520a3889b24aaf909e287d19d406862ced9ffc9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"rust-overlay_2": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1693102271,
|
||||
"narHash": "sha256-JuxJYl7zZ9FUOA/3Az5OPYWQfH9Y8SvtqqFnPKB6zUw=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "1aac4029cfbc529f8b39c96d29fe1d09338f9110",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
86
flake.nix
Normal file
86
flake.nix
Normal file
|
@ -0,0 +1,86 @@
|
|||
{
|
||||
description = "Build a cargo project";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||
|
||||
crane = {
|
||||
url = "github:ipetkov/crane";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
|
||||
rust-overlay = {
|
||||
url = "github:oxalica/rust-overlay";
|
||||
inputs = {
|
||||
nixpkgs.follows = "nixpkgs";
|
||||
flake-utils.follows = "flake-utils";
|
||||
};
|
||||
};
|
||||
};
|
||||
outputs = { self, nixpkgs, crane, flake-utils, rust-overlay, ... }:
|
||||
flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [ (import rust-overlay) ];
|
||||
};
|
||||
|
||||
rustWithWasiTarget = pkgs.rust-bin.stable.latest.default.override {
|
||||
targets = [ "wasm32-wasi" "wasm32-unknown-unknown" ];
|
||||
};
|
||||
|
||||
# NB: we don't need to overlay our custom toolchain for the *entire*
|
||||
# pkgs (which would require rebuidling anything else which uses rust).
|
||||
# Instead, we just want to update the scope that crane will use by appending
|
||||
# our specific toolchain there.
|
||||
craneLib = (crane.mkLib pkgs).overrideToolchain rustWithWasiTarget;
|
||||
|
||||
my-crate = craneLib.buildPackage {
|
||||
src = craneLib.cleanCargoSource (craneLib.path ./.);
|
||||
|
||||
cargoExtraArgs = "--target wasm32-unknown-unknown";
|
||||
|
||||
# Tests currently need to be run via `cargo wasi` which
|
||||
# isn't packaged in nixpkgs yet...
|
||||
doCheck = false;
|
||||
|
||||
buildInputs = with pkgs; [
|
||||
# Add additional build inputs here
|
||||
openssl
|
||||
pkg-config
|
||||
] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [
|
||||
# Additional darwin specific inputs can be set here
|
||||
pkgs.libiconv
|
||||
];
|
||||
};
|
||||
in
|
||||
{
|
||||
checks = {
|
||||
inherit my-crate;
|
||||
};
|
||||
|
||||
packages.default = my-crate;
|
||||
|
||||
apps.default = flake-utils.lib.mkApp {
|
||||
drv = pkgs.writeShellScriptBin "my-app" ''
|
||||
${pkgs.wasmtime}/bin/wasmtime run ${my-crate}/bin/custom-toolchain.wasm
|
||||
'';
|
||||
};
|
||||
|
||||
devShells.default = pkgs.mkShell {
|
||||
inputsFrom = builtins.attrValues self.checks.${system};
|
||||
# Extra inputs can be added here
|
||||
nativeBuildInputs = with pkgs; [
|
||||
rustWithWasiTarget
|
||||
rust-analyzer
|
||||
cargo
|
||||
rustup
|
||||
rustc
|
||||
nodePackages_latest.wrangler
|
||||
worker-build
|
||||
];
|
||||
};
|
||||
});
|
||||
}
|
82
src/lib.rs
Normal file
82
src/lib.rs
Normal file
|
@ -0,0 +1,82 @@
|
|||
use reqwest::{Error as ReqwestError, StatusCode};
|
||||
use rss::{Channel, Error as RssError};
|
||||
use regex::Regex;
|
||||
use std::io::Cursor;
|
||||
|
||||
use worker::{Request, Env, Response, Router, event, Headers};
|
||||
|
||||
#[derive(Debug)]
|
||||
enum CustomError {
|
||||
Reqwest(ReqwestError),
|
||||
Rss(RssError),
|
||||
}
|
||||
|
||||
impl From<ReqwestError> for CustomError {
|
||||
fn from(error: ReqwestError) -> Self {
|
||||
CustomError::Reqwest(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RssError> for CustomError {
|
||||
fn from(error: RssError) -> Self {
|
||||
CustomError::Rss(error)
|
||||
}
|
||||
}
|
||||
|
||||
#[event(fetch)]
|
||||
pub async fn main(req: Request, env: Env, _ctx: worker::Context) -> worker::Result<Response>{
|
||||
let router = Router::new();
|
||||
router
|
||||
.get_async("/", |_, ctx| async move {
|
||||
let rss = match fetch_modified_rss().await {
|
||||
Ok(r) => r,
|
||||
Err(e) => "".to_owned(),
|
||||
};
|
||||
|
||||
let res = Response::from_bytes(rss.into()).unwrap();
|
||||
let mut headers = Headers::new();
|
||||
headers.set("content-type", "application/rss+xml");
|
||||
|
||||
Ok(res.with_headers(headers))
|
||||
}).run(req, env).await
|
||||
}
|
||||
|
||||
async fn fetch_modified_rss() -> Result<String, CustomError> {
|
||||
let url = "https://news.ycombinator.com/rss";
|
||||
|
||||
let resp = reqwest::get(url).await?;
|
||||
let body = resp.text().await?;
|
||||
|
||||
let cursor = Cursor::new(body);
|
||||
let channel = match Channel::read_from(cursor) {
|
||||
Ok(channel) => channel,
|
||||
Err(RssError::InvalidStartTag) => {
|
||||
eprintln!("Invalid start tag found in the feed. Please check the feed URL or try again later.");
|
||||
return Ok(String::new());
|
||||
},
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
|
||||
let items = channel.into_items();
|
||||
|
||||
let updated_items = items
|
||||
.iter()
|
||||
.map(|item| {
|
||||
let mut new_item = item.clone();
|
||||
let description = item.description().unwrap_or_default();
|
||||
let new_description = remove_comment_link(description);
|
||||
new_item.set_description(new_description);
|
||||
new_item
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut modified_rss = Channel::default();
|
||||
modified_rss.set_items(updated_items);
|
||||
|
||||
Ok(modified_rss.to_string())
|
||||
}
|
||||
|
||||
fn remove_comment_link(description: &str) -> String {
|
||||
let re = Regex::new(r"(?i)<a[^>]*>comments</a>").unwrap();
|
||||
re.replace(description, "").to_string()
|
||||
}
|
19
wrangler.toml
Normal file
19
wrangler.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
name = "hn-rss"
|
||||
type = "javascript"
|
||||
workers_dev = true
|
||||
compatibility_date = "2022-01-20"
|
||||
|
||||
[vars]
|
||||
WORKERS_RS_VERSION = "0.0.18"
|
||||
|
||||
[build]
|
||||
command = "cargo install -q worker-build && worker-build --release" # required
|
||||
|
||||
[build.upload]
|
||||
dir = "build/worker"
|
||||
format = "modules"
|
||||
main = "./shim.mjs"
|
||||
|
||||
[[build.upload.rules]]
|
||||
globs = ["**/*.wasm"]
|
||||
type = "CompiledWasm"
|
Loading…
Reference in a new issue