"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ServerService = void 0;
const common_1 = require("@nestjs/common");
const constants_1 = require("../constants");
const storage_core_1 = require("../cores/storage.core");
const decorators_1 = require("../decorators");
const server_dto_1 = require("../dtos/server.dto");
const enum_1 = require("../enum");
const base_service_1 = require("./base.service");
const bytes_1 = require("../utils/bytes");
const mime_types_1 = require("../utils/mime-types");
const misc_1 = require("../utils/misc");
let ServerService = class ServerService extends base_service_1.BaseService {
    async onBootstrap() {
        const featureFlags = await this.getFeatures();
        if (featureFlags.configFile) {
            await this.systemMetadataRepository.set(enum_1.SystemMetadataKey.AdminOnboarding, {
                isOnboarded: true,
            });
        }
        this.logger.log(`Feature Flags: ${JSON.stringify(await this.getFeatures(), null, 2)}`);
    }
    async getAboutInfo() {
        const version = `v${constants_1.serverVersion.toString()}`;
        const { buildMetadata } = this.configRepository.getEnv();
        const buildVersions = await this.serverInfoRepository.getBuildVersions();
        const licensed = await this.systemMetadataRepository.get(enum_1.SystemMetadataKey.License);
        return {
            version,
            versionUrl: `https://github.com/immich-app/immich/releases/tag/${version}`,
            licensed: !!licensed,
            ...buildMetadata,
            ...buildVersions,
        };
    }
    getApkLinks() {
        const baseUrl = `https://github.com/immich-app/immich/releases/download/v${constants_1.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() {
        const libraryBase = storage_core_1.StorageCore.getBaseFolder(enum_1.StorageFolder.Library);
        const diskInfo = await this.storageRepository.checkDiskUsage(libraryBase);
        const usagePercentage = (((diskInfo.total - diskInfo.free) / diskInfo.total) * 100).toFixed(2);
        const serverInfo = new server_dto_1.ServerStorageResponseDto();
        serverInfo.diskAvailable = (0, bytes_1.asHumanReadable)(diskInfo.available);
        serverInfo.diskSize = (0, bytes_1.asHumanReadable)(diskInfo.total);
        serverInfo.diskUse = (0, bytes_1.asHumanReadable)(diskInfo.total - diskInfo.free);
        serverInfo.diskAvailableRaw = diskInfo.available;
        serverInfo.diskSizeRaw = diskInfo.total;
        serverInfo.diskUseRaw = diskInfo.total - diskInfo.free;
        serverInfo.diskUsagePercentage = Number.parseFloat(usagePercentage);
        return serverInfo;
    }
    ping() {
        return { res: 'pong' };
    }
    async getFeatures() {
        const { reverseGeocoding, metadata, map, machineLearning, trash, oauth, passwordLogin, notifications, ffmpeg } = await this.getConfig({ withCache: false });
        const { configFile } = this.configRepository.getEnv();
        return {
            smartSearch: (0, misc_1.isSmartSearchEnabled)(machineLearning),
            facialRecognition: (0, misc_1.isFacialRecognitionEnabled)(machineLearning),
            duplicateDetection: (0, misc_1.isDuplicateDetectionEnabled)(machineLearning),
            map: map.enabled,
            reverseGeocoding: reverseGeocoding.enabled,
            importFaces: metadata.faces.import,
            sidecar: true,
            search: true,
            trash: trash.enabled,
            oauth: oauth.enabled,
            oauthAutoLaunch: oauth.autoLaunch,
            ocr: (0, misc_1.isOcrEnabled)(machineLearning),
            passwordLogin: passwordLogin.enabled,
            configFile: !!configFile,
            email: notifications.smtp.enabled,
            realtimeTranscoding: ffmpeg.realtime.enabled,
        };
    }
    async getSystemConfig() {
        const { setup } = this.configRepository.getEnv();
        const config = await this.getConfig({ withCache: false });
        const isInitialized = !setup.allow || (await this.userRepository.hasAdmin());
        const onboarding = await this.systemMetadataRepository.get(enum_1.SystemMetadataKey.AdminOnboarding);
        return {
            loginPageMessage: config.server.loginPageMessage,
            trashDays: config.trash.days,
            userDeleteDelay: config.user.deleteDelay,
            oauthButtonText: config.oauth.buttonText,
            isInitialized,
            isOnboarded: onboarding?.isOnboarded || false,
            externalDomain: config.server.externalDomain,
            publicUsers: config.server.publicUsers,
            mapDarkStyleUrl: config.map.darkStyle,
            mapLightStyleUrl: config.map.lightStyle,
            maintenanceMode: false,
            minFaces: config.machineLearning.facialRecognition.minFaces,
        };
    }
    async getStatistics() {
        const userStats = await this.userRepository.getUserStats();
        const serverStats = new server_dto_1.ServerStatsResponseDto();
        serverStats.photos ??= 0;
        serverStats.videos ??= 0;
        serverStats.usage ??= 0;
        serverStats.usagePhotos ??= 0;
        serverStats.usageVideos ??= 0;
        serverStats.usageByUser ??= [];
        for (const user of userStats) {
            const usage = new server_dto_1.UsageByUserDto();
            usage.userId = user.userId;
            usage.userName = user.userName;
            usage.photos = user.photos;
            usage.videos = user.videos;
            usage.usage = user.usage;
            usage.usagePhotos = user.usagePhotos;
            usage.usageVideos = user.usageVideos;
            usage.quotaSizeInBytes = user.quotaSizeInBytes;
            serverStats.photos += usage.photos;
            serverStats.videos += usage.videos;
            serverStats.usage += usage.usage;
            serverStats.usagePhotos += usage.usagePhotos;
            serverStats.usageVideos += usage.usageVideos;
            serverStats.usageByUser.push(usage);
        }
        return serverStats;
    }
    getSupportedMediaTypes() {
        return {
            video: Object.keys(mime_types_1.mimeTypes.video),
            image: Object.keys(mime_types_1.mimeTypes.image),
            sidecar: Object.keys(mime_types_1.mimeTypes.sidecar),
        };
    }
    async deleteLicense() {
        await this.systemMetadataRepository.delete(enum_1.SystemMetadataKey.License);
    }
    async getLicense() {
        const license = await this.systemMetadataRepository.get(enum_1.SystemMetadataKey.License);
        if (!license) {
            throw new common_1.NotFoundException();
        }
        return license;
    }
    async setLicense(dto) {
        if (!dto.licenseKey.startsWith('IMSV-')) {
            throw new common_1.BadRequestException('Invalid license key');
        }
        const { licensePublicKey } = this.configRepository.getEnv();
        const licenseValid = this.cryptoRepository.verifySha256(dto.licenseKey, dto.activationKey, licensePublicKey.server);
        if (!licenseValid) {
            throw new common_1.BadRequestException('Invalid license key');
        }
        const licenseData = { ...dto, activatedAt: new Date() };
        await this.systemMetadataRepository.set(enum_1.SystemMetadataKey.License, licenseData);
        return licenseData;
    }
};
exports.ServerService = ServerService;
__decorate([
    (0, decorators_1.OnEvent)({ name: 'AppBootstrap' }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", []),
    __metadata("design:returntype", Promise)
], ServerService.prototype, "onBootstrap", null);
exports.ServerService = ServerService = __decorate([
    (0, common_1.Injectable)()
], ServerService);
//# sourceMappingURL=server.service.js.map