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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ Provider and query may be given as positionals after `s` / `-s`, or with `-P` /
| `cupcake` | [Cupcake](https://cupcake.nilssonlee.se) | Free CC0 stock photography by Jonas Nilsson Lee | Direct master resolution photo downloads. |
| `freenaturestock` | [Free Nature Stock](https://freenaturestock.com) | Free CC0 nature & wildlife stock photography by Adrian Pelletier | Direct master full-resolution photo downloads (up to 20+ MB). |
| `goodfreephotos` | [Good Free Photos](https://goodfreephotos.com) | Free CC0 public domain photos, state parks, and landmarks by Yinan Chen | Direct master full-resolution photo downloads. |
| `wikimedia` | [Wikimedia Commons](https://commons.wikimedia.org) | Freely licensed and public domain educational & stock media repository | Direct master full-resolution image downloads. |

List providers at runtime via `ast help` (printed under **PROVIDERS**).

Expand Down Expand Up @@ -312,6 +313,7 @@ src/
cupcake.zig
freenaturestock.zig
goodfreephotos.zig
wikimedia.zig
assets/ README banner and static assets
docs/ Provider implementation notes
install.sh curl | bash installer (Linux release binaries)
Expand Down
16 changes: 16 additions & 0 deletions docs/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,19 @@ This document summarizes the network endpoints, transport models, and image down
* Master full-resolution URLs constructed by rewriting `/cache/` to `/albums/` and stripping thumbnail geometry tokens (`_200_w200_..._thumb`).
* **Download**: Direct GET on master original camera photo JPEG files.
* **License**: CC0 / 100% Free Public Domain.

---

## 22. Wikimedia Commons (`commons.wikimedia.org`)

* **Search**: `GET https://commons.wikimedia.org/w/api.php?action=query&generator=search&gsrnamespace=6&gsrsearch={query}&gsrlimit={limit}&prop=imageinfo&iiprop=url|size|mime&iiurlwidth=500&format=json`
* **Format**: Official MediaWiki Action API querying Wikimedia's file repository (namespace 6).
* **Extraction**:
* Sorted ascending by search relevance rank (`index`).
* File IDs formatted as `wikimedia-{pageid}`.
* Titles cleaned by stripping `File:` prefix and file extensions, and replacing underscores with spaces.
* Full original master media URLs extracted from `imageinfo.url` (with query tracking stripped).
* 500px thumbnail URLs extracted from `imageinfo.thumburl`.
* Dimensions extracted from `imageinfo.width` and `imageinfo.height`.
* **Download**: Direct GET on full master resolution media via `upload.wikimedia.org`.
* **License**: Public Domain, CC0, and Creative Commons.
2 changes: 1 addition & 1 deletion docs/stock_photo_sites.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This document tracks all 24 stock photo websites listed in the [GrayGrids 21+ Be

- **Total Sites Listed**: 24
- **Implemented & Working**: 13 (`unsplash`, `isorepublic`, `picjumbo`, `foodiesfeed`, `picography`, `gratisography`, `startupstockphotos`, `burst`, `jaymantri`, `publicdomainarchive`, `magdeleine`, `splitshire`, `deviantart`)
- *(Additional Providers Implemented in `ast`)*: `aura` ([Aura.build](https://www.aura.build)), `negativespace` ([NegativeSpace.co](https://negativespace.co)), `skitterphoto` ([Skitterphoto.com](https://skitterphoto.com)), `libreshot` ([LibreShot.com](https://libreshot.com)), `moveast` ([Moveast.me](https://moveast.me)), `cupcake` ([Cupcake](https://cupcake.nilssonlee.se)), `freenaturestock` ([FreeNatureStock](https://freenaturestock.com)), `goodfreephotos` ([Good Free Photos](https://goodfreephotos.com))
- *(Additional Providers Implemented in `ast`)*: `aura` ([Aura.build](https://www.aura.build)), `negativespace` ([NegativeSpace.co](https://negativespace.co)), `skitterphoto` ([Skitterphoto.com](https://skitterphoto.com)), `libreshot` ([LibreShot.com](https://libreshot.com)), `moveast` ([Moveast.me](https://moveast.me)), `cupcake` ([Cupcake](https://cupcake.nilssonlee.se)), `freenaturestock` ([FreeNatureStock](https://freenaturestock.com)), `goodfreephotos` ([Good Free Photos](https://goodfreephotos.com)), `wikimedia` ([Wikimedia Commons](https://commons.wikimedia.org))
- **Unimplemented / Blocked / Pending**: 11

---
Expand Down
9 changes: 9 additions & 0 deletions src/commands/search.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const moveast = @import("../providers/moveast.zig");
const cupcake = @import("../providers/cupcake.zig");
const freenaturestock = @import("../providers/freenaturestock.zig");
const goodfreephotos = @import("../providers/goodfreephotos.zig");
const wikimedia = @import("../providers/wikimedia.zig");
const stdio = @import("../stdio.zig");
const Allocator = std.mem.Allocator;
const Io = std.Io;
Expand Down Expand Up @@ -108,6 +109,9 @@ fn doSearch(
if (std.ascii.eqlIgnoreCase(provider_id, "goodfreephotos")) {
return goodfreephotos.search(client, allocator, query, limit);
}
if (std.ascii.eqlIgnoreCase(provider_id, "wikimedia")) {
return wikimedia.search(client, allocator, query, limit);
}
return error.UnknownProvider;
}

Expand Down Expand Up @@ -182,6 +186,9 @@ fn doDownload(
if (std.ascii.eqlIgnoreCase(provider_id, "goodfreephotos")) {
return goodfreephotos.download(client, allocator, io, a, output_dir);
}
if (std.ascii.eqlIgnoreCase(provider_id, "wikimedia")) {
return wikimedia.download(client, allocator, io, a, output_dir);
}
return error.UnknownProvider;
}

Expand All @@ -207,6 +214,7 @@ fn doPrompt(provider_id: []const u8, a: Asset) ?[]const u8 {
if (std.ascii.eqlIgnoreCase(provider_id, "cupcake")) return cupcake.getPrompt(a);
if (std.ascii.eqlIgnoreCase(provider_id, "freenaturestock")) return freenaturestock.getPrompt(a);
if (std.ascii.eqlIgnoreCase(provider_id, "goodfreephotos")) return goodfreephotos.getPrompt(a);
if (std.ascii.eqlIgnoreCase(provider_id, "wikimedia")) return wikimedia.getPrompt(a);
return a.prompt orelse a.description;
}

Expand All @@ -232,6 +240,7 @@ fn doUrl(provider_id: []const u8, a: Asset) ?[]const u8 {
if (std.ascii.eqlIgnoreCase(provider_id, "cupcake")) return cupcake.getUrl(a);
if (std.ascii.eqlIgnoreCase(provider_id, "freenaturestock")) return freenaturestock.getUrl(a);
if (std.ascii.eqlIgnoreCase(provider_id, "goodfreephotos")) return goodfreephotos.getUrl(a);
if (std.ascii.eqlIgnoreCase(provider_id, "wikimedia")) return wikimedia.getUrl(a);
return a.image_url;
}

Expand Down
9 changes: 9 additions & 0 deletions src/interactive.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const moveast = @import("providers/moveast.zig");
const cupcake = @import("providers/cupcake.zig");
const freenaturestock = @import("providers/freenaturestock.zig");
const goodfreephotos = @import("providers/goodfreephotos.zig");
const wikimedia = @import("providers/wikimedia.zig");
const registry = @import("providers/registry.zig");
const stdio = @import("stdio.zig");
const Allocator = std.mem.Allocator;
Expand Down Expand Up @@ -105,6 +106,9 @@ fn searchProvider(
if (std.ascii.eqlIgnoreCase(provider_id, "goodfreephotos")) {
return goodfreephotos.search(client, allocator, query, config.default_limit);
}
if (std.ascii.eqlIgnoreCase(provider_id, "wikimedia")) {
return wikimedia.search(client, allocator, query, config.default_limit);
}
return error.UnknownProvider;
}

Expand Down Expand Up @@ -178,6 +182,9 @@ fn downloadAsset(
if (std.ascii.eqlIgnoreCase(provider_id, "goodfreephotos")) {
return goodfreephotos.download(client, allocator, io, a, config.default_output_dir);
}
if (std.ascii.eqlIgnoreCase(provider_id, "wikimedia")) {
return wikimedia.download(client, allocator, io, a, config.default_output_dir);
}
return error.UnknownProvider;
}

Expand All @@ -203,6 +210,7 @@ fn promptOf(provider_id: []const u8, a: Asset) ?[]const u8 {
if (std.ascii.eqlIgnoreCase(provider_id, "cupcake")) return cupcake.getPrompt(a);
if (std.ascii.eqlIgnoreCase(provider_id, "freenaturestock")) return freenaturestock.getPrompt(a);
if (std.ascii.eqlIgnoreCase(provider_id, "goodfreephotos")) return goodfreephotos.getPrompt(a);
if (std.ascii.eqlIgnoreCase(provider_id, "wikimedia")) return wikimedia.getPrompt(a);
return a.prompt;
}

Expand All @@ -228,6 +236,7 @@ fn urlOf(provider_id: []const u8, a: Asset) ?[]const u8 {
if (std.ascii.eqlIgnoreCase(provider_id, "cupcake")) return cupcake.getUrl(a);
if (std.ascii.eqlIgnoreCase(provider_id, "freenaturestock")) return freenaturestock.getUrl(a);
if (std.ascii.eqlIgnoreCase(provider_id, "goodfreephotos")) return goodfreephotos.getUrl(a);
if (std.ascii.eqlIgnoreCase(provider_id, "wikimedia")) return wikimedia.getUrl(a);
return a.image_url;
}

Expand Down
4 changes: 3 additions & 1 deletion src/providers/registry.zig
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const moveast = @import("moveast.zig");
const cupcake = @import("cupcake.zig");
const freenaturestock = @import("freenaturestock.zig");
const goodfreephotos = @import("goodfreephotos.zig");
const wikimedia = @import("wikimedia.zig");

pub const ProviderInfo = struct {
id: []const u8,
Expand Down Expand Up @@ -51,6 +52,7 @@ pub fn list() []const ProviderInfo {
.{ .id = cupcake.id, .name = cupcake.name },
.{ .id = freenaturestock.id, .name = freenaturestock.name },
.{ .id = goodfreephotos.id, .name = goodfreephotos.name },
.{ .id = wikimedia.id, .name = wikimedia.name },
};
}

Expand All @@ -69,5 +71,5 @@ pub fn displayName(id: []const u8) ?[]const u8 {
}

pub fn availableIds() []const u8 {
return "aura, unsplash, isorepublic, picjumbo, foodiesfeed, picography, gratisography, startupstockphotos, burst, jaymantri, publicdomainarchive, magdeleine, splitshire, deviantart, negativespace, skitterphoto, libreshot, moveast, cupcake, freenaturestock, goodfreephotos";
return "aura, unsplash, isorepublic, picjumbo, foodiesfeed, picography, gratisography, startupstockphotos, burst, jaymantri, publicdomainarchive, magdeleine, splitshire, deviantart, negativespace, skitterphoto, libreshot, moveast, cupcake, freenaturestock, goodfreephotos, wikimedia";
}
Loading
Loading