Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Changelog

All notable changes to vortex-mod-gallery will be documented here.
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [1.1.0] - 2026-07-17

### Added
- Declared `imgur_client_id` and `flickr_api_key` in the `[config]` manifest
section so the host can validate and persist them; the plugin already reads
both through `get_config` (MAT-134 R-01).
- Manifest test pinning every config key read by `plugin_api.rs` to a
`[config]` declaration, and an ABI smoke assertion proving a configured
Imgur client id travels from `get_config` into the `Client-ID`
Authorization header.

## [1.0.0] - 2026-04-15

### Added
- Initial release: Imgur, Flickr, and generic HTML gallery extraction with
`can_handle`, `supports_playlist`, `extract_links`, `extract_generic`, and
`is_http_url` exports.
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "vortex-mod-gallery"
version = "1.0.0"
version = "1.1.0"
edition = "2021"
description = "Gallery WASM plugin for Vortex — Imgur, Reddit, Flickr image galleries"
license = "GPL-3.0"
Expand Down
4 changes: 3 additions & 1 deletion plugin.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[plugin]
name = "vortex-mod-gallery"
version = "1.0.0"
version = "1.1.0"
category = "crawler"
author = "vortex-community"
description = "Image galleries: Imgur, Reddit, Flickr, generic <img> scraping"
Expand All @@ -15,3 +15,5 @@ http = true
[config]
min_resolution = { type = "string", default = "800x600", description = "Filter by minimum image size (WxH)" }
auto_name = { type = "boolean", default = true, description = "Auto-generate filenames from provider metadata" }
imgur_client_id = { type = "string", default = "", description = "Imgur API client ID (sent as 'Client-ID' authorization header)" }
flickr_api_key = { type = "string", default = "", description = "Flickr REST API key" }
26 changes: 26 additions & 0 deletions tests/manifest_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//! Guards the `[config]` contract: keys the plugin reads via `get_config`
//! must be declared in `plugin.toml` so the host can validate and expose them.

const MANIFEST: &str = include_str!("../plugin.toml");
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.

#[test]
fn manifest_declares_every_config_key_read_by_the_plugin() {
let (_, config_section) = MANIFEST
.split_once("[config]")
.expect("plugin.toml must have a [config] section");
for key in [
"min_resolution",
"auto_name",
"imgur_client_id",
"flickr_api_key",
] {
let declared = config_section.lines().any(|line| {
line.split_once('=')
.is_some_and(|(name, _)| name.trim() == key)
});
assert!(
declared,
"plugin.toml [config] is missing '{key}', which plugin_api.rs reads via get_config"
);
}
}
22 changes: 20 additions & 2 deletions tests/wasm_smoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const GENERIC_URL: &str = "https://example.test/gallery/page.html";
const GENERIC_IMAGE_URL: &str = "https://example.test/gallery/sample.jpg";
const IMGUR_BODY: &str = r#"{"data":[{"id":"img1","title":"sample","link":"https://i.imgur.com/img1.jpg","width":1920,"height":1080}],"status":200,"success":true}"#;
const GENERIC_BODY: &str = r#"<html><body><img src="sample.jpg"></body></html>"#;
const SMOKE_CLIENT_ID: &str = "SMOKE_CLIENT";

fn wasm_path() -> PathBuf {
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(WASM_REL_PATH);
Expand Down Expand Up @@ -38,6 +39,14 @@ fn stub_http_request() -> Function {
.as_str()
.ok_or_else(|| extism::Error::msg("http_request URL is missing"))?;
let body = if url.contains("api.imgur.com") {
// The configured client id must travel from `get_config`
// all the way into the Imgur Authorization header.
let auth = request["headers"]["Authorization"].as_str().unwrap_or("");
if auth != format!("Client-ID {SMOKE_CLIENT_ID}") {
return Err(extism::Error::msg(format!(
"imgur request carries wrong Authorization header: {auth:?}"
)));
}
IMGUR_BODY
} else if url == GENERIC_URL {
GENERIC_BODY
Expand All @@ -60,8 +69,17 @@ fn stub_get_config() -> Function {
[PTR],
[PTR],
UserData::<()>::default(),
|plugin, _inputs, outputs, _user_data: UserData<()>| {
let handle = plugin.memory_new("")?;
|plugin, inputs, outputs, _user_data: UserData<()>| {
let input = inputs[0]
.i64()
.ok_or_else(|| extism::Error::msg("get_config expected i64 input"))?;
let key: String = plugin.memory_get_val(&Val::I64(input))?;
let value = if key == "imgur_client_id" {
SMOKE_CLIENT_ID
} else {
""
};
let handle = plugin.memory_new(value)?;
outputs[0] = Val::I64(handle.offset() as i64);
Ok(())
},
Expand Down