import 'dart:convert'; import 'package:logging/logging.dart'; import 'package:nc_photos/entity/face_recognition_face.dart'; import 'package:nc_photos/entity/face_recognition_person.dart'; import 'package:nc_photos/entity/favorite.dart'; import 'package:nc_photos/entity/file.dart'; import 'package:nc_photos/entity/nc_album.dart'; import 'package:nc_photos/entity/nc_album_item.dart'; import 'package:nc_photos/entity/recognize_face.dart'; import 'package:nc_photos/entity/recognize_face_item.dart'; import 'package:nc_photos/entity/server_status.dart'; import 'package:nc_photos/entity/share.dart'; import 'package:nc_photos/entity/sharee.dart'; import 'package:nc_photos/entity/tag.dart'; import 'package:nc_photos/entity/tagged_file.dart'; import 'package:nc_photos/object_extension.dart'; import 'package:np_api/np_api.dart' as api; import 'package:np_codegen/np_codegen.dart'; import 'package:np_common/ci_string.dart'; import 'package:np_common/string_extension.dart'; part 'entity_converter.g.dart'; class ApiFaceRecognitionFaceConverter { static FaceRecognitionFace fromApi(api.FaceRecognitionFace face) { return FaceRecognitionFace( id: face.id, fileId: face.fileId, ); } } class ApiFaceRecognitionPersonConverter { static FaceRecognitionPerson fromApi(api.FaceRecognitionPerson person) { return FaceRecognitionPerson( name: person.name, thumbFaceId: person.thumbFaceId, count: person.count, ); } } class ApiFavoriteConverter { static Favorite fromApi(api.Favorite favorite) { return Favorite( fileId: favorite.fileId, ); } } class ApiFileConverter { static File fromApi(api.File file) { final metadata = file.customProperties?["com.nkming.nc_photos:metadata"] ?.run((obj) => Metadata.fromJson( jsonDecode(obj), upgraderV1: MetadataUpgraderV1( fileContentType: file.contentType, logFilePath: file.href, ), upgraderV2: MetadataUpgraderV2( fileContentType: file.contentType, logFilePath: file.href, ), upgraderV3: MetadataUpgraderV3( fileContentType: file.contentType, logFilePath: file.href, ), )); return File( path: _hrefToPath(file.href), contentLength: file.contentLength, contentType: file.contentType, etag: file.etag, lastModified: file.lastModified, isCollection: file.isCollection, hasPreview: file.hasPreview, fileId: file.fileId, isFavorite: file.favorite, ownerId: file.ownerId?.toCi(), ownerDisplayName: file.ownerDisplayName, trashbinFilename: file.trashbinFilename, trashbinOriginalLocation: file.trashbinOriginalLocation, trashbinDeletionTime: file.trashbinDeletionTime, metadata: metadata, isArchived: file.customProperties?["com.nkming.nc_photos:is-archived"] ?.run((obj) => obj == "true"), overrideDateTime: file .customProperties?["com.nkming.nc_photos:override-date-time"] ?.run((obj) => DateTime.parse(obj)), location: file.customProperties?["com.nkming.nc_photos:location"] ?.run((obj) => ImageLocation.fromJson(jsonDecode(obj))), ); } } class ApiNcAlbumConverter { static NcAlbum fromApi(api.NcAlbum album) { return NcAlbum( path: _hrefToPath(album.href), lastPhoto: (album.lastPhoto ?? -1) < 0 ? null : album.lastPhoto, nbItems: album.nbItems ?? 0, location: album.location, dateStart: (album.dateRange?["start"] as int?) ?.run((d) => DateTime.fromMillisecondsSinceEpoch(d * 1000)), dateEnd: (album.dateRange?["end"] as int?) ?.run((d) => DateTime.fromMillisecondsSinceEpoch(d * 1000)), collaborators: album.collaborators .map((c) => NcAlbumCollaborator( id: c.id.toCi(), label: c.label, type: c.type, )) .toList(), ); } } class ApiNcAlbumItemConverter { static NcAlbumItem fromApi(api.NcAlbumItem item) { return NcAlbumItem( path: _hrefToPath(item.href), fileId: item.fileId!, contentLength: item.contentLength, contentType: item.contentType, etag: item.etag, lastModified: item.lastModified, hasPreview: item.hasPreview, isFavorite: item.favorite, fileMetadataWidth: item.fileMetadataSize?["width"], fileMetadataHeight: item.fileMetadataSize?["height"], ); } } class ApiRecognizeFaceConverter { static RecognizeFace fromApi(api.RecognizeFace item) { // remote.php/dav/recognize/admin/faces/john var path = _hrefToPath(item.href); if (!path.startsWith("remote.php/dav/recognize/")) { throw ArgumentError("Invalid face path: ${item.href}"); } // admin/faces/john path = path.substring(25); final found = path.indexOf("/"); if (found == -1) { throw ArgumentError("Invalid face path: ${item.href}"); } // faces/john path = path.substring(found + 1); if (!path.startsWith("faces")) { throw ArgumentError("Invalid face path: ${item.href}"); } // john path = path.slice(6); return RecognizeFace(label: path); } } class ApiRecognizeFaceItemConverter { static RecognizeFaceItem fromApi(api.RecognizeFaceItem item) { return RecognizeFaceItem( path: _hrefToPath(item.href), fileId: item.fileId!, contentLength: item.contentLength, contentType: item.contentType, etag: item.etag, lastModified: item.lastModified, hasPreview: item.hasPreview, realPath: item.realPath, isFavorite: item.favorite, fileMetadataWidth: item.fileMetadataSize?["width"], fileMetadataHeight: item.fileMetadataSize?["height"], faceDetections: item.faceDetections?.isEmpty == true ? null : item.faceDetections, ); } } class ApiShareConverter { static Share fromApi(api.Share share) { final shareType = ShareTypeExtension.fromValue(share.shareType); final itemType = ShareItemTypeExtension.fromValue(share.itemType); return Share( id: share.id, shareType: shareType, stime: DateTime.fromMillisecondsSinceEpoch(share.stime * 1000), uidOwner: share.uidOwner.toCi(), displaynameOwner: share.displaynameOwner, uidFileOwner: share.uidFileOwner.toCi(), path: share.path, itemType: itemType, mimeType: share.mimeType, itemSource: share.itemSource, // when shared with a password protected link, shareWith somehow contains // the password, which doesn't make sense. We set it to null instead shareWith: shareType == ShareType.publicLink ? null : share.shareWith?.toCi(), shareWithDisplayName: share.shareWithDisplayName, url: share.url, ); } } class ApiShareeConverter { static Sharee fromApi(api.Sharee sharee) { return Sharee( type: _keyTypes[sharee.type]!, label: sharee.label, shareType: sharee.shareType, shareWith: sharee.shareWith.toCi(), shareWithDisplayNameUnique: sharee.shareWithDisplayNameUnique, ); } static const _keyTypes = { "users": ShareeType.user, "groups": ShareeType.group, "remotes": ShareeType.remote, "remote_groups": ShareeType.remoteGroup, "emails": ShareeType.email, "circles": ShareeType.circle, "rooms": ShareeType.room, "deck": ShareeType.deck, "lookup": ShareeType.lookup, }; } class ApiStatusConverter { static ServerStatus fromApi(api.Status status) { return ServerStatus( versionRaw: status.version, versionName: status.versionString, productName: status.productName, ); } } class ApiTagConverter { static Tag fromApi(api.Tag tag) { return Tag( id: tag.id, displayName: tag.displayName, userVisible: tag.userVisible, userAssignable: tag.userAssignable, ); } } class ApiTaggedFileConverter { static TaggedFile fromApi(api.TaggedFile taggedFile) { return TaggedFile( fileId: taggedFile.fileId, ); } } String _hrefToPath(String href) { final rawPath = href.trimAny("/"); final pos = rawPath.indexOf("remote.php"); if (pos == -1) { // what? _$_NpLog.log.warning("[_hrefToPath] Unknown href value: $rawPath"); return rawPath; } else { return rawPath.substring(pos); } } @npLog // ignore: camel_case_types class _ {}