update api

This commit is contained in:
mertalev 2025-06-16 13:23:00 -04:00
parent 1c53e65641
commit dd7c06f937
No known key found for this signature in database
GPG key ID: DF6ABC77AAD98C95
22 changed files with 177 additions and 863 deletions

View file

@ -194,7 +194,6 @@ Class | Method | HTTP request | Description
*SearchApi* | [**searchAssetStatistics**](doc//SearchApi.md#searchassetstatistics) | **POST** /search/statistics |
*SearchApi* | [**searchAssets**](doc//SearchApi.md#searchassets) | **POST** /search/metadata |
*SearchApi* | [**searchLargeAssets**](doc//SearchApi.md#searchlargeassets) | **POST** /search/large-assets |
*SearchApi* | [**searchOcr**](doc//SearchApi.md#searchocr) | **POST** /search/ocr |
*SearchApi* | [**searchPerson**](doc//SearchApi.md#searchperson) | **GET** /search/person |
*SearchApi* | [**searchPlaces**](doc//SearchApi.md#searchplaces) | **GET** /search/places |
*SearchApi* | [**searchRandom**](doc//SearchApi.md#searchrandom) | **POST** /search/random |
@ -417,7 +416,6 @@ Class | Method | HTTP request | Description
- [OAuthConfigDto](doc//OAuthConfigDto.md)
- [OAuthTokenEndpointAuthMethod](doc//OAuthTokenEndpointAuthMethod.md)
- [OcrConfig](doc//OcrConfig.md)
- [OcrSearchDto](doc//OcrSearchDto.md)
- [OnThisDayDto](doc//OnThisDayDto.md)
- [OnboardingDto](doc//OnboardingDto.md)
- [OnboardingResponseDto](doc//OnboardingResponseDto.md)

View file

@ -188,7 +188,6 @@ part 'model/o_auth_callback_dto.dart';
part 'model/o_auth_config_dto.dart';
part 'model/o_auth_token_endpoint_auth_method.dart';
part 'model/ocr_config.dart';
part 'model/ocr_search_dto.dart';
part 'model/on_this_day_dto.dart';
part 'model/onboarding_dto.dart';
part 'model/onboarding_response_dto.dart';

View file

@ -346,6 +346,8 @@ class SearchApi {
///
/// * [String] model:
///
/// * [String] ocr:
///
/// * [List<String>] personIds:
///
/// * [num] rating:
@ -375,7 +377,7 @@ class SearchApi {
/// * [bool] withDeleted:
///
/// * [bool] withExif:
Future<Response> searchLargeAssetsWithHttpInfo({ List<String>? albumIds, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceId, bool? isEncoded, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, String? lensModel, String? libraryId, String? make, int? minFileSize, String? model, List<String>? personIds, num? rating, num? size, String? state, List<String>? tagIds, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, AssetVisibility? visibility, bool? withDeleted, bool? withExif, }) async {
Future<Response> searchLargeAssetsWithHttpInfo({ List<String>? albumIds, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceId, bool? isEncoded, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, String? lensModel, String? libraryId, String? make, int? minFileSize, String? model, String? ocr, List<String>? personIds, num? rating, num? size, String? state, List<String>? tagIds, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, AssetVisibility? visibility, bool? withDeleted, bool? withExif, }) async {
// ignore: prefer_const_declarations
final apiPath = r'/search/large-assets';
@ -434,6 +436,9 @@ class SearchApi {
if (model != null) {
queryParams.addAll(_queryParams('', 'model', model));
}
if (ocr != null) {
queryParams.addAll(_queryParams('', 'ocr', ocr));
}
if (personIds != null) {
queryParams.addAll(_queryParams('multi', 'personIds', personIds));
}
@ -530,6 +535,8 @@ class SearchApi {
///
/// * [String] model:
///
/// * [String] ocr:
///
/// * [List<String>] personIds:
///
/// * [num] rating:
@ -559,8 +566,8 @@ class SearchApi {
/// * [bool] withDeleted:
///
/// * [bool] withExif:
Future<List<AssetResponseDto>?> searchLargeAssets({ List<String>? albumIds, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceId, bool? isEncoded, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, String? lensModel, String? libraryId, String? make, int? minFileSize, String? model, List<String>? personIds, num? rating, num? size, String? state, List<String>? tagIds, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, AssetVisibility? visibility, bool? withDeleted, bool? withExif, }) async {
final response = await searchLargeAssetsWithHttpInfo( albumIds: albumIds, city: city, country: country, createdAfter: createdAfter, createdBefore: createdBefore, deviceId: deviceId, isEncoded: isEncoded, isFavorite: isFavorite, isMotion: isMotion, isNotInAlbum: isNotInAlbum, isOffline: isOffline, lensModel: lensModel, libraryId: libraryId, make: make, minFileSize: minFileSize, model: model, personIds: personIds, rating: rating, size: size, state: state, tagIds: tagIds, takenAfter: takenAfter, takenBefore: takenBefore, trashedAfter: trashedAfter, trashedBefore: trashedBefore, type: type, updatedAfter: updatedAfter, updatedBefore: updatedBefore, visibility: visibility, withDeleted: withDeleted, withExif: withExif, );
Future<List<AssetResponseDto>?> searchLargeAssets({ List<String>? albumIds, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceId, bool? isEncoded, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, String? lensModel, String? libraryId, String? make, int? minFileSize, String? model, String? ocr, List<String>? personIds, num? rating, num? size, String? state, List<String>? tagIds, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, AssetVisibility? visibility, bool? withDeleted, bool? withExif, }) async {
final response = await searchLargeAssetsWithHttpInfo( albumIds: albumIds, city: city, country: country, createdAfter: createdAfter, createdBefore: createdBefore, deviceId: deviceId, isEncoded: isEncoded, isFavorite: isFavorite, isMotion: isMotion, isNotInAlbum: isNotInAlbum, isOffline: isOffline, lensModel: lensModel, libraryId: libraryId, make: make, minFileSize: minFileSize, model: model, ocr: ocr, personIds: personIds, rating: rating, size: size, state: state, tagIds: tagIds, takenAfter: takenAfter, takenBefore: takenBefore, trashedAfter: trashedAfter, trashedBefore: trashedBefore, type: type, updatedAfter: updatedAfter, updatedBefore: updatedBefore, visibility: visibility, withDeleted: withDeleted, withExif: withExif, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
@ -577,53 +584,6 @@ class SearchApi {
return null;
}
/// Performs an HTTP 'POST /search/ocr' operation and returns the [Response].
/// Parameters:
///
/// * [OcrSearchDto] ocrSearchDto (required):
Future<Response> searchOcrWithHttpInfo(OcrSearchDto ocrSearchDto,) async {
// ignore: prefer_const_declarations
final apiPath = r'/search/ocr';
// ignore: prefer_final_locals
Object? postBody = ocrSearchDto;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>['application/json'];
return apiClient.invokeAPI(
apiPath,
'POST',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Parameters:
///
/// * [OcrSearchDto] ocrSearchDto (required):
Future<SearchResponseDto?> searchOcr(OcrSearchDto ocrSearchDto,) async {
final response = await searchOcrWithHttpInfo(ocrSearchDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
// When a remote server returns no body with a status of 204, we shall not decode it.
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
// FormatException when trying to decode an empty string.
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'SearchResponseDto',) as SearchResponseDto;
}
return null;
}
/// This endpoint requires the `person.read` permission.
///
/// Note: This method returns the HTTP [Response].

View file

@ -430,8 +430,6 @@ class ApiClient {
return OAuthTokenEndpointAuthMethodTypeTransformer().decode(value);
case 'OcrConfig':
return OcrConfig.fromJson(value);
case 'OcrSearchDto':
return OcrSearchDto.fromJson(value);
case 'OnThisDayDto':
return OnThisDayDto.fromJson(value);
case 'OnboardingDto':

View file

@ -33,6 +33,7 @@ class MetadataSearchDto {
this.libraryId,
this.make,
this.model,
this.ocr,
this.order = AssetOrder.desc,
this.originalFileName,
this.originalPath,
@ -182,6 +183,14 @@ class MetadataSearchDto {
String? model;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? ocr;
AssetOrder order;
///
@ -369,6 +378,7 @@ class MetadataSearchDto {
other.libraryId == libraryId &&
other.make == make &&
other.model == model &&
other.ocr == ocr &&
other.order == order &&
other.originalFileName == originalFileName &&
other.originalPath == originalPath &&
@ -416,6 +426,7 @@ class MetadataSearchDto {
(libraryId == null ? 0 : libraryId!.hashCode) +
(make == null ? 0 : make!.hashCode) +
(model == null ? 0 : model!.hashCode) +
(ocr == null ? 0 : ocr!.hashCode) +
(order.hashCode) +
(originalFileName == null ? 0 : originalFileName!.hashCode) +
(originalPath == null ? 0 : originalPath!.hashCode) +
@ -441,7 +452,7 @@ class MetadataSearchDto {
(withStacked == null ? 0 : withStacked!.hashCode);
@override
String toString() => 'MetadataSearchDto[albumIds=$albumIds, checksum=$checksum, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, description=$description, deviceAssetId=$deviceAssetId, deviceId=$deviceId, encodedVideoPath=$encodedVideoPath, id=$id, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, order=$order, originalFileName=$originalFileName, originalPath=$originalPath, page=$page, personIds=$personIds, previewPath=$previewPath, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, thumbnailPath=$thumbnailPath, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
String toString() => 'MetadataSearchDto[albumIds=$albumIds, checksum=$checksum, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, description=$description, deviceAssetId=$deviceAssetId, deviceId=$deviceId, encodedVideoPath=$encodedVideoPath, id=$id, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, order=$order, originalFileName=$originalFileName, originalPath=$originalPath, page=$page, personIds=$personIds, previewPath=$previewPath, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, thumbnailPath=$thumbnailPath, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@ -540,6 +551,11 @@ class MetadataSearchDto {
json[r'model'] = this.model;
} else {
// json[r'model'] = null;
}
if (this.ocr != null) {
json[r'ocr'] = this.ocr;
} else {
// json[r'ocr'] = null;
}
json[r'order'] = this.order;
if (this.originalFileName != null) {
@ -682,6 +698,7 @@ class MetadataSearchDto {
libraryId: mapValueOfType<String>(json, r'libraryId'),
make: mapValueOfType<String>(json, r'make'),
model: mapValueOfType<String>(json, r'model'),
ocr: mapValueOfType<String>(json, r'ocr'),
order: AssetOrder.fromJson(json[r'order']) ?? AssetOrder.desc,
originalFileName: mapValueOfType<String>(json, r'originalFileName'),
originalPath: mapValueOfType<String>(json, r'originalPath'),

View file

@ -14,38 +14,53 @@ class OcrConfig {
/// Returns a new [OcrConfig] instance.
OcrConfig({
required this.enabled,
required this.minScore,
required this.maxResolution,
required this.minDetectionScore,
required this.minRecognitionScore,
required this.modelName,
});
bool enabled;
/// Minimum value: 1
int maxResolution;
/// Minimum value: 0.1
/// Maximum value: 1
double minScore;
double minDetectionScore;
/// Minimum value: 0.1
/// Maximum value: 1
double minRecognitionScore;
String modelName;
@override
bool operator ==(Object other) => identical(this, other) || other is OcrConfig &&
other.enabled == enabled &&
other.minScore == minScore &&
other.maxResolution == maxResolution &&
other.minDetectionScore == minDetectionScore &&
other.minRecognitionScore == minRecognitionScore &&
other.modelName == modelName;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(enabled.hashCode) +
(minScore.hashCode) +
(maxResolution.hashCode) +
(minDetectionScore.hashCode) +
(minRecognitionScore.hashCode) +
(modelName.hashCode);
@override
String toString() => 'OcrConfig[enabled=$enabled, minScore=$minScore, modelName=$modelName]';
String toString() => 'OcrConfig[enabled=$enabled, maxResolution=$maxResolution, minDetectionScore=$minDetectionScore, minRecognitionScore=$minRecognitionScore, modelName=$modelName]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'enabled'] = this.enabled;
json[r'minScore'] = this.minScore;
json[r'maxResolution'] = this.maxResolution;
json[r'minDetectionScore'] = this.minDetectionScore;
json[r'minRecognitionScore'] = this.minRecognitionScore;
json[r'modelName'] = this.modelName;
return json;
}
@ -60,7 +75,9 @@ class OcrConfig {
return OcrConfig(
enabled: mapValueOfType<bool>(json, r'enabled')!,
minScore: (mapValueOfType<num>(json, r'minScore')!).toDouble(),
maxResolution: mapValueOfType<int>(json, r'maxResolution')!,
minDetectionScore: (mapValueOfType<num>(json, r'minDetectionScore')!).toDouble(),
minRecognitionScore: (mapValueOfType<num>(json, r'minRecognitionScore')!).toDouble(),
modelName: mapValueOfType<String>(json, r'modelName')!,
);
}
@ -110,7 +127,9 @@ class OcrConfig {
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'enabled',
'minScore',
'maxResolution',
'minDetectionScore',
'minRecognitionScore',
'modelName',
};
}

View file

@ -1,522 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class OcrSearchDto {
/// Returns a new [OcrSearchDto] instance.
OcrSearchDto({
this.albumIds = const [],
this.city,
this.country,
this.createdAfter,
this.createdBefore,
this.deviceId,
this.isEncoded,
this.isFavorite,
this.isMotion,
this.isNotInAlbum,
this.isOffline,
this.lensModel,
this.libraryId,
this.make,
this.model,
required this.ocr,
this.page,
this.personIds = const [],
this.rating,
this.state,
this.tagIds = const [],
this.takenAfter,
this.takenBefore,
this.trashedAfter,
this.trashedBefore,
this.type,
this.updatedAfter,
this.updatedBefore,
this.visibility,
});
List<String> albumIds;
String? city;
String? country;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
DateTime? createdAfter;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
DateTime? createdBefore;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? deviceId;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
bool? isEncoded;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
bool? isFavorite;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
bool? isMotion;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
bool? isNotInAlbum;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
bool? isOffline;
String? lensModel;
String? libraryId;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? make;
String? model;
String ocr;
/// Minimum value: 1
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
num? page;
List<String> personIds;
/// Minimum value: -1
/// Maximum value: 5
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
num? rating;
String? state;
List<String>? tagIds;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
DateTime? takenAfter;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
DateTime? takenBefore;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
DateTime? trashedAfter;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
DateTime? trashedBefore;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
AssetTypeEnum? type;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
DateTime? updatedAfter;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
DateTime? updatedBefore;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
AssetVisibility? visibility;
@override
bool operator ==(Object other) => identical(this, other) || other is OcrSearchDto &&
_deepEquality.equals(other.albumIds, albumIds) &&
other.city == city &&
other.country == country &&
other.createdAfter == createdAfter &&
other.createdBefore == createdBefore &&
other.deviceId == deviceId &&
other.isEncoded == isEncoded &&
other.isFavorite == isFavorite &&
other.isMotion == isMotion &&
other.isNotInAlbum == isNotInAlbum &&
other.isOffline == isOffline &&
other.lensModel == lensModel &&
other.libraryId == libraryId &&
other.make == make &&
other.model == model &&
other.ocr == ocr &&
other.page == page &&
_deepEquality.equals(other.personIds, personIds) &&
other.rating == rating &&
other.state == state &&
_deepEquality.equals(other.tagIds, tagIds) &&
other.takenAfter == takenAfter &&
other.takenBefore == takenBefore &&
other.trashedAfter == trashedAfter &&
other.trashedBefore == trashedBefore &&
other.type == type &&
other.updatedAfter == updatedAfter &&
other.updatedBefore == updatedBefore &&
other.visibility == visibility;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(albumIds.hashCode) +
(city == null ? 0 : city!.hashCode) +
(country == null ? 0 : country!.hashCode) +
(createdAfter == null ? 0 : createdAfter!.hashCode) +
(createdBefore == null ? 0 : createdBefore!.hashCode) +
(deviceId == null ? 0 : deviceId!.hashCode) +
(isEncoded == null ? 0 : isEncoded!.hashCode) +
(isFavorite == null ? 0 : isFavorite!.hashCode) +
(isMotion == null ? 0 : isMotion!.hashCode) +
(isNotInAlbum == null ? 0 : isNotInAlbum!.hashCode) +
(isOffline == null ? 0 : isOffline!.hashCode) +
(lensModel == null ? 0 : lensModel!.hashCode) +
(libraryId == null ? 0 : libraryId!.hashCode) +
(make == null ? 0 : make!.hashCode) +
(model == null ? 0 : model!.hashCode) +
(ocr.hashCode) +
(page == null ? 0 : page!.hashCode) +
(personIds.hashCode) +
(rating == null ? 0 : rating!.hashCode) +
(state == null ? 0 : state!.hashCode) +
(tagIds == null ? 0 : tagIds!.hashCode) +
(takenAfter == null ? 0 : takenAfter!.hashCode) +
(takenBefore == null ? 0 : takenBefore!.hashCode) +
(trashedAfter == null ? 0 : trashedAfter!.hashCode) +
(trashedBefore == null ? 0 : trashedBefore!.hashCode) +
(type == null ? 0 : type!.hashCode) +
(updatedAfter == null ? 0 : updatedAfter!.hashCode) +
(updatedBefore == null ? 0 : updatedBefore!.hashCode) +
(visibility == null ? 0 : visibility!.hashCode);
@override
String toString() => 'OcrSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, page=$page, personIds=$personIds, rating=$rating, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'albumIds'] = this.albumIds;
if (this.city != null) {
json[r'city'] = this.city;
} else {
// json[r'city'] = null;
}
if (this.country != null) {
json[r'country'] = this.country;
} else {
// json[r'country'] = null;
}
if (this.createdAfter != null) {
json[r'createdAfter'] = this.createdAfter!.toUtc().toIso8601String();
} else {
// json[r'createdAfter'] = null;
}
if (this.createdBefore != null) {
json[r'createdBefore'] = this.createdBefore!.toUtc().toIso8601String();
} else {
// json[r'createdBefore'] = null;
}
if (this.deviceId != null) {
json[r'deviceId'] = this.deviceId;
} else {
// json[r'deviceId'] = null;
}
if (this.isEncoded != null) {
json[r'isEncoded'] = this.isEncoded;
} else {
// json[r'isEncoded'] = null;
}
if (this.isFavorite != null) {
json[r'isFavorite'] = this.isFavorite;
} else {
// json[r'isFavorite'] = null;
}
if (this.isMotion != null) {
json[r'isMotion'] = this.isMotion;
} else {
// json[r'isMotion'] = null;
}
if (this.isNotInAlbum != null) {
json[r'isNotInAlbum'] = this.isNotInAlbum;
} else {
// json[r'isNotInAlbum'] = null;
}
if (this.isOffline != null) {
json[r'isOffline'] = this.isOffline;
} else {
// json[r'isOffline'] = null;
}
if (this.lensModel != null) {
json[r'lensModel'] = this.lensModel;
} else {
// json[r'lensModel'] = null;
}
if (this.libraryId != null) {
json[r'libraryId'] = this.libraryId;
} else {
// json[r'libraryId'] = null;
}
if (this.make != null) {
json[r'make'] = this.make;
} else {
// json[r'make'] = null;
}
if (this.model != null) {
json[r'model'] = this.model;
} else {
// json[r'model'] = null;
}
json[r'ocr'] = this.ocr;
if (this.page != null) {
json[r'page'] = this.page;
} else {
// json[r'page'] = null;
}
json[r'personIds'] = this.personIds;
if (this.rating != null) {
json[r'rating'] = this.rating;
} else {
// json[r'rating'] = null;
}
if (this.state != null) {
json[r'state'] = this.state;
} else {
// json[r'state'] = null;
}
if (this.tagIds != null) {
json[r'tagIds'] = this.tagIds;
} else {
// json[r'tagIds'] = null;
}
if (this.takenAfter != null) {
json[r'takenAfter'] = this.takenAfter!.toUtc().toIso8601String();
} else {
// json[r'takenAfter'] = null;
}
if (this.takenBefore != null) {
json[r'takenBefore'] = this.takenBefore!.toUtc().toIso8601String();
} else {
// json[r'takenBefore'] = null;
}
if (this.trashedAfter != null) {
json[r'trashedAfter'] = this.trashedAfter!.toUtc().toIso8601String();
} else {
// json[r'trashedAfter'] = null;
}
if (this.trashedBefore != null) {
json[r'trashedBefore'] = this.trashedBefore!.toUtc().toIso8601String();
} else {
// json[r'trashedBefore'] = null;
}
if (this.type != null) {
json[r'type'] = this.type;
} else {
// json[r'type'] = null;
}
if (this.updatedAfter != null) {
json[r'updatedAfter'] = this.updatedAfter!.toUtc().toIso8601String();
} else {
// json[r'updatedAfter'] = null;
}
if (this.updatedBefore != null) {
json[r'updatedBefore'] = this.updatedBefore!.toUtc().toIso8601String();
} else {
// json[r'updatedBefore'] = null;
}
if (this.visibility != null) {
json[r'visibility'] = this.visibility;
} else {
// json[r'visibility'] = null;
}
return json;
}
/// Returns a new [OcrSearchDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static OcrSearchDto? fromJson(dynamic value) {
upgradeDto(value, "OcrSearchDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return OcrSearchDto(
albumIds: json[r'albumIds'] is Iterable
? (json[r'albumIds'] as Iterable).cast<String>().toList(growable: false)
: const [],
city: mapValueOfType<String>(json, r'city'),
country: mapValueOfType<String>(json, r'country'),
createdAfter: mapDateTime(json, r'createdAfter', r''),
createdBefore: mapDateTime(json, r'createdBefore', r''),
deviceId: mapValueOfType<String>(json, r'deviceId'),
isEncoded: mapValueOfType<bool>(json, r'isEncoded'),
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
isMotion: mapValueOfType<bool>(json, r'isMotion'),
isNotInAlbum: mapValueOfType<bool>(json, r'isNotInAlbum'),
isOffline: mapValueOfType<bool>(json, r'isOffline'),
lensModel: mapValueOfType<String>(json, r'lensModel'),
libraryId: mapValueOfType<String>(json, r'libraryId'),
make: mapValueOfType<String>(json, r'make'),
model: mapValueOfType<String>(json, r'model'),
ocr: mapValueOfType<String>(json, r'ocr')!,
page: num.parse('${json[r'page']}'),
personIds: json[r'personIds'] is Iterable
? (json[r'personIds'] as Iterable).cast<String>().toList(growable: false)
: const [],
rating: num.parse('${json[r'rating']}'),
state: mapValueOfType<String>(json, r'state'),
tagIds: json[r'tagIds'] is Iterable
? (json[r'tagIds'] as Iterable).cast<String>().toList(growable: false)
: const [],
takenAfter: mapDateTime(json, r'takenAfter', r''),
takenBefore: mapDateTime(json, r'takenBefore', r''),
trashedAfter: mapDateTime(json, r'trashedAfter', r''),
trashedBefore: mapDateTime(json, r'trashedBefore', r''),
type: AssetTypeEnum.fromJson(json[r'type']),
updatedAfter: mapDateTime(json, r'updatedAfter', r''),
updatedBefore: mapDateTime(json, r'updatedBefore', r''),
visibility: AssetVisibility.fromJson(json[r'visibility']),
);
}
return null;
}
static List<OcrSearchDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <OcrSearchDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = OcrSearchDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, OcrSearchDto> mapFromJson(dynamic json) {
final map = <String, OcrSearchDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = OcrSearchDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of OcrSearchDto-objects as value to a dart map
static Map<String, List<OcrSearchDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<OcrSearchDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = OcrSearchDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'ocr',
};
}

View file

@ -28,6 +28,7 @@ class RandomSearchDto {
this.libraryId,
this.make,
this.model,
this.ocr,
this.personIds = const [],
this.rating,
this.size,
@ -131,6 +132,14 @@ class RandomSearchDto {
String? model;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? ocr;
List<String> personIds;
/// Minimum value: -1
@ -270,6 +279,7 @@ class RandomSearchDto {
other.libraryId == libraryId &&
other.make == make &&
other.model == model &&
other.ocr == ocr &&
_deepEquality.equals(other.personIds, personIds) &&
other.rating == rating &&
other.size == size &&
@ -306,6 +316,7 @@ class RandomSearchDto {
(libraryId == null ? 0 : libraryId!.hashCode) +
(make == null ? 0 : make!.hashCode) +
(model == null ? 0 : model!.hashCode) +
(ocr == null ? 0 : ocr!.hashCode) +
(personIds.hashCode) +
(rating == null ? 0 : rating!.hashCode) +
(size == null ? 0 : size!.hashCode) +
@ -325,7 +336,7 @@ class RandomSearchDto {
(withStacked == null ? 0 : withStacked!.hashCode);
@override
String toString() => 'RandomSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, personIds=$personIds, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
String toString() => 'RandomSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, personIds=$personIds, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@ -399,6 +410,11 @@ class RandomSearchDto {
json[r'model'] = this.model;
} else {
// json[r'model'] = null;
}
if (this.ocr != null) {
json[r'ocr'] = this.ocr;
} else {
// json[r'ocr'] = null;
}
json[r'personIds'] = this.personIds;
if (this.rating != null) {
@ -510,6 +526,7 @@ class RandomSearchDto {
libraryId: mapValueOfType<String>(json, r'libraryId'),
make: mapValueOfType<String>(json, r'make'),
model: mapValueOfType<String>(json, r'model'),
ocr: mapValueOfType<String>(json, r'ocr'),
personIds: json[r'personIds'] is Iterable
? (json[r'personIds'] as Iterable).cast<String>().toList(growable: false)
: const [],

View file

@ -29,6 +29,7 @@ class SmartSearchDto {
this.libraryId,
this.make,
this.model,
this.ocr,
this.page,
this.personIds = const [],
this.query,
@ -141,6 +142,14 @@ class SmartSearchDto {
String? model;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? ocr;
/// Minimum value: 1
///
/// Please note: This property should have been non-nullable! Since the specification file
@ -290,6 +299,7 @@ class SmartSearchDto {
other.libraryId == libraryId &&
other.make == make &&
other.model == model &&
other.ocr == ocr &&
other.page == page &&
_deepEquality.equals(other.personIds, personIds) &&
other.query == query &&
@ -328,6 +338,7 @@ class SmartSearchDto {
(libraryId == null ? 0 : libraryId!.hashCode) +
(make == null ? 0 : make!.hashCode) +
(model == null ? 0 : model!.hashCode) +
(ocr == null ? 0 : ocr!.hashCode) +
(page == null ? 0 : page!.hashCode) +
(personIds.hashCode) +
(query == null ? 0 : query!.hashCode) +
@ -348,7 +359,7 @@ class SmartSearchDto {
(withExif == null ? 0 : withExif!.hashCode);
@override
String toString() => 'SmartSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, language=$language, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, page=$page, personIds=$personIds, query=$query, queryAssetId=$queryAssetId, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif]';
String toString() => 'SmartSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, language=$language, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, page=$page, personIds=$personIds, query=$query, queryAssetId=$queryAssetId, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@ -428,6 +439,11 @@ class SmartSearchDto {
} else {
// json[r'model'] = null;
}
if (this.ocr != null) {
json[r'ocr'] = this.ocr;
} else {
// json[r'ocr'] = null;
}
if (this.page != null) {
json[r'page'] = this.page;
} else {
@ -544,6 +560,7 @@ class SmartSearchDto {
libraryId: mapValueOfType<String>(json, r'libraryId'),
make: mapValueOfType<String>(json, r'make'),
model: mapValueOfType<String>(json, r'model'),
ocr: mapValueOfType<String>(json, r'ocr'),
page: num.parse('${json[r'page']}'),
personIds: json[r'personIds'] is Iterable
? (json[r'personIds'] as Iterable).cast<String>().toList(growable: false)

View file

@ -29,6 +29,7 @@ class StatisticsSearchDto {
this.libraryId,
this.make,
this.model,
this.ocr,
this.personIds = const [],
this.rating,
this.state,
@ -135,6 +136,14 @@ class StatisticsSearchDto {
String? model;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
String? ocr;
List<String> personIds;
/// Minimum value: -1
@ -233,6 +242,7 @@ class StatisticsSearchDto {
other.libraryId == libraryId &&
other.make == make &&
other.model == model &&
other.ocr == ocr &&
_deepEquality.equals(other.personIds, personIds) &&
other.rating == rating &&
other.state == state &&
@ -265,6 +275,7 @@ class StatisticsSearchDto {
(libraryId == null ? 0 : libraryId!.hashCode) +
(make == null ? 0 : make!.hashCode) +
(model == null ? 0 : model!.hashCode) +
(ocr == null ? 0 : ocr!.hashCode) +
(personIds.hashCode) +
(rating == null ? 0 : rating!.hashCode) +
(state == null ? 0 : state!.hashCode) +
@ -279,7 +290,7 @@ class StatisticsSearchDto {
(visibility == null ? 0 : visibility!.hashCode);
@override
String toString() => 'StatisticsSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, description=$description, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, personIds=$personIds, rating=$rating, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility]';
String toString() => 'StatisticsSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, description=$description, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, personIds=$personIds, rating=$rating, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@ -358,6 +369,11 @@ class StatisticsSearchDto {
json[r'model'] = this.model;
} else {
// json[r'model'] = null;
}
if (this.ocr != null) {
json[r'ocr'] = this.ocr;
} else {
// json[r'ocr'] = null;
}
json[r'personIds'] = this.personIds;
if (this.rating != null) {
@ -445,6 +461,7 @@ class StatisticsSearchDto {
libraryId: mapValueOfType<String>(json, r'libraryId'),
make: mapValueOfType<String>(json, r'make'),
model: mapValueOfType<String>(json, r'model'),
ocr: mapValueOfType<String>(json, r'ocr'),
personIds: json[r'personIds'] is Iterable
? (json[r'personIds'] as Iterable).cast<String>().toList(growable: false)
: const [],

View file

@ -5933,6 +5933,14 @@
"type": "string"
}
},
{
"name": "ocr",
"required": false,
"in": "query",
"schema": {
"type": "string"
}
},
{
"name": "personIds",
"required": false,
@ -6151,48 +6159,6 @@
"description": "This endpoint requires the `asset.read` permission."
}
},
"/search/ocr": {
"post": {
"operationId": "searchOcr",
"parameters": [],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OcrSearchDto"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SearchResponseDto"
}
}
},
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Search"
]
}
},
"/search/person": {
"get": {
"operationId": "searchPerson",
@ -12604,6 +12570,9 @@
"nullable": true,
"type": "string"
},
"ocr": {
"type": "string"
},
"order": {
"allOf": [
{
@ -12918,176 +12887,32 @@
"enabled": {
"type": "boolean"
},
"minDetectionBoxScore": {
"format": "double",
"maximum": 1,
"minimum": 0,
"type": "number"
"maxResolution": {
"minimum": 1,
"type": "integer"
},
"minDetectionScore": {
"format": "double",
"maximum": 1,
"minimum": 0,
"minimum": 0.1,
"type": "number"
},
"minRecognitionScore": {
"format": "double",
"maximum": 1,
"minimum": 0,
"minimum": 0.1,
"type": "number"
},
"modelName": {
"type": "string"
},
"orientationClassifyEnabled": {
"type": "boolean"
},
"unwarpingEnabled": {
"type": "boolean"
}
},
"required": [
"enabled",
"minDetectionBoxScore",
"maxResolution",
"minDetectionScore",
"minRecognitionScore",
"modelName",
"orientationClassifyEnabled",
"unwarpingEnabled"
],
"type": "object"
},
"OcrSearchDto": {
"properties": {
"albumIds": {
"items": {
"format": "uuid",
"type": "string"
},
"type": "array"
},
"city": {
"nullable": true,
"type": "string"
},
"country": {
"nullable": true,
"type": "string"
},
"createdAfter": {
"format": "date-time",
"type": "string"
},
"createdBefore": {
"format": "date-time",
"type": "string"
},
"deviceId": {
"type": "string"
},
"isEncoded": {
"type": "boolean"
},
"isFavorite": {
"type": "boolean"
},
"isMotion": {
"type": "boolean"
},
"isNotInAlbum": {
"type": "boolean"
},
"isOffline": {
"type": "boolean"
},
"lensModel": {
"nullable": true,
"type": "string"
},
"libraryId": {
"format": "uuid",
"nullable": true,
"type": "string"
},
"make": {
"type": "string"
},
"model": {
"nullable": true,
"type": "string"
},
"ocr": {
"type": "string"
},
"page": {
"minimum": 1,
"type": "number"
},
"personIds": {
"items": {
"format": "uuid",
"type": "string"
},
"type": "array"
},
"rating": {
"maximum": 5,
"minimum": -1,
"type": "number"
},
"state": {
"nullable": true,
"type": "string"
},
"tagIds": {
"items": {
"format": "uuid",
"type": "string"
},
"nullable": true,
"type": "array"
},
"takenAfter": {
"format": "date-time",
"type": "string"
},
"takenBefore": {
"format": "date-time",
"type": "string"
},
"trashedAfter": {
"format": "date-time",
"type": "string"
},
"trashedBefore": {
"format": "date-time",
"type": "string"
},
"type": {
"allOf": [
{
"$ref": "#/components/schemas/AssetTypeEnum"
}
]
},
"updatedAfter": {
"format": "date-time",
"type": "string"
},
"updatedBefore": {
"format": "date-time",
"type": "string"
},
"visibility": {
"allOf": [
{
"$ref": "#/components/schemas/AssetVisibility"
}
]
}
},
"required": [
"ocr"
"modelName"
],
"type": "object"
},
@ -13760,6 +13585,9 @@
"nullable": true,
"type": "string"
},
"ocr": {
"type": "string"
},
"personIds": {
"items": {
"format": "uuid",
@ -14856,6 +14684,9 @@
"nullable": true,
"type": "string"
},
"ocr": {
"type": "string"
},
"page": {
"minimum": 1,
"type": "number"
@ -15061,6 +14892,9 @@
"nullable": true,
"type": "string"
},
"ocr": {
"type": "string"
},
"personIds": {
"items": {
"format": "uuid",

View file

@ -909,6 +909,7 @@ export type MetadataSearchDto = {
libraryId?: string | null;
make?: string;
model?: string | null;
ocr?: string;
order?: AssetOrder;
originalFileName?: string;
originalPath?: string;
@ -958,37 +959,6 @@ export type SearchResponseDto = {
albums: SearchAlbumResponseDto;
assets: SearchAssetResponseDto;
};
export type OcrSearchDto = {
albumIds?: string[];
city?: string | null;
country?: string | null;
createdAfter?: string;
createdBefore?: string;
deviceId?: string;
isEncoded?: boolean;
isFavorite?: boolean;
isMotion?: boolean;
isNotInAlbum?: boolean;
isOffline?: boolean;
lensModel?: string | null;
libraryId?: string | null;
make?: string;
model?: string | null;
ocr: string;
page?: number;
personIds?: string[];
rating?: number;
state?: string | null;
tagIds?: string[] | null;
takenAfter?: string;
takenBefore?: string;
trashedAfter?: string;
trashedBefore?: string;
"type"?: AssetTypeEnum;
updatedAfter?: string;
updatedBefore?: string;
visibility?: AssetVisibility;
};
export type PlacesResponseDto = {
admin1name?: string;
admin2name?: string;
@ -1012,6 +982,7 @@ export type RandomSearchDto = {
libraryId?: string | null;
make?: string;
model?: string | null;
ocr?: string;
personIds?: string[];
rating?: number;
size?: number;
@ -1047,6 +1018,7 @@ export type SmartSearchDto = {
libraryId?: string | null;
make?: string;
model?: string | null;
ocr?: string;
page?: number;
personIds?: string[];
query?: string;
@ -1083,6 +1055,7 @@ export type StatisticsSearchDto = {
libraryId?: string | null;
make?: string;
model?: string | null;
ocr?: string;
personIds?: string[];
rating?: number;
state?: string | null;
@ -1434,7 +1407,9 @@ export type FacialRecognitionConfig = {
};
export type OcrConfig = {
enabled: boolean;
minScore: number;
maxResolution: number;
minDetectionScore: number;
minRecognitionScore: number;
modelName: string;
};
export type SystemConfigMachineLearningDto = {
@ -3409,7 +3384,7 @@ export function getExploreData(opts?: Oazapfts.RequestOpts) {
/**
* This endpoint requires the `asset.read` permission.
*/
export function searchLargeAssets({ albumIds, city, country, createdAfter, createdBefore, deviceId, isEncoded, isFavorite, isMotion, isNotInAlbum, isOffline, lensModel, libraryId, make, minFileSize, model, personIds, rating, size, state, tagIds, takenAfter, takenBefore, trashedAfter, trashedBefore, $type, updatedAfter, updatedBefore, visibility, withDeleted, withExif }: {
export function searchLargeAssets({ albumIds, city, country, createdAfter, createdBefore, deviceId, isEncoded, isFavorite, isMotion, isNotInAlbum, isOffline, lensModel, libraryId, make, minFileSize, model, ocr, personIds, rating, size, state, tagIds, takenAfter, takenBefore, trashedAfter, trashedBefore, $type, updatedAfter, updatedBefore, visibility, withDeleted, withExif }: {
albumIds?: string[];
city?: string | null;
country?: string | null;
@ -3426,6 +3401,7 @@ export function searchLargeAssets({ albumIds, city, country, createdAfter, creat
make?: string;
minFileSize?: number;
model?: string | null;
ocr?: string;
personIds?: string[];
rating?: number;
size?: number;
@ -3462,6 +3438,7 @@ export function searchLargeAssets({ albumIds, city, country, createdAfter, creat
make,
minFileSize,
model,
ocr,
personIds,
rating,
size,
@ -3497,18 +3474,6 @@ export function searchAssets({ metadataSearchDto }: {
body: metadataSearchDto
})));
}
export function searchOcr({ ocrSearchDto }: {
ocrSearchDto: OcrSearchDto;
}, opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;
data: SearchResponseDto;
}>("/search/ocr", oazapfts.json({
...opts,
method: "POST",
body: ocrSearchDto
})));
}
/**
* This endpoint requires the `person.read` permission.
*/

View file

@ -253,8 +253,8 @@ export const defaults = Object.freeze<SystemConfig>({
ocr: {
enabled: true,
modelName: 'PP-OCRv5_server',
minDetectionScore: 0.3,
minRecognitionScore: 0.0,
minDetectionScore: 0.5,
minRecognitionScore: 0.5,
maxResolution: 1440,
},
},

View file

@ -101,6 +101,11 @@ class BaseSearchDto {
@Max(5)
@Min(-1)
rating?: number;
@IsString()
@IsNotEmpty()
@Optional()
ocr?: string;
}
class BaseSearchWithResultsDto extends BaseSearchDto {
@ -218,18 +223,6 @@ export class SmartSearchDto extends BaseSearchWithResultsDto {
page?: number;
}
export class OcrSearchDto extends BaseSearchDto {
@IsString()
@IsNotEmpty()
ocr!: string;
@IsInt()
@Min(1)
@Type(() => Number)
@Optional()
page?: number;
}
export class SearchPlacesDto {
@IsString()
@IsNotEmpty()

View file

@ -196,9 +196,9 @@ export class AssetJobRepository {
@GenerateSql({ params: [DummyValue.UUID] })
getForOcr(id: string) {
return this.db
.selectFrom('assets')
.select((eb) => ['assets.visibility', withFile(eb, AssetFileType.PREVIEW).as('previewFile')])
.where('assets.id', '=', id)
.selectFrom('asset')
.select((eb) => ['asset.visibility', withFile(eb, AssetFileType.Preview).as('previewFile')])
.where('asset.id', '=', id)
.executeTakeFirst();
}
@ -361,15 +361,15 @@ export class AssetJobRepository {
@GenerateSql({ params: [], stream: true })
streamForOcrJob(force?: boolean) {
return this.db
.selectFrom('assets')
.select(['assets.id'])
.selectFrom('asset')
.select(['asset.id'])
.$if(!force, (qb) =>
qb
.innerJoin('asset_job_status', 'asset_job_status.assetId', 'assets.id')
.innerJoin('asset_job_status', 'asset_job_status.assetId', 'asset.id')
.where('asset_job_status.ocrAt', 'is', null),
)
.where('assets.deletedAt', 'is', null)
.where('assets.visibility', '!=', AssetVisibility.HIDDEN)
.where('asset.deletedAt', 'is', null)
.where('asset.visibility', '!=', AssetVisibility.Hidden)
.stream();
}

View file

@ -1,8 +1,9 @@
import { Injectable } from '@nestjs/common';
import { Insertable, Kysely, sql } from 'kysely';
import { InjectKysely } from 'nestjs-kysely';
import { AssetOcr, DB } from 'src/db';
import { DummyValue, GenerateSql } from 'src/decorators';
import { DB } from 'src/schema';
import { AssetOcrTable } from 'src/schema/tables/asset-ocr.table';
@Injectable()
export class OcrRepository {
@ -46,7 +47,7 @@ export class OcrRepository {
],
],
})
upsert(assetId: string, ocrDataList: Insertable<AssetOcr>[]) {
upsert(assetId: string, ocrDataList: Insertable<AssetOcrTable>[]) {
let query = this.db.with('deleted_ocr', (db) => db.deleteFrom('asset_ocr').where('assetId', '=', assetId));
if (ocrDataList.length > 0) {
const searchText = ocrDataList.map((item) => item.text.trim()).join(' ');

View file

@ -178,6 +178,8 @@ export interface DB {
asset_metadata: AssetMetadataTable;
asset_metadata_audit: AssetMetadataAuditTable;
asset_job_status: AssetJobStatusTable;
asset_ocr: AssetOcrTable;
ocr_search: OcrSearchTable;
audit: AuditTable;

View file

@ -1,10 +1,10 @@
import { AssetTable } from 'src/schema/tables/asset.table';
import { Column, ForeignKeyColumn, PrimaryGeneratedColumn, Table } from 'src/sql-tools';
import { Column, ForeignKeyColumn, Generated, PrimaryGeneratedColumn, Table } from 'src/sql-tools';
@Table('asset_ocr')
export class AssetOcrTable {
@PrimaryGeneratedColumn()
id!: string;
id!: Generated<string>;
@ForeignKeyColumn(() => AssetTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
assetId!: string;

View file

@ -308,7 +308,6 @@ export class JobService extends BaseService {
if (config.nightlyTasks.clusterNewFaces) {
jobs.push({ name: JobName.FacialRecognitionQueueAll, data: { force: false, nightly: true } });
{ name: JobName.QUEUE_OCR, data: { force: false, nightly: true } },
}
await this.jobRepository.queueAll(jobs);

View file

@ -13,7 +13,7 @@ export class OcrService extends BaseService {
async handleQueueOcr({ force, nightly }: JobOf<JobName.QUEUE_OCR>): Promise<JobStatus> {
const { machineLearning } = await this.getConfig({ withCache: false });
if (!isOcrEnabled(machineLearning)) {
return JobStatus.SKIPPED;
return JobStatus.Skipped;
}
if (force) {
@ -33,23 +33,23 @@ export class OcrService extends BaseService {
}
await this.jobRepository.queueAll(jobs);
return JobStatus.SUCCESS;
return JobStatus.Success;
}
@OnJob({ name: JobName.OCR, queue: QueueName.OCR })
async handleOcr({ id }: JobOf<JobName.OCR>): Promise<JobStatus> {
const { machineLearning } = await this.getConfig({ withCache: true });
if (!isOcrEnabled(machineLearning)) {
return JobStatus.SKIPPED;
return JobStatus.Skipped;
}
const asset = await this.assetJobRepository.getForOcr(id);
if (!asset || !asset.previewFile) {
return JobStatus.FAILED;
return JobStatus.Failed;
}
if (asset.visibility === AssetVisibility.HIDDEN) {
return JobStatus.SKIPPED;
if (asset.visibility === AssetVisibility.Hidden) {
return JobStatus.Skipped;
}
const ocrResults = await this.machineLearningRepository.ocr(
@ -63,7 +63,7 @@ export class OcrService extends BaseService {
await this.assetRepository.upsertJobStatus({ assetId: id, ocrAt: new Date() });
this.logger.debug(`Processed ${ocrResults.text.length} OCR result(s) for ${id}`);
return JobStatus.SUCCESS;
return JobStatus.Success;
}
parseOcrResults(id: string, ocrResults: OCR) {

View file

@ -390,7 +390,7 @@ export function searchAssetBuilder(kysely: Kysely<DB>, options: AssetSearchBuild
)
.$if(!!options.ocr, (qb) =>
qb
.innerJoin('ocr_search', 'assets.id', 'ocr_search.assetId')
.innerJoin('ocr_search', 'asset.id', 'ocr_search.assetId')
.where(() => sql`f_unaccent(ocr_search.text) %>> f_unaccent(${options.ocr!})`),
)
.$if(!!options.type, (qb) => qb.where('asset.type', '=', options.type!))

View file

@ -39,7 +39,7 @@
searchStore.isSearchEnabled = false;
});
const handleSearch = async (payload: SmartSearchDto | MetadataSearchDto | OcrSearchDto) => {
const handleSearch = async (payload: SmartSearchDto | MetadataSearchDto) => {
const params = getMetadataSearchQuery(payload);
closeDropdown();