Explorar o código

Send user agent

Manav Rathi hai 1 ano
pai
achega
cb86ab84f3

+ 4 - 3
web/apps/photos/src/services/face/face.worker.ts

@@ -12,15 +12,16 @@ export class DedicatedMLWorker {
     public async syncLocalFile(
         token: string,
         userID: number,
+        userAgent: string,
         enteFile: EnteFile,
         localFile: globalThis.File,
     ) {
-        mlService.syncLocalFile(token, userID, enteFile, localFile);
+        mlService.syncLocalFile(token, userID, userAgent, enteFile, localFile);
     }
 
-    public async sync(token: string, userID: number) {
+    public async sync(token: string, userID: number, userAgent: string) {
         await downloadManager.init(APPS.PHOTOS, { token });
-        return mlService.sync(token, userID);
+        return mlService.sync(token, userID, userAgent);
     }
 }
 

+ 7 - 8
web/apps/photos/src/services/face/remote.ts

@@ -8,8 +8,9 @@ import type { Face, FaceDetection, MlFileData } from "./types";
 export const putFaceEmbedding = async (
     enteFile: EnteFile,
     mlFileData: MlFileData,
+    userAgent: string,
 ) => {
-    const serverMl = LocalFileMlDataToServerFileMl(mlFileData);
+    const serverMl = LocalFileMlDataToServerFileMl(mlFileData, userAgent);
     log.debug(() => ({ t: "Local ML file data", mlFileData }));
     log.debug(() => ({
         t: "Uploaded ML file data",
@@ -57,13 +58,11 @@ class ServerFileMl {
 class ServerFaceEmbeddings {
     public faces: ServerFace[];
     public version: number;
-    /* TODO
-    public client?: string;
-    public error?: boolean;
-    */
+    public client: string;
 
-    public constructor(faces: ServerFace[], version: number) {
+    public constructor(faces: ServerFace[], client: string, version: number) {
         this.faces = faces;
+        this.client = client;
         this.version = version;
     }
 }
@@ -121,6 +120,7 @@ class ServerFaceBox {
 
 function LocalFileMlDataToServerFileMl(
     localFileMlData: MlFileData,
+    userAgent: string,
 ): ServerFileMl {
     if (localFileMlData.errorCount > 0) {
         return null;
@@ -139,7 +139,6 @@ function LocalFileMlDataToServerFileMl(
         const landmarks = detection.landmarks;
         const newBox = new ServerFaceBox(box.x, box.y, box.width, box.height);
 
-        // TODO-ML: Add client UA and version
         const newFaceObject = new ServerFace(
             faceID,
             Array.from(embedding),
@@ -149,7 +148,7 @@ function LocalFileMlDataToServerFileMl(
         );
         faces.push(newFaceObject);
     }
-    const faceEmbeddings = new ServerFaceEmbeddings(faces, 1);
+    const faceEmbeddings = new ServerFaceEmbeddings(faces, userAgent, 1);
     return new ServerFileMl(
         localFileMlData.fileId,
         faceEmbeddings,

+ 38 - 11
web/apps/photos/src/services/machineLearning/machineLearningService.ts

@@ -44,6 +44,7 @@ export async function updateMLSearchConfig(newConfig: MLSearchConfig) {
 class MLSyncContext {
     public token: string;
     public userID: number;
+    public userAgent: string;
 
     public localFilesMap: Map<number, EnteFile>;
     public outOfSyncFiles: EnteFile[];
@@ -52,9 +53,10 @@ class MLSyncContext {
 
     public syncQueue: PQueue;
 
-    constructor(token: string, userID: number) {
+    constructor(token: string, userID: number, userAgent: string) {
         this.token = token;
         this.userID = userID;
+        this.userAgent = userAgent;
 
         this.outOfSyncFiles = [];
         this.nSyncedFiles = 0;
@@ -77,12 +79,16 @@ class MachineLearningService {
     private localSyncContext: Promise<MLSyncContext>;
     private syncContext: Promise<MLSyncContext>;
 
-    public async sync(token: string, userID: number): Promise<boolean> {
+    public async sync(
+        token: string,
+        userID: number,
+        userAgent: string,
+    ): Promise<boolean> {
         if (!token) {
             throw Error("Token needed by ml service to sync file");
         }
 
-        const syncContext = await this.getSyncContext(token, userID);
+        const syncContext = await this.getSyncContext(token, userID, userAgent);
 
         await this.syncLocalFiles(syncContext);
 
@@ -214,13 +220,17 @@ class MachineLearningService {
         // await this.disposeMLModels();
     }
 
-    private async getSyncContext(token: string, userID: number) {
+    private async getSyncContext(
+        token: string,
+        userID: number,
+        userAgent: string,
+    ) {
         if (!this.syncContext) {
             log.info("Creating syncContext");
 
             // TODO-ML(MR): Keep as promise for now.
             this.syncContext = new Promise((resolve) => {
-                resolve(new MLSyncContext(token, userID));
+                resolve(new MLSyncContext(token, userID, userAgent));
             });
         } else {
             log.info("reusing existing syncContext");
@@ -228,13 +238,17 @@ class MachineLearningService {
         return this.syncContext;
     }
 
-    private async getLocalSyncContext(token: string, userID: number) {
+    private async getLocalSyncContext(
+        token: string,
+        userID: number,
+        userAgent: string,
+    ) {
         // TODO-ML(MR): This is updating the file ML version. verify.
         if (!this.localSyncContext) {
             log.info("Creating localSyncContext");
             // TODO-ML(MR):
             this.localSyncContext = new Promise((resolve) => {
-                resolve(new MLSyncContext(token, userID));
+                resolve(new MLSyncContext(token, userID, userAgent));
             });
         } else {
             log.info("reusing existing localSyncContext");
@@ -254,10 +268,15 @@ class MachineLearningService {
     public async syncLocalFile(
         token: string,
         userID: number,
+        userAgent: string,
         enteFile: EnteFile,
         localFile?: globalThis.File,
     ) {
-        const syncContext = await this.getLocalSyncContext(token, userID);
+        const syncContext = await this.getLocalSyncContext(
+            token,
+            userID,
+            userAgent,
+        );
 
         try {
             await this.syncFileWithErrorHandler(
@@ -281,7 +300,11 @@ class MachineLearningService {
         localFile?: globalThis.File,
     ) {
         try {
-            const mlFileData = await this.syncFile(enteFile, localFile);
+            const mlFileData = await this.syncFile(
+                enteFile,
+                localFile,
+                syncContext.userAgent,
+            );
             syncContext.nSyncedFiles += 1;
             return mlFileData;
         } catch (e) {
@@ -313,14 +336,18 @@ class MachineLearningService {
         }
     }
 
-    private async syncFile(enteFile: EnteFile, localFile?: globalThis.File) {
+    private async syncFile(
+        enteFile: EnteFile,
+        localFile: globalThis.File | undefined,
+        userAgent: string,
+    ) {
         const oldMlFile = await mlIDbStorage.getFile(enteFile.id);
         if (oldMlFile && oldMlFile.mlVersion) {
             return oldMlFile;
         }
 
         const newMlFile = await indexFaces(enteFile, localFile);
-        await putFaceEmbedding(enteFile, newMlFile);
+        await putFaceEmbedding(enteFile, newMlFile, userAgent);
         await mlIDbStorage.putFile(newMlFile);
         return newMlFile;
     }

+ 19 - 2
web/apps/photos/src/services/machineLearning/mlWorkManager.ts

@@ -1,6 +1,8 @@
 import { FILE_TYPE } from "@/media/file-type";
+import { ensureElectron } from "@/next/electron";
 import log from "@/next/log";
 import { ComlinkWorker } from "@/next/worker/comlink-worker";
+import { clientPackageNamePhotosDesktop } from "@ente/shared/apps/constants";
 import { eventBus, Events } from "@ente/shared/events";
 import { getToken, getUserID } from "@ente/shared/storage/localStorage/helpers";
 import debounce from "debounce";
@@ -227,8 +229,15 @@ class MLWorkManager {
             this.stopSyncJob();
             const token = getToken();
             const userID = getUserID();
+            const userAgent = await getUserAgent();
             const mlWorker = await this.getLiveSyncWorker();
-            return mlWorker.syncLocalFile(token, userID, enteFile, localFile);
+            return mlWorker.syncLocalFile(
+                token,
+                userID,
+                userAgent,
+                enteFile,
+                localFile,
+            );
         });
     }
 
@@ -266,9 +275,10 @@ class MLWorkManager {
 
             const token = getToken();
             const userID = getUserID();
+            const userAgent = await getUserAgent();
             const jobWorkerProxy = await this.getSyncJobWorker();
 
-            return await jobWorkerProxy.sync(token, userID);
+            return await jobWorkerProxy.sync(token, userID, userAgent);
             // this.terminateSyncJobWorker();
             // TODO: redirect/refresh to gallery in case of session_expired, stop ml sync job
         } catch (e) {
@@ -320,3 +330,10 @@ export function logQueueStats(queue: PQueue, name: string) {
         console.error(`queuestats: ${name}: Error, `, error),
     );
 }
+
+const getUserAgent = async () => {
+    const electron = ensureElectron();
+    const name = clientPackageNamePhotosDesktop;
+    const version = await electron.appVersion();
+    return `${name}/${version}`;
+};

+ 2 - 0
web/packages/shared/apps/constants.ts

@@ -14,6 +14,8 @@ export const CLIENT_PACKAGE_NAMES = new Map([
     [APPS.ACCOUNTS, "io.ente.accounts.web"],
 ]);
 
+export const clientPackageNamePhotosDesktop = "io.ente.photos.desktop";
+
 export const APP_TITLES = new Map([
     [APPS.ALBUMS, "Ente Albums"],
     [APPS.PHOTOS, "Ente Photos"],