Skip to content

Commit

Permalink
Add RSS feed (#1229)
Browse files Browse the repository at this point in the history
  • Loading branch information
casey authored Jan 18, 2023
1 parent a404a5c commit 690ed24
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 4 deletions.
125 changes: 121 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ miniscript = "9.0.0"
ord-bitcoincore-rpc = { git = "https://github.com/casey/rust-bitcoincore-rpc", branch = "ord" }
redb = "0.11.0"
regex = "1.6.0"
rss = "2.0.1"
rust-embed = "6.4.0"
rustls = "0.20.6"
rustls-acme = { version = "0.5.0", features = ["axum"] }
Expand Down
14 changes: 14 additions & 0 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,20 @@ impl Index {
)
}

pub(crate) fn get_feed_inscriptions(&self, n: usize) -> Result<Vec<(u64, InscriptionId)>> {
Ok(
self
.database
.begin_read()?
.open_table(INSCRIPTION_NUMBER_TO_INSCRIPTION_ID)?
.iter()?
.rev()
.take(n)
.map(|(number, id)| (number.value(), Entry::load(*id.value())))
.collect(),
)
}

pub(crate) fn get_inscription_entry(
&self,
inscription_id: InscriptionId,
Expand Down
62 changes: 62 additions & 0 deletions src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ impl Server {
.route("/faq", get(Self::faq))
.route("/favicon.ico", get(Self::favicon_ico))
.route("/favicon.svg", get(Self::favicon_svg))
.route("/feed.xml", get(Self::feed))
.route("/input/:block/:transaction/:input", get(Self::input))
.route("/inscription/:inscription_id", get(Self::inscription))
.route("/inscriptions", get(Self::inscriptions))
Expand Down Expand Up @@ -568,6 +569,47 @@ impl Server {
)
}

async fn feed(
Extension(chain): Extension<Chain>,
Extension(index): Extension<Arc<Index>>,
) -> ServerResult<Response> {
let mut builder = rss::ChannelBuilder::default();

match chain {
Chain::Mainnet => builder.title("Inscriptions"),
_ => builder.title(format!("Inscriptions – {chain:?}")),
};

builder.generator(Some("ord".to_string()));

for (number, id) in index.get_feed_inscriptions(100)? {
builder.item(
rss::ItemBuilder::default()
.title(format!("Inscription {number}"))
.link(format!("/inscription/{id}"))
.guid(Some(rss::Guid {
value: format!("/inscription/{id}"),
permalink: true,
}))
.build(),
);
}

Ok(
(
[
(header::CONTENT_TYPE, "application/rss+xml"),
(
header::CONTENT_SECURITY_POLICY,
"default-src 'unsafe-inline'",
),
],
builder.build().to_string(),
)
.into_response(),
)
}

async fn static_asset(Path(path): Path<String>) -> ServerResult<Response> {
let content = StaticAssets::get(if let Some(stripped) = path.strip_prefix('/') {
stripped
Expand Down Expand Up @@ -1990,4 +2032,24 @@ mod tests {
"max-age=31536000; includeSubDomains; preload",
);
}

#[test]
fn feed() {
let server = TestServer::new_with_sat_index();
server.mine_blocks(1);

server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate {
inputs: &[(1, 0, 0)],
witness: inscription("text/foo", "hello").to_witness(),
..Default::default()
});

server.mine_blocks(1);

server.assert_response_regex(
"/feed.xml",
StatusCode::OK,
".*<title>Inscription 0</title>.*",
);
}
}
1 change: 1 addition & 0 deletions src/templates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ mod tests {
<meta name=format-detection content='telephone=no'>
<meta name=viewport content='width=device-width,initial-scale=1.0'>
<title>Foo</title>
<link rel=alternate href=/feed.xml type=application/rss\+xml title='Inscription RSS Feed'>
<link rel=icon type=image/svg\+xml href=/favicon.svg>
<link rel=icon type=image/png href=/favicon.ico>
<link rel=stylesheet href=/static/index.css>
Expand Down
1 change: 1 addition & 0 deletions templates/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<meta property=og:image content='{{ url }}'>
%% }
<title>{{ self.content.title() }}</title>
<link rel=alternate href=/feed.xml type=application/rss+xml title='Inscription RSS Feed'>
<link rel=icon type=image/svg+xml href=/favicon.svg>
<link rel=icon type=image/png href=/favicon.ico>
<link rel=stylesheet href=/static/index.css>
Expand Down

0 comments on commit 690ed24

Please sign in to comment.