Compare commits
2
Commits
e6c0350287
...
63ba259ced
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63ba259ced | ||
|
|
8e120a4f49 |
No files matched your search
@@ -31,7 +31,8 @@ again on the next run. Every download is decrypted on its way to disk.
|
||||
|
||||
## Getting Started
|
||||
|
||||
The commands below need `git`, Node 22 or later and `yarn`.
|
||||
The commands below need `git`, `yarn` and Node 22.13 or later. Node 23 needs
|
||||
23.5 or later.
|
||||
|
||||
```bash
|
||||
git clone https://git.eeqj.de/sneak/quak.git
|
||||
@@ -69,11 +70,29 @@ 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.
|
||||
|
||||
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 add the clone to
|
||||
your own program's `package.json` by its path, for example
|
||||
`yarn add file:../quak`. 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.
|
||||
and `dist/` is not committed. Clone and build it as above, then link the clone
|
||||
into your own program:
|
||||
|
||||
```bash
|
||||
# In the quak clone:
|
||||
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
|
||||
import { Client, Library } from "quak";
|
||||
@@ -302,7 +321,7 @@ title, with unsafe characters replaced (see "File names from the server"). With
|
||||
original is kept in the cache as well.
|
||||
|
||||
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.
|
||||
`get` writes both, each named after the title with its own extension, as Ente's
|
||||
|
||||
@@ -123,7 +123,6 @@ program
|
||||
.description("Download and decrypt a single file")
|
||||
.argument("<fileID>", "File ID (from `quak files`)")
|
||||
.option("--out <path>", "Output file path")
|
||||
.option("--collection <id>", "Accepted for compatibility; ignored")
|
||||
.action((fileID: string, opts: { out?: string }) =>
|
||||
run(getCommand(context(), fileID, opts)),
|
||||
);
|
||||
@@ -133,7 +132,6 @@ program
|
||||
.description("Download and decrypt a thumbnail")
|
||||
.argument("<fileID>", "File ID (from `quak files`)")
|
||||
.option("--out <path>", "Output file path")
|
||||
.option("--collection <id>", "Accepted for compatibility; ignored")
|
||||
.action((fileID: string, opts: { out?: string }) =>
|
||||
run(getThumbCommand(context(), fileID, opts)),
|
||||
);
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
"node": "^22.13.0 || >=23.5.0"
|
||||
},
|
||||
"main": "./dist/src/index.js",
|
||||
"types": "./dist/src/index.d.ts",
|
||||
|
||||
+14
-2
@@ -1,8 +1,9 @@
|
||||
/**
|
||||
* Tests for the retry options `bin/quak.ts` loads the saved session with
|
||||
* (`quak backup` gets the unattended ones, every other command the default),
|
||||
* each with the callbacks that log its requests and retries, and for
|
||||
* `quak files` taking its collection ID as an optional argument.
|
||||
* each with the callbacks that log its requests and retries, for `quak files`
|
||||
* 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
|
||||
* 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/);
|
||||
});
|
||||
});
|
||||
|
||||
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'/,
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
@@ -569,14 +569,14 @@ describe("files", () => {
|
||||
});
|
||||
|
||||
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");
|
||||
expect(await getCommand(context(), "200", { out })).toBe(0);
|
||||
expect(readFileSync(out)).toEqual(Buffer.alloc(7, 200));
|
||||
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");
|
||||
expect(await getThumbCommand(context(), "200", { out })).toBe(0);
|
||||
expect(readFileSync(out)).toEqual(Buffer.alloc(3, 200));
|
||||
|
||||
Reference in new issue
Block a user