mirror of
https://github.com/immich-app/immich.git
synced 2024-12-29 15:11:58 +00:00
chore(cli): use upload api and update documentation (#6927)
* use fetch api * bump version * add documentation * revert to using file blob
This commit is contained in:
parent
ce6dc3b7af
commit
755444e9a4
4 changed files with 31 additions and 43 deletions
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@immich/cli",
|
||||
"version": "2.0.6",
|
||||
"version": "2.0.7",
|
||||
"description": "Command Line Interface (CLI) for Immich",
|
||||
"type": "module",
|
||||
"exports": "./dist/index.js",
|
||||
|
|
|
@ -7,14 +7,15 @@ import { basename } from 'node:path';
|
|||
import { access, constants, stat, unlink } from 'node:fs/promises';
|
||||
import { createHash } from 'node:crypto';
|
||||
import os from 'node:os';
|
||||
import { UploadFileRequest } from '@immich/sdk';
|
||||
|
||||
class Asset {
|
||||
readonly path: string;
|
||||
readonly deviceId!: string;
|
||||
|
||||
deviceAssetId?: string;
|
||||
fileCreatedAt?: string;
|
||||
fileModifiedAt?: string;
|
||||
fileCreatedAt?: Date;
|
||||
fileModifiedAt?: Date;
|
||||
sidecarPath?: string;
|
||||
fileSize!: number;
|
||||
albumName?: string;
|
||||
|
@ -26,13 +27,13 @@ class Asset {
|
|||
async prepare() {
|
||||
const stats = await stat(this.path);
|
||||
this.deviceAssetId = `${basename(this.path)}-${stats.size}`.replaceAll(/\s+/g, '');
|
||||
this.fileCreatedAt = stats.mtime.toISOString();
|
||||
this.fileModifiedAt = stats.mtime.toISOString();
|
||||
this.fileCreatedAt = stats.mtime;
|
||||
this.fileModifiedAt = stats.mtime;
|
||||
this.fileSize = stats.size;
|
||||
this.albumName = this.extractAlbumName();
|
||||
}
|
||||
|
||||
async getUploadFormData(): Promise<FormData> {
|
||||
async getUploadFileRequest(): Promise<UploadFileRequest> {
|
||||
if (!this.deviceAssetId) {
|
||||
throw new Error('Device asset id not set');
|
||||
}
|
||||
|
@ -51,25 +52,15 @@ class Asset {
|
|||
sidecarData = new File([await fs.openAsBlob(sideCarPath)], basename(sideCarPath));
|
||||
} catch {}
|
||||
|
||||
const data: any = {
|
||||
return {
|
||||
assetData: new File([await fs.openAsBlob(this.path)], basename(this.path)),
|
||||
deviceAssetId: this.deviceAssetId,
|
||||
deviceId: 'CLI',
|
||||
fileCreatedAt: this.fileCreatedAt,
|
||||
fileModifiedAt: this.fileModifiedAt,
|
||||
isFavorite: String(false),
|
||||
isFavorite: false,
|
||||
sidecarData,
|
||||
};
|
||||
const formData = new FormData();
|
||||
|
||||
for (const property in data) {
|
||||
formData.append(property, data[property]);
|
||||
}
|
||||
|
||||
if (sidecarData) {
|
||||
formData.append('sidecarData', sidecarData);
|
||||
}
|
||||
|
||||
return formData;
|
||||
}
|
||||
|
||||
async delete(): Promise<void> {
|
||||
|
@ -197,10 +188,9 @@ export class UploadCommand extends BaseCommand {
|
|||
|
||||
if (!skipAsset && !options.dryRun) {
|
||||
if (!skipUpload) {
|
||||
const formData = await asset.getUploadFormData();
|
||||
const response = await this.uploadAsset(formData);
|
||||
const json = await response.json();
|
||||
existingAssetId = json.id;
|
||||
const fileRequest = await asset.getUploadFileRequest();
|
||||
const response = await this.immichApi.assetApi.uploadFile(fileRequest);
|
||||
existingAssetId = response.id;
|
||||
uploadCounter++;
|
||||
totalSizeUploaded += asset.fileSize;
|
||||
}
|
||||
|
@ -258,21 +248,4 @@ export class UploadCommand extends BaseCommand {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async uploadAsset(data: FormData): Promise<Response> {
|
||||
const url = this.immichApi.instanceUrl + '/asset/upload';
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'post',
|
||||
redirect: 'error',
|
||||
headers: {
|
||||
'x-api-key': this.immichApi.apiKey,
|
||||
},
|
||||
body: data,
|
||||
});
|
||||
if (response.status !== 200 && response.status !== 201) {
|
||||
throw new Error(await response.text());
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ program
|
|||
.addOption(new Option('-r, --recursive', 'Recursive').env('IMMICH_RECURSIVE').default(false))
|
||||
.addOption(new Option('-i, --ignore [paths...]', 'Paths to ignore').env('IMMICH_IGNORE_PATHS'))
|
||||
.addOption(new Option('-h, --skip-hash', "Don't hash files before upload").env('IMMICH_SKIP_HASH').default(false))
|
||||
.addOption(new Option('-i, --include-hidden', 'Include hidden folders').env('IMMICH_INCLUDE_HIDDEN').default(false))
|
||||
.addOption(new Option('-H, --include-hidden', 'Include hidden folders').env('IMMICH_INCLUDE_HIDDEN').default(false))
|
||||
.addOption(
|
||||
new Option('-a, --album', 'Automatically create albums based on folder name')
|
||||
.env('IMMICH_AUTO_CREATE_ALBUM')
|
||||
|
|
|
@ -39,10 +39,11 @@ immich
|
|||
```
|
||||
Usage: immich [options] [command]
|
||||
|
||||
Immich command line interface
|
||||
Command line interface for Immich
|
||||
|
||||
Options:
|
||||
-V, --version output the version number
|
||||
-d, --config Configuration directory (env: IMMICH_CONFIG_DIR)
|
||||
-h, --help display help for command
|
||||
|
||||
Commands:
|
||||
|
@ -69,7 +70,9 @@ Options:
|
|||
-r, --recursive Recursive (default: false, env: IMMICH_RECURSIVE)
|
||||
-i, --ignore [paths...] Paths to ignore (env: IMMICH_IGNORE_PATHS)
|
||||
-h, --skip-hash Don't hash files before upload (default: false, env: IMMICH_SKIP_HASH)
|
||||
-H, --include-hidden Include hidden folders (default: false, env: IMMICH_INCLUDE_HIDDEN)
|
||||
-a, --album Automatically create albums based on folder name (default: false, env: IMMICH_AUTO_CREATE_ALBUM)
|
||||
-A, --album-name <name> Add all assets to specified album (env: IMMICH_ALBUM_NAME)
|
||||
-n, --dry-run Don't perform any actions, just show what will be done (default: false, env: IMMICH_DRY_RUN)
|
||||
--delete Delete local assets after upload (env: IMMICH_DELETE_ASSETS)
|
||||
--help display help for command
|
||||
|
@ -91,7 +94,7 @@ For instance,
|
|||
immich login-key http://192.168.1.216:2283/api HFEJ38DNSDUEG
|
||||
```
|
||||
|
||||
This will store your credentials in a file in your home directory. Please keep the file secure, either by performing the logout command after you are done, or deleting it manually.
|
||||
This will store your credentials in a `auth.yml` file in the configuration directory which defaults to `~/.config/`. The directory can be set with the `-d` option or the environment variable `IMMICH_CONFIG_DIR`. Please keep the file secure, either by performing the logout command after you are done, or deleting it manually.
|
||||
|
||||
Once you are authenticated, you can upload assets to your Immich server.
|
||||
|
||||
|
@ -123,6 +126,12 @@ You can automatically create albums based on the folder name by passing the `--a
|
|||
immich upload --album --recursive directory/
|
||||
```
|
||||
|
||||
You can also choose to upload all assets to a specific album with the `--album-name` option.
|
||||
|
||||
```bash
|
||||
immich upload --album-name "My summer holiday" --recursive directory/
|
||||
```
|
||||
|
||||
It is possible to skip assets matching a glob pattern by passing the `--ignore` option. See [the library documentation](docs/features/libraries.md) on how to use glob patterns. You can add several exclusion patterns if needed.
|
||||
|
||||
```bash
|
||||
|
@ -133,6 +142,12 @@ immich upload --ignore **/Raw/** --recursive directory/
|
|||
immich upload --ignore **/Raw/** **/*.tif --recursive directory/
|
||||
```
|
||||
|
||||
By default, hidden files are skipped. If you want to include hidden files, use the `--include-hidden` option:
|
||||
|
||||
```bash
|
||||
immich upload --include-hidden --recursive directory/
|
||||
```
|
||||
|
||||
### Obtain the API Key
|
||||
|
||||
The API key can be obtained in the user setting panel on the web interface.
|
||||
|
|
Loading…
Reference in a new issue