poit-puller (0.1.0)
Installation
[registries.forgejo]
index = "sparse+ " # Sparse index
# index = " " # Git
[net]
git-fetch-with-cli = truecargo add poit-puller@0.1.0 --registry forgejoAbout this package
POIT Puller
A Rust client for listing and fetching Kallelser from Post- och Inrikes Tidningar (POIT).
Status
The client can:
- list publications with
amnesomradeId=1for a date range; - fetch an individual publication by
kungorelseid; - decode POIT's version 5 response format into JSON.
Persistence and scheduled polling still need to be implemented.
Requirements
- A recent stable Rust toolchain
Install Rust with rustup if needed.
Library usage
use poit_puller::{PoitClient, Result};
async fn fetch() -> Result<()> {
let client = PoitClient::new()?;
let listings = client
.list_kallelser("2026-09-14", "2026-09-14")
.await?;
let notice = client.fetch_announcement(&listings[0].kungorelseid).await?;
println!("{notice:#}");
Ok(())
}
PDF support
Enable the optional pdf feature to convert kungorelseText to PDF:
let pdf: Vec<u8> = client.fetch_announcement_pdf("K621433/26").await?;
std::fs::write("K621433-26.pdf", pdf)?;
The targeted renderer supports the HTML elements emitted by POIT: paragraphs, bold text, line breaks, and ordered or unordered lists. It uses built-in PDF fonts and an all-Rust dependency stack—no browser, wkhtmltopdf, system font, or native library is required.
Examples
List Kallelser for one day or a date range:
cargo run --example list -- 2026-09-14
cargo run --example list -- 2026-09-14 2026-09-16
Fetch and decode an individual publication:
cargo run --example fetch -- 'K621433/26'
The examples write pretty-printed JSON to standard output. Generate a PDF with:
cargo run --features pdf --example pdf -- 'K621433/26' output.pdf
How individual publications are decoded
The client follows the current POIT web application:
- Request a coupling token from
HamtaKopplingusing the same HTTP session. - Request
HamtaKungorelsewith the publication ID, coupling token, andversion=5. - Reverse POIT's letter-case and digit transformation.
- Base64-decode the response.
- Derive a 32-byte state from
SHA-256(kungorelseid + koppling). - Apply POIT's mutable XOR routine and parse the resulting JSON.
Coupling token
HamtaKoppling returns a short-lived token that links a detail request to the current HTTP session. POIT also uses it when encoding the response: the decoder key state is derived from SHA-256(kungorelseid + koppling). The token and cookies must therefore be fetched dynamically and reused by the same client.
The client sends browser-like request headers because POIT otherwise returns its security challenge instead of API data.
Development
cargo fmt --check
cargo test
cargo clippy --all-targets --all-features
Dependencies
tokiofor the asynchronous runtimereqwestfor HTTP requests and in-memory session cookiesserdeandserde_jsonfor POIT responsesbase64andsha2for publication decoding- Optional
printpdfandhtml-escapefor pure-Rust PDF output
Dependencies
| ID | Version |
|---|---|
| base64 | ^0.23.1 |
| html-escape | ^0.2.15 |
| printpdf | ^0.12.8 |
| reqwest | ^0.13.5 |
| serde | ^1.0.229 |
| serde_json | ^1.0.151 |
| sha2 | ^0.11.0 |
| tokio | ^1.53.1 |