From a6258c0c45f7c5d08ff77d4bcf9d747a24199a15 Mon Sep 17 00:00:00 2001 From: Kris Yotam Date: Thu, 12 Mar 2026 21:23:22 -0500 Subject: [PATCH] update sbot --- CLAUDE.md => .claude/CLAUDE.md | 26 ++- .gitignore | 2 +- Makefile | 18 +- README.md | 229 ++++++++++++++++++ archiver.c | 72 +++++- config.h | 6 +- detect.c | 411 +++++++++++++++++++++++++++++++++ detect.h | 42 ++++ robots.c | 4 +- 9 files changed, 780 insertions(+), 30 deletions(-) rename CLAUDE.md => .claude/CLAUDE.md (82%) create mode 100644 README.md create mode 100644 detect.c create mode 100644 detect.h diff --git a/CLAUDE.md b/.claude/CLAUDE.md similarity index 82% rename from CLAUDE.md rename to .claude/CLAUDE.md index c2bef6d26b4a539677ed19790253616cf7d7d27f..c4b20db716d33e40369991ff2b41dbf3d0e99816 100644 --- a/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -1,11 +1,12 @@ -# archiver-bot — CLAUDE.md +# sbot — CLAUDE.md ## Project -archiver-bot is a suckless web archiver written in C. It creates -self-contained archives of websites with all resources (CSS, images, -fonts) inlined as data URIs. Supports single-page and recursive -whole-site archival with GWTAR (Gwern Web Tar Archive) format headers. +sbot (Simple Archiver Bot) is a suckless web archiver written in C. It +creates self-contained archives of websites with all resources (CSS, +images, fonts) inlined as data URIs. Supports single-page archival in +GWTAR (Gwern Web Tar Archive) format and recursive whole-site archival +with navigable directory structure. ## Coding Standards — Suckless C Style @@ -41,7 +42,7 @@ All code in this project MUST follow the suckless.org coding style: static void usage(void) { - fprintf(stderr, "usage: archiver-bot [-v] [-r] url\n"); + fprintf(stderr, "usage: sbot [-v] [-r] url\n"); exit(1); } ``` @@ -96,6 +97,8 @@ usage(void) | Crawler | `queue_`, `visited_` | crawl.c | URL queue (BFS), visited set, URL normalization, path conversion | | Fetcher | `fetch_` | fetch.c | HTTP fetching via libcurl, response management | | Parser | `reslist_`, `parse_` | parse.c | HTML parsing, resource extraction, image inlining | +| Robots | `robots_` | robots.c | robots.txt fetching, parsing, and rule matching | +| Detect | `detect_`, `siteinfo_` | detect.c | CMS/framework detection (WordPress, Blogger, Hugo, Jekyll, Ghost, Drupal, MediaWiki) | | Utilities | `die`, `warn`, `x*`, `str_*`, `url_*` | util.c | Memory wrappers, string ops, URL helpers, base64, MIME types | | Config | — | config.h | Compile-time constants (timeouts, limits, user agent) | @@ -114,11 +117,12 @@ usage(void) - **Depth control.** Hard limit on crawl depth to prevent runaway. - **URL normalization.** Canonical form for deduplication. - **Graceful degradation.** Skip failed resources, continue crawling. +- **robots.txt compliance.** Respects Disallow/Allow rules and Crawl-delay. ## Build ```sh -make # build archiver-bot binary +make # build sbot binary make clean # remove build artifacts make install # install to /usr/local/bin ``` @@ -128,14 +132,14 @@ Dependencies: `libcurl` (via pkg-config) ## Usage ```sh -# Single page -archiver-bot https://example.com/article +# Single page archive (GWTAR format) +sbot https://example.com/article # Whole site (recursive, depth 3) -archiver-bot -r -d 3 https://example.com +sbot -r -d 3 https://example.com # Verbose with custom output dir -archiver-bot -v -r -o ./archive https://example.com +sbot -v -r -o ./archive https://example.com ``` ## Git Conventions diff --git a/.gitignore b/.gitignore index 52af25699b65dd3cc75b6a6218e2b45ea25a7cf3..694348837cc152c534af2b8992c83f9cd5a9a56b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # Build artifacts -archiver-bot +sbot *.o # Test output diff --git a/Makefile b/Makefile index 7f5ba55a7475525923b06db3cdfcf1ec484ff3b1..cb24706169d0e6cb38b16b302b3729f63f180a1b 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ -# archiver-bot - suckless web archiver +# sbot - Simple Archiver Bot # See LICENSE file for copyright and license details. -VERSION = 0.2.0 +VERSION = 0.3.0 # paths PREFIX = /usr/local @@ -20,26 +20,26 @@ LDFLAGS = $(LIBS) CC = cc # sources -SRC = archiver.c crawl.c fetch.c parse.c robots.c util.c +SRC = archiver.c crawl.c detect.c fetch.c parse.c robots.c util.c OBJ = $(SRC:.c=.o) -all: archiver-bot +all: sbot .c.o: $(CC) $(CFLAGS) -c $< -archiver-bot: $(OBJ) +sbot: $(OBJ) $(CC) -o $@ $(OBJ) $(LDFLAGS) clean: - rm -f archiver-bot $(OBJ) + rm -f sbot $(OBJ) install: all mkdir -p $(DESTDIR)$(PREFIX)/bin - cp -f archiver-bot $(DESTDIR)$(PREFIX)/bin - chmod 755 $(DESTDIR)$(PREFIX)/bin/archiver-bot + cp -f sbot $(DESTDIR)$(PREFIX)/bin + chmod 755 $(DESTDIR)$(PREFIX)/bin/sbot uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/archiver-bot + rm -f $(DESTDIR)$(PREFIX)/bin/sbot .PHONY: all clean install uninstall diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..49089cc90ed3e010bf8c178d4c7a63887354c97c --- /dev/null +++ b/README.md @@ -0,0 +1,229 @@ +# sbot + +**Simple Archiver Bot** -- a suckless web archiver written in C. + +sbot creates self-contained archives of web pages and entire websites. +Every resource -- CSS, images, fonts, scripts -- is fetched and inlined +directly into the HTML as base64 data URIs. The result is a single file +(or directory of files) that renders perfectly offline, with no external +dependencies, forever. + +## Why + +Web pages disappear. Link rot is real. The average web page has a +half-life of about two years. Bookmarks break, articles vanish, +references evaporate. + +sbot solves this by creating archives that are: + +- **Self-contained.** Everything is inlined. No external requests needed. +- **Human-readable.** Output is standard HTML. Open it in any browser. +- **Permanent.** No database, no server, no special viewer. Just files. +- **Metadata-rich.** GWTAR headers record provenance, date, and source. + +## Modes + +### Single Page Archive + +```sh +sbot https://example.com/article +``` + +Archives a single page in **GWTAR format** (Gwern Web Tar Archive). This +is the default mode and the most common use case. The output is one +`.gwtar.html` file containing: + +- A GWTAR metadata header (HTML comment) with title, source URL, domain, + author, archive date, and generator version +- The full HTML with all CSS stylesheets inlined as `