From 8ea40973a736db6b8b90a6c289f2b6b20fa9fef0 Mon Sep 17 00:00:00 2001 From: Nicholas <30300649+NicholasFlamy@users.noreply.github.com> Date: Wed, 28 May 2025 17:45:49 -0400 Subject: [PATCH] feat(server): apk links API endpoint for Obtainium Android mobile-server version sync (#18700) --- mobile/openapi/README.md | Bin 36278 -> 36434 bytes mobile/openapi/lib/api.dart | Bin 13002 -> 13042 bytes mobile/openapi/lib/api/server_api.dart | Bin 19929 -> 21329 bytes mobile/openapi/lib/api_client.dart | Bin 32879 -> 32965 bytes .../lib/model/server_apk_links_dto.dart | Bin 0 -> 3619 bytes open-api/immich-openapi-specs.json | 55 ++++++++++++++++++ open-api/typescript-sdk/src/fetch-client.ts | 14 +++++ server/src/controllers/server.controller.ts | 7 +++ server/src/dtos/server.dto.ts | 7 +++ server/src/services/server.service.ts | 11 ++++ 10 files changed, 94 insertions(+) create mode 100644 mobile/openapi/lib/model/server_apk_links_dto.dart diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index b8bcbcebcd7f5c59cd222f6f5ee2bd2483bfd9f2..22264857e06ede54e7d422c1a645c4b129231532 100644 GIT binary patch delta 103 zcmdlso9WUVrVZOnc^vanit;m4d@}R0izoM+NpdGb1ag1^lNHQGd7*q=kU;TdMl-q1 mdrWWJDL58ngY~$Sp92>Ad2 delta 12 TcmeyAdMb5;f!yW@xmh9rDKQ0H diff --git a/mobile/openapi/lib/api/server_api.dart b/mobile/openapi/lib/api/server_api.dart index a0fd54f3d2bb7c1a771f2f054b9363e29cd00a40..4220e674714cc6bd708295575c980ee7270db878 100644 GIT binary patch delta 151 zcmcaPoAKf@#tkR9coXwdit;m4baOKEvWq7>8rtzVLPUJP0v{FPc#xHBz9_w)QP!~_ z8!YWol5cOPke*tCqGzLqCO4A6=0-hRCIuud>N=VViNy-RsYPX}MKJNrbzITT09;o% A*8l(j delta 14 Wcmcb(jPd4d#tkR9HaiFiIs*VRs0GIW diff --git a/mobile/openapi/lib/api_client.dart b/mobile/openapi/lib/api_client.dart index 1059655323a4b40b5f8dd05a3177a1d1f449ecd0..2657cece1cc5c7ca8414dce1db1b873c62f68430 100644 GIT binary patch delta 42 ucmaFgz;v{cX@iO%hhssuPi9_r@#KrXa%>Rx(lMDRVHmmq~8vy`fln*?_?a1jeRqHnOCWR6HZif8X7a zl;lWVvOOdbk9Wtr@4h=S!(neYgp)t6Ca-@xyFB}Na&>kJ=kG4gA~>DE<>U%JOitgO z|MddZNb~JnXgm5b{^6)cOSQ~$Et5sAlZ8sMP?H<#{<BPW8jn2cT%4ew-+kAHK#U*`yRj$5%?%= zsWSrtGP!|iOYs^M2RM^4TC}zYwvy*@;oIZwXnH{(P%Ka z`7CFMuU$#K52G=-dd);Spq!(y^YyFy0@a23t5*yOd#PYT_f-<`Si`5`b;4>#t4fQM z>cx%@XG#0r>8i}aQd(FEv-&lkOH7ahty+XSBa<^}jL=(RHj;HEjWVn@2sMa)v-sbLOz$NLo=s696jrPJA{7#?7asqTm9`q!ww z(?o4WAMlQ$45L`N6N*7$HV_7VTIDE=fwCyT3XA-&h}fY=v7gIxPB++6k6 zo;1&~51eaysHpU$gG#gCv}cMvY3qqu8+x!G7zfSQ7n7vorZ4q{B7h%Xd}ByaevZW3 zskwvdp2z-D=Noa8;t+&|NR5mhLLprlwKQdFxvg8?r`I(V$R{y@0>Qb?4HPSLncK5< zVYk64vIDP}f%lzn@WN%)dOz@oiG%01l8UL3I3En%<3lyB3Hf5g7&U#;txbu&X3vOhU!I^;G+uPj`T)!H{ebYQL4A0j4`d0G$9?r)1~x` za8S!7GYw$b#4_SrZQFFHOLfI-CFl;R57fh>G7-vF@|upk`)K4$3N1|;NwMLrAws8 zjRd@(4IWFqAmII{$tC?0;R(Q(cJ-gb?_^uOl*adrNBt~v_ZF?gP2?r@)#3&IzMvI8 IvTzRl13wmnhX4Qo literal 0 HcmV?d00001 diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 6aca3c349..dee027f83 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -5275,6 +5275,38 @@ ] } }, + "/server/android-links": { + "get": { + "operationId": "getAndroidLinks", + "parameters": [], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServerApkLinksDto" + } + } + }, + "description": "" + } + }, + "security": [ + { + "bearer": [] + }, + { + "cookie": [] + }, + { + "api_key": [] + } + ], + "tags": [ + "Server" + ] + } + }, "/server/config": { "get": { "operationId": "getServerConfig", @@ -11959,6 +11991,29 @@ ], "type": "object" }, + "ServerApkLinksDto": { + "properties": { + "arm64v8a": { + "type": "string" + }, + "armeabiv7a": { + "type": "string" + }, + "universal": { + "type": "string" + }, + "x86_64": { + "type": "string" + } + }, + "required": [ + "arm64v8a", + "armeabiv7a", + "universal", + "x86_64" + ], + "type": "object" + }, "ServerConfigDto": { "properties": { "externalDomain": { diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index 050fabca9..0c0ffd979 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -1004,6 +1004,12 @@ export type ServerAboutResponseDto = { version: string; versionUrl: string; }; +export type ServerApkLinksDto = { + arm64v8a: string; + armeabiv7a: string; + universal: string; + x86_64: string; +}; export type ServerConfigDto = { externalDomain: string; isInitialized: boolean; @@ -2868,6 +2874,14 @@ export function getAboutInfo(opts?: Oazapfts.RequestOpts) { ...opts })); } +export function getAndroidLinks(opts?: Oazapfts.RequestOpts) { + return oazapfts.ok(oazapfts.fetchJson<{ + status: 200; + data: ServerApkLinksDto; + }>("/server/android-links", { + ...opts + })); +} export function getServerConfig(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; diff --git a/server/src/controllers/server.controller.ts b/server/src/controllers/server.controller.ts index 267fc42ef..5bc78574c 100644 --- a/server/src/controllers/server.controller.ts +++ b/server/src/controllers/server.controller.ts @@ -3,6 +3,7 @@ import { ApiNotFoundResponse, ApiTags } from '@nestjs/swagger'; import { LicenseKeyDto, LicenseResponseDto } from 'src/dtos/license.dto'; import { ServerAboutResponseDto, + ServerApkLinksDto, ServerConfigDto, ServerFeaturesDto, ServerMediaTypesResponseDto, @@ -34,6 +35,12 @@ export class ServerController { return this.service.getAboutInfo(); } + @Get('android-links') + @Authenticated() + getAndroidLinks(): ServerApkLinksDto { + return this.service.getAndroidLinks(); + } + @Get('storage') @Authenticated() getStorage(): Promise { diff --git a/server/src/dtos/server.dto.ts b/server/src/dtos/server.dto.ts index e1f94dbaa..47442ad4f 100644 --- a/server/src/dtos/server.dto.ts +++ b/server/src/dtos/server.dto.ts @@ -37,6 +37,13 @@ export class ServerAboutResponseDto { thirdPartySupportUrl?: string; } +export class ServerApkLinksDto { + arm64v8a!: string; + armeabiv7a!: string; + universal!: string; + x86_64!: string; +} + export class ServerStorageResponseDto { diskSize!: string; diskUse!: string; diff --git a/server/src/services/server.service.ts b/server/src/services/server.service.ts index 9112c40a1..f07b8ee92 100644 --- a/server/src/services/server.service.ts +++ b/server/src/services/server.service.ts @@ -5,6 +5,7 @@ import { OnEvent } from 'src/decorators'; import { LicenseKeyDto, LicenseResponseDto } from 'src/dtos/license.dto'; import { ServerAboutResponseDto, + ServerApkLinksDto, ServerConfigDto, ServerFeaturesDto, ServerMediaTypesResponseDto, @@ -48,6 +49,16 @@ export class ServerService extends BaseService { }; } + getAndroidLinks(): ServerApkLinksDto { + const baseURL = `https://github.com/immich-app/immich/releases/download/v${serverVersion.toString()}`; + return { + arm64v8a: `${baseURL}/app-arm64-v8a-release.apk`, + armeabiv7a: `${baseURL}/app-armeabi-v7a-release.apk`, + universal: `${baseURL}/app-release.apk`, + x86_64: `${baseURL}/app-x86_64-release.apk`, + }; + } + async getStorage(): Promise { const libraryBase = StorageCore.getBaseFolder(StorageFolder.LIBRARY); const diskInfo = await this.storageRepository.checkDiskUsage(libraryBase);