Author SHA1 Message Date
clawbot 9c53a94ef6 Remove the no-op --collection option from get and get-thumb (closes #241)
check / check (push) Successful in 2m58s
Both commands listed `--collection <id>` as accepted and ignored. It now
is refused as an unknown option, and the README no longer mentions it.

Model: opus-5-5
2026-11-11 20:33:16 +00:00
5 changed files with 24 additions and 33 deletions

No files matched your search

+7 -26
View File
@@ -31,8 +31,7 @@ again on the next run. Every download is decrypted on its way to disk.
## Getting Started ## Getting Started
The commands below need `git`, `yarn` and Node 22.13 or later. Node 23 needs The commands below need `git`, Node 22 or later and `yarn`.
23.5 or later.
```bash ```bash
git clone https://git.eeqj.de/sneak/quak.git git clone https://git.eeqj.de/sneak/quak.git
@@ -70,29 +69,11 @@ The library keeps a local copy of the account's album and file lists, the cache.
It brings the cache up to date with the server in rounds called refreshes. It brings the cache up to date with the server in rounds called refreshes.
quak is not published to a package registry: `package.json` marks it `private`, quak is not published to a package registry: `package.json` marks it `private`,
and `dist/` is not committed. Clone and build it as above, then link the clone and `dist/` is not committed. Clone and build it as above, then add the clone to
into your own program: your own program's `package.json` by its path, for example
`yarn add file:../quak`. The package's `main`, `types` and `exports` fields
```bash point into `dist/`, so the clone must be built first. The package is an ES
# In the quak clone: module only, so a CommonJS program cannot `require` it.
yarn link
# In your program's directory:
yarn link quak
```
`yarn link` also installs the `quak` command in yarn's global bin directory, and
`yarn unlink` in the clone removes the link and the command.
A linked quak uses the dependencies that `yarn install` put in the clone, at the
versions in quak's `yarn.lock`. Avoid `yarn add file:../quak`: it resolves
quak's dependencies again, and their newer releases can need a newer Node.
`yarn link quak` does not add quak to your `package.json`, so run it again in
each new checkout of your program.
The package's `main`, `types` and `exports` fields point into `dist/`, so the
clone must be built first. The package is an ES module only, so a CommonJS
program cannot `require` it.
```ts ```ts
import { Client, Library } from "quak"; import { Client, Library } from "quak";
@@ -321,7 +302,7 @@ title, with unsafe characters replaced (see "File names from the server"). With
original is kept in the cache as well. original is kept in the cache as well.
A file ID that no collection holds gives `File <id> not found`, and the exit A file ID that no collection holds gives `File <id> not found`, and the exit
status is 1. The option `--collection <id>` is accepted and ignored. status is 1.
A live photo is a still image and a short video that Ente stores as one file. A live photo is a still image and a short video that Ente stores as one file.
`get` writes both, each named after the title with its own extension, as Ente's `get` writes both, each named after the title with its own extension, as Ente's
-2
View File
@@ -123,7 +123,6 @@ program
.description("Download and decrypt a single file") .description("Download and decrypt a single file")
.argument("<fileID>", "File ID (from `quak files`)") .argument("<fileID>", "File ID (from `quak files`)")
.option("--out <path>", "Output file path") .option("--out <path>", "Output file path")
.option("--collection <id>", "Accepted for compatibility; ignored")
.action((fileID: string, opts: { out?: string }) => .action((fileID: string, opts: { out?: string }) =>
run(getCommand(context(), fileID, opts)), run(getCommand(context(), fileID, opts)),
); );
@@ -133,7 +132,6 @@ program
.description("Download and decrypt a thumbnail") .description("Download and decrypt a thumbnail")
.argument("<fileID>", "File ID (from `quak files`)") .argument("<fileID>", "File ID (from `quak files`)")
.option("--out <path>", "Output file path") .option("--out <path>", "Output file path")
.option("--collection <id>", "Accepted for compatibility; ignored")
.action((fileID: string, opts: { out?: string }) => .action((fileID: string, opts: { out?: string }) =>
run(getThumbCommand(context(), fileID, opts)), run(getThumbCommand(context(), fileID, opts)),
); );
+1 -1
View File
@@ -12,7 +12,7 @@
"private": true, "private": true,
"type": "module", "type": "module",
"engines": { "engines": {
"node": "^22.13.0 || >=23.5.0" "node": ">=22"
}, },
"main": "./dist/src/index.js", "main": "./dist/src/index.js",
"types": "./dist/src/index.d.ts", "types": "./dist/src/index.d.ts",
+14 -2
View File
@@ -1,8 +1,9 @@
/** /**
* Tests for the retry options `bin/quak.ts` loads the saved session with * Tests for the retry options `bin/quak.ts` loads the saved session with
* (`quak backup` gets the unattended ones, every other command the default), * (`quak backup` gets the unattended ones, every other command the default),
* each with the callbacks that log its requests and retries, and for * each with the callbacks that log its requests and retries, for `quak files`
* `quak files` taking its collection ID as an optional argument. * taking its collection ID as an optional argument, and for `quak get` and
* `quak get-thumb` refusing `--collection`.
* *
* Each test runs `bin/quak.ts`, as the smoke test does, with its session loader * Each test runs `bin/quak.ts`, as the smoke test does, with its session loader
* replaced by one that records the options it is given and reports no session, * replaced by one that records the options it is given and reports no session,
@@ -105,3 +106,14 @@ describe("bin/quak.ts files", () => {
expect(await quak("files", "7")).toMatch(/^Not logged in/); expect(await quak("files", "7")).toMatch(/^Not logged in/);
}); });
}); });
describe("bin/quak.ts get and get-thumb", () => {
it.each(["get", "get-thumb"])(
"%s refuses --collection as an unknown option",
async (command) => {
expect(await quak(command, "1", "--collection", "2")).toMatch(
/^error: unknown option '--collection'/,
);
},
);
});
+2 -2
View File
@@ -569,14 +569,14 @@ describe("files", () => {
}); });
describe("get and get-thumb", () => { describe("get and get-thumb", () => {
it("get finds a file in any album without --collection", async () => { it("get finds a file in any album", async () => {
const out = join(root, "diagram.png"); const out = join(root, "diagram.png");
expect(await getCommand(context(), "200", { out })).toBe(0); expect(await getCommand(context(), "200", { out })).toBe(0);
expect(readFileSync(out)).toEqual(Buffer.alloc(7, 200)); expect(readFileSync(out)).toEqual(Buffer.alloc(7, 200));
expect(stderr.text).toBe(`7 bytes -> ${out}\n`); expect(stderr.text).toBe(`7 bytes -> ${out}\n`);
}); });
it("get-thumb finds a file in any album without --collection", async () => { it("get-thumb finds a file in any album", async () => {
const out = join(root, "thumb.jpg"); const out = join(root, "thumb.jpg");
expect(await getThumbCommand(context(), "200", { out })).toBe(0); expect(await getThumbCommand(context(), "200", { out })).toBe(0);
expect(readFileSync(out)).toEqual(Buffer.alloc(3, 200)); expect(readFileSync(out)).toEqual(Buffer.alloc(3, 200));