mirror of
https://github.com/immich-app/immich.git
synced 2025-06-03 13:46:47 -04:00
feat(server): sort assets randomly from the API 'api/search/metadata' endpoint by including 'order': 'rand' in the API call. (#12741)
feat(server): search metadata random sort order Co-authored-by: Jason Rasmussen <jason@rasm.me>
This commit is contained in:
parent
a7719a94fc
commit
9f8a7e0bea
3
mobile/openapi/README.md
generated
3
mobile/openapi/README.md
generated
@ -116,6 +116,7 @@ Class | Method | HTTP request | Description
|
|||||||
*AuthenticationApi* | [**signUpAdmin**](doc//AuthenticationApi.md#signupadmin) | **POST** /auth/admin-sign-up |
|
*AuthenticationApi* | [**signUpAdmin**](doc//AuthenticationApi.md#signupadmin) | **POST** /auth/admin-sign-up |
|
||||||
*AuthenticationApi* | [**validateAccessToken**](doc//AuthenticationApi.md#validateaccesstoken) | **POST** /auth/validateToken |
|
*AuthenticationApi* | [**validateAccessToken**](doc//AuthenticationApi.md#validateaccesstoken) | **POST** /auth/validateToken |
|
||||||
*DeprecatedApi* | [**getPersonAssets**](doc//DeprecatedApi.md#getpersonassets) | **GET** /people/{id}/assets |
|
*DeprecatedApi* | [**getPersonAssets**](doc//DeprecatedApi.md#getpersonassets) | **GET** /people/{id}/assets |
|
||||||
|
*DeprecatedApi* | [**getRandom**](doc//DeprecatedApi.md#getrandom) | **GET** /assets/random |
|
||||||
*DownloadApi* | [**downloadArchive**](doc//DownloadApi.md#downloadarchive) | **POST** /download/archive |
|
*DownloadApi* | [**downloadArchive**](doc//DownloadApi.md#downloadarchive) | **POST** /download/archive |
|
||||||
*DownloadApi* | [**getDownloadInfo**](doc//DownloadApi.md#getdownloadinfo) | **POST** /download/info |
|
*DownloadApi* | [**getDownloadInfo**](doc//DownloadApi.md#getdownloadinfo) | **POST** /download/info |
|
||||||
*DuplicatesApi* | [**getAssetDuplicates**](doc//DuplicatesApi.md#getassetduplicates) | **GET** /duplicates |
|
*DuplicatesApi* | [**getAssetDuplicates**](doc//DuplicatesApi.md#getassetduplicates) | **GET** /duplicates |
|
||||||
@ -172,6 +173,7 @@ Class | Method | HTTP request | Description
|
|||||||
*SearchApi* | [**searchMetadata**](doc//SearchApi.md#searchmetadata) | **POST** /search/metadata |
|
*SearchApi* | [**searchMetadata**](doc//SearchApi.md#searchmetadata) | **POST** /search/metadata |
|
||||||
*SearchApi* | [**searchPerson**](doc//SearchApi.md#searchperson) | **GET** /search/person |
|
*SearchApi* | [**searchPerson**](doc//SearchApi.md#searchperson) | **GET** /search/person |
|
||||||
*SearchApi* | [**searchPlaces**](doc//SearchApi.md#searchplaces) | **GET** /search/places |
|
*SearchApi* | [**searchPlaces**](doc//SearchApi.md#searchplaces) | **GET** /search/places |
|
||||||
|
*SearchApi* | [**searchRandom**](doc//SearchApi.md#searchrandom) | **POST** /search/random |
|
||||||
*SearchApi* | [**searchSmart**](doc//SearchApi.md#searchsmart) | **POST** /search/smart |
|
*SearchApi* | [**searchSmart**](doc//SearchApi.md#searchsmart) | **POST** /search/smart |
|
||||||
*ServerApi* | [**deleteServerLicense**](doc//ServerApi.md#deleteserverlicense) | **DELETE** /server/license |
|
*ServerApi* | [**deleteServerLicense**](doc//ServerApi.md#deleteserverlicense) | **DELETE** /server/license |
|
||||||
*ServerApi* | [**getAboutInfo**](doc//ServerApi.md#getaboutinfo) | **GET** /server/about |
|
*ServerApi* | [**getAboutInfo**](doc//ServerApi.md#getaboutinfo) | **GET** /server/about |
|
||||||
@ -379,6 +381,7 @@ Class | Method | HTTP request | Description
|
|||||||
- [PurchaseResponse](doc//PurchaseResponse.md)
|
- [PurchaseResponse](doc//PurchaseResponse.md)
|
||||||
- [PurchaseUpdate](doc//PurchaseUpdate.md)
|
- [PurchaseUpdate](doc//PurchaseUpdate.md)
|
||||||
- [QueueStatusDto](doc//QueueStatusDto.md)
|
- [QueueStatusDto](doc//QueueStatusDto.md)
|
||||||
|
- [RandomSearchDto](doc//RandomSearchDto.md)
|
||||||
- [RatingsResponse](doc//RatingsResponse.md)
|
- [RatingsResponse](doc//RatingsResponse.md)
|
||||||
- [RatingsUpdate](doc//RatingsUpdate.md)
|
- [RatingsUpdate](doc//RatingsUpdate.md)
|
||||||
- [ReactionLevel](doc//ReactionLevel.md)
|
- [ReactionLevel](doc//ReactionLevel.md)
|
||||||
|
1
mobile/openapi/lib/api.dart
generated
1
mobile/openapi/lib/api.dart
generated
@ -192,6 +192,7 @@ part 'model/places_response_dto.dart';
|
|||||||
part 'model/purchase_response.dart';
|
part 'model/purchase_response.dart';
|
||||||
part 'model/purchase_update.dart';
|
part 'model/purchase_update.dart';
|
||||||
part 'model/queue_status_dto.dart';
|
part 'model/queue_status_dto.dart';
|
||||||
|
part 'model/random_search_dto.dart';
|
||||||
part 'model/ratings_response.dart';
|
part 'model/ratings_response.dart';
|
||||||
part 'model/ratings_update.dart';
|
part 'model/ratings_update.dart';
|
||||||
part 'model/reaction_level.dart';
|
part 'model/reaction_level.dart';
|
||||||
|
7
mobile/openapi/lib/api/assets_api.dart
generated
7
mobile/openapi/lib/api/assets_api.dart
generated
@ -449,7 +449,10 @@ class AssetsApi {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs an HTTP 'GET /assets/random' operation and returns the [Response].
|
/// This property was deprecated in v1.116.0
|
||||||
|
///
|
||||||
|
/// Note: This method returns the HTTP [Response].
|
||||||
|
///
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
///
|
///
|
||||||
/// * [num] count:
|
/// * [num] count:
|
||||||
@ -482,6 +485,8 @@ class AssetsApi {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This property was deprecated in v1.116.0
|
||||||
|
///
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
///
|
///
|
||||||
/// * [num] count:
|
/// * [num] count:
|
||||||
|
59
mobile/openapi/lib/api/deprecated_api.dart
generated
59
mobile/openapi/lib/api/deprecated_api.dart
generated
@ -71,4 +71,63 @@ class DeprecatedApi {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This property was deprecated in v1.116.0
|
||||||
|
///
|
||||||
|
/// Note: This method returns the HTTP [Response].
|
||||||
|
///
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [num] count:
|
||||||
|
Future<Response> getRandomWithHttpInfo({ num? count, }) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final path = r'/assets/random';
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
if (count != null) {
|
||||||
|
queryParams.addAll(_queryParams('', 'count', count));
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentTypes = <String>[];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
path,
|
||||||
|
'GET',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This property was deprecated in v1.116.0
|
||||||
|
///
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [num] count:
|
||||||
|
Future<List<AssetResponseDto>?> getRandom({ num? count, }) async {
|
||||||
|
final response = await getRandomWithHttpInfo( count: count, );
|
||||||
|
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) {
|
||||||
|
final responseBody = await _decodeBodyBytes(response);
|
||||||
|
return (await apiClient.deserializeAsync(responseBody, 'List<AssetResponseDto>') as List)
|
||||||
|
.cast<AssetResponseDto>()
|
||||||
|
.toList(growable: false);
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
47
mobile/openapi/lib/api/search_api.dart
generated
47
mobile/openapi/lib/api/search_api.dart
generated
@ -351,6 +351,53 @@ class SearchApi {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs an HTTP 'POST /search/random' operation and returns the [Response].
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [RandomSearchDto] randomSearchDto (required):
|
||||||
|
Future<Response> searchRandomWithHttpInfo(RandomSearchDto randomSearchDto,) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final path = r'/search/random';
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody = randomSearchDto;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>['application/json'];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
path,
|
||||||
|
'POST',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [RandomSearchDto] randomSearchDto (required):
|
||||||
|
Future<SearchResponseDto?> searchRandom(RandomSearchDto randomSearchDto,) async {
|
||||||
|
final response = await searchRandomWithHttpInfo(randomSearchDto,);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/// Performs an HTTP 'POST /search/smart' operation and returns the [Response].
|
/// Performs an HTTP 'POST /search/smart' operation and returns the [Response].
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
///
|
///
|
||||||
|
2
mobile/openapi/lib/api_client.dart
generated
2
mobile/openapi/lib/api_client.dart
generated
@ -439,6 +439,8 @@ class ApiClient {
|
|||||||
return PurchaseUpdate.fromJson(value);
|
return PurchaseUpdate.fromJson(value);
|
||||||
case 'QueueStatusDto':
|
case 'QueueStatusDto':
|
||||||
return QueueStatusDto.fromJson(value);
|
return QueueStatusDto.fromJson(value);
|
||||||
|
case 'RandomSearchDto':
|
||||||
|
return RandomSearchDto.fromJson(value);
|
||||||
case 'RatingsResponse':
|
case 'RatingsResponse':
|
||||||
return RatingsResponse.fromJson(value);
|
return RatingsResponse.fromJson(value);
|
||||||
case 'RatingsUpdate':
|
case 'RatingsUpdate':
|
||||||
|
583
mobile/openapi/lib/model/random_search_dto.dart
generated
Normal file
583
mobile/openapi/lib/model/random_search_dto.dart
generated
Normal file
@ -0,0 +1,583 @@
|
|||||||
|
//
|
||||||
|
// 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 RandomSearchDto {
|
||||||
|
/// Returns a new [RandomSearchDto] instance.
|
||||||
|
RandomSearchDto({
|
||||||
|
this.city,
|
||||||
|
this.country,
|
||||||
|
this.createdAfter,
|
||||||
|
this.createdBefore,
|
||||||
|
this.deviceId,
|
||||||
|
this.isArchived,
|
||||||
|
this.isEncoded,
|
||||||
|
this.isFavorite,
|
||||||
|
this.isMotion,
|
||||||
|
this.isNotInAlbum,
|
||||||
|
this.isOffline,
|
||||||
|
this.isVisible,
|
||||||
|
this.lensModel,
|
||||||
|
this.libraryId,
|
||||||
|
this.make,
|
||||||
|
this.model,
|
||||||
|
this.page,
|
||||||
|
this.personIds = const [],
|
||||||
|
this.size,
|
||||||
|
this.state,
|
||||||
|
this.takenAfter,
|
||||||
|
this.takenBefore,
|
||||||
|
this.trashedAfter,
|
||||||
|
this.trashedBefore,
|
||||||
|
this.type,
|
||||||
|
this.updatedAfter,
|
||||||
|
this.updatedBefore,
|
||||||
|
this.withArchived = false,
|
||||||
|
this.withDeleted,
|
||||||
|
this.withExif,
|
||||||
|
this.withPeople,
|
||||||
|
this.withStacked,
|
||||||
|
});
|
||||||
|
|
||||||
|
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? isArchived;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// 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;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// 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? isVisible;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/// 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: 1000
|
||||||
|
///
|
||||||
|
/// 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? size;
|
||||||
|
|
||||||
|
String? state;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// 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;
|
||||||
|
|
||||||
|
bool withArchived;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// 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? withDeleted;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// 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? withExif;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// 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? withPeople;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// 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? withStacked;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is RandomSearchDto &&
|
||||||
|
other.city == city &&
|
||||||
|
other.country == country &&
|
||||||
|
other.createdAfter == createdAfter &&
|
||||||
|
other.createdBefore == createdBefore &&
|
||||||
|
other.deviceId == deviceId &&
|
||||||
|
other.isArchived == isArchived &&
|
||||||
|
other.isEncoded == isEncoded &&
|
||||||
|
other.isFavorite == isFavorite &&
|
||||||
|
other.isMotion == isMotion &&
|
||||||
|
other.isNotInAlbum == isNotInAlbum &&
|
||||||
|
other.isOffline == isOffline &&
|
||||||
|
other.isVisible == isVisible &&
|
||||||
|
other.lensModel == lensModel &&
|
||||||
|
other.libraryId == libraryId &&
|
||||||
|
other.make == make &&
|
||||||
|
other.model == model &&
|
||||||
|
other.page == page &&
|
||||||
|
_deepEquality.equals(other.personIds, personIds) &&
|
||||||
|
other.size == size &&
|
||||||
|
other.state == state &&
|
||||||
|
other.takenAfter == takenAfter &&
|
||||||
|
other.takenBefore == takenBefore &&
|
||||||
|
other.trashedAfter == trashedAfter &&
|
||||||
|
other.trashedBefore == trashedBefore &&
|
||||||
|
other.type == type &&
|
||||||
|
other.updatedAfter == updatedAfter &&
|
||||||
|
other.updatedBefore == updatedBefore &&
|
||||||
|
other.withArchived == withArchived &&
|
||||||
|
other.withDeleted == withDeleted &&
|
||||||
|
other.withExif == withExif &&
|
||||||
|
other.withPeople == withPeople &&
|
||||||
|
other.withStacked == withStacked;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(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) +
|
||||||
|
(isArchived == null ? 0 : isArchived!.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) +
|
||||||
|
(isVisible == null ? 0 : isVisible!.hashCode) +
|
||||||
|
(lensModel == null ? 0 : lensModel!.hashCode) +
|
||||||
|
(libraryId == null ? 0 : libraryId!.hashCode) +
|
||||||
|
(make == null ? 0 : make!.hashCode) +
|
||||||
|
(model == null ? 0 : model!.hashCode) +
|
||||||
|
(page == null ? 0 : page!.hashCode) +
|
||||||
|
(personIds.hashCode) +
|
||||||
|
(size == null ? 0 : size!.hashCode) +
|
||||||
|
(state == null ? 0 : state!.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) +
|
||||||
|
(withArchived.hashCode) +
|
||||||
|
(withDeleted == null ? 0 : withDeleted!.hashCode) +
|
||||||
|
(withExif == null ? 0 : withExif!.hashCode) +
|
||||||
|
(withPeople == null ? 0 : withPeople!.hashCode) +
|
||||||
|
(withStacked == null ? 0 : withStacked!.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'RandomSearchDto[city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isArchived=$isArchived, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, page=$page, personIds=$personIds, size=$size, state=$state, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
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.isArchived != null) {
|
||||||
|
json[r'isArchived'] = this.isArchived;
|
||||||
|
} else {
|
||||||
|
// json[r'isArchived'] = 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.isVisible != null) {
|
||||||
|
json[r'isVisible'] = this.isVisible;
|
||||||
|
} else {
|
||||||
|
// json[r'isVisible'] = 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;
|
||||||
|
}
|
||||||
|
if (this.page != null) {
|
||||||
|
json[r'page'] = this.page;
|
||||||
|
} else {
|
||||||
|
// json[r'page'] = null;
|
||||||
|
}
|
||||||
|
json[r'personIds'] = this.personIds;
|
||||||
|
if (this.size != null) {
|
||||||
|
json[r'size'] = this.size;
|
||||||
|
} else {
|
||||||
|
// json[r'size'] = null;
|
||||||
|
}
|
||||||
|
if (this.state != null) {
|
||||||
|
json[r'state'] = this.state;
|
||||||
|
} else {
|
||||||
|
// json[r'state'] = 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;
|
||||||
|
}
|
||||||
|
json[r'withArchived'] = this.withArchived;
|
||||||
|
if (this.withDeleted != null) {
|
||||||
|
json[r'withDeleted'] = this.withDeleted;
|
||||||
|
} else {
|
||||||
|
// json[r'withDeleted'] = null;
|
||||||
|
}
|
||||||
|
if (this.withExif != null) {
|
||||||
|
json[r'withExif'] = this.withExif;
|
||||||
|
} else {
|
||||||
|
// json[r'withExif'] = null;
|
||||||
|
}
|
||||||
|
if (this.withPeople != null) {
|
||||||
|
json[r'withPeople'] = this.withPeople;
|
||||||
|
} else {
|
||||||
|
// json[r'withPeople'] = null;
|
||||||
|
}
|
||||||
|
if (this.withStacked != null) {
|
||||||
|
json[r'withStacked'] = this.withStacked;
|
||||||
|
} else {
|
||||||
|
// json[r'withStacked'] = null;
|
||||||
|
}
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [RandomSearchDto] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static RandomSearchDto? fromJson(dynamic value) {
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return RandomSearchDto(
|
||||||
|
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'),
|
||||||
|
isArchived: mapValueOfType<bool>(json, r'isArchived'),
|
||||||
|
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'),
|
||||||
|
isVisible: mapValueOfType<bool>(json, r'isVisible'),
|
||||||
|
lensModel: mapValueOfType<String>(json, r'lensModel'),
|
||||||
|
libraryId: mapValueOfType<String>(json, r'libraryId'),
|
||||||
|
make: mapValueOfType<String>(json, r'make'),
|
||||||
|
model: mapValueOfType<String>(json, r'model'),
|
||||||
|
page: num.parse('${json[r'page']}'),
|
||||||
|
personIds: json[r'personIds'] is Iterable
|
||||||
|
? (json[r'personIds'] as Iterable).cast<String>().toList(growable: false)
|
||||||
|
: const [],
|
||||||
|
size: num.parse('${json[r'size']}'),
|
||||||
|
state: mapValueOfType<String>(json, r'state'),
|
||||||
|
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''),
|
||||||
|
withArchived: mapValueOfType<bool>(json, r'withArchived') ?? false,
|
||||||
|
withDeleted: mapValueOfType<bool>(json, r'withDeleted'),
|
||||||
|
withExif: mapValueOfType<bool>(json, r'withExif'),
|
||||||
|
withPeople: mapValueOfType<bool>(json, r'withPeople'),
|
||||||
|
withStacked: mapValueOfType<bool>(json, r'withStacked'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<RandomSearchDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <RandomSearchDto>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = RandomSearchDto.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, RandomSearchDto> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, RandomSearchDto>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = RandomSearchDto.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of RandomSearchDto-objects as value to a dart map
|
||||||
|
static Map<String, List<RandomSearchDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<RandomSearchDto>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = RandomSearchDto.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1646,6 +1646,8 @@
|
|||||||
},
|
},
|
||||||
"/assets/random": {
|
"/assets/random": {
|
||||||
"get": {
|
"get": {
|
||||||
|
"deprecated": true,
|
||||||
|
"description": "This property was deprecated in v1.116.0",
|
||||||
"operationId": "getRandom",
|
"operationId": "getRandom",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
@ -1685,8 +1687,12 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"Assets"
|
"Assets",
|
||||||
]
|
"Deprecated"
|
||||||
|
],
|
||||||
|
"x-immich-lifecycle": {
|
||||||
|
"deprecatedAt": "v1.116.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/assets/statistics": {
|
"/assets/statistics": {
|
||||||
@ -4677,6 +4683,48 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/search/random": {
|
||||||
|
"post": {
|
||||||
|
"operationId": "searchRandom",
|
||||||
|
"parameters": [],
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/RandomSearchDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/SearchResponseDto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Search"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/search/smart": {
|
"/search/smart": {
|
||||||
"post": {
|
"post": {
|
||||||
"operationId": "searchSmart",
|
"operationId": "searchSmart",
|
||||||
@ -10454,6 +10502,130 @@
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"RandomSearchDto": {
|
||||||
|
"properties": {
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
"isArchived": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isEncoded": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isFavorite": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isMotion": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isNotInAlbum": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isOffline": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isVisible": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"lensModel": {
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"libraryId": {
|
||||||
|
"format": "uuid",
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"make": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"model": {
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"page": {
|
||||||
|
"minimum": 1,
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"personIds": {
|
||||||
|
"items": {
|
||||||
|
"format": "uuid",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"size": {
|
||||||
|
"maximum": 1000,
|
||||||
|
"minimum": 1,
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"nullable": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"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": {
|
||||||
|
"$ref": "#/components/schemas/AssetTypeEnum"
|
||||||
|
},
|
||||||
|
"updatedAfter": {
|
||||||
|
"format": "date-time",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"updatedBefore": {
|
||||||
|
"format": "date-time",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"withArchived": {
|
||||||
|
"default": false,
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"withDeleted": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"withExif": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"withPeople": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"withStacked": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"RatingsResponse": {
|
"RatingsResponse": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"enabled": {
|
"enabled": {
|
||||||
|
@ -837,6 +837,40 @@ export type PlacesResponseDto = {
|
|||||||
longitude: number;
|
longitude: number;
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
export type RandomSearchDto = {
|
||||||
|
city?: string | null;
|
||||||
|
country?: string | null;
|
||||||
|
createdAfter?: string;
|
||||||
|
createdBefore?: string;
|
||||||
|
deviceId?: string;
|
||||||
|
isArchived?: boolean;
|
||||||
|
isEncoded?: boolean;
|
||||||
|
isFavorite?: boolean;
|
||||||
|
isMotion?: boolean;
|
||||||
|
isNotInAlbum?: boolean;
|
||||||
|
isOffline?: boolean;
|
||||||
|
isVisible?: boolean;
|
||||||
|
lensModel?: string | null;
|
||||||
|
libraryId?: string | null;
|
||||||
|
make?: string;
|
||||||
|
model?: string | null;
|
||||||
|
page?: number;
|
||||||
|
personIds?: string[];
|
||||||
|
size?: number;
|
||||||
|
state?: string | null;
|
||||||
|
takenAfter?: string;
|
||||||
|
takenBefore?: string;
|
||||||
|
trashedAfter?: string;
|
||||||
|
trashedBefore?: string;
|
||||||
|
"type"?: AssetTypeEnum;
|
||||||
|
updatedAfter?: string;
|
||||||
|
updatedBefore?: string;
|
||||||
|
withArchived?: boolean;
|
||||||
|
withDeleted?: boolean;
|
||||||
|
withExif?: boolean;
|
||||||
|
withPeople?: boolean;
|
||||||
|
withStacked?: boolean;
|
||||||
|
};
|
||||||
export type SmartSearchDto = {
|
export type SmartSearchDto = {
|
||||||
city?: string | null;
|
city?: string | null;
|
||||||
country?: string | null;
|
country?: string | null;
|
||||||
@ -1696,6 +1730,9 @@ export function getMemoryLane({ day, month }: {
|
|||||||
...opts
|
...opts
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This property was deprecated in v1.116.0
|
||||||
|
*/
|
||||||
export function getRandom({ count }: {
|
export function getRandom({ count }: {
|
||||||
count?: number;
|
count?: number;
|
||||||
}, opts?: Oazapfts.RequestOpts) {
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
@ -2500,6 +2537,18 @@ export function searchPlaces({ name }: {
|
|||||||
...opts
|
...opts
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
export function searchRandom({ randomSearchDto }: {
|
||||||
|
randomSearchDto: RandomSearchDto;
|
||||||
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
|
status: 200;
|
||||||
|
data: SearchResponseDto;
|
||||||
|
}>("/search/random", oazapfts.json({
|
||||||
|
...opts,
|
||||||
|
method: "POST",
|
||||||
|
body: randomSearchDto
|
||||||
|
})));
|
||||||
|
}
|
||||||
export function searchSmart({ smartSearchDto }: {
|
export function searchSmart({ smartSearchDto }: {
|
||||||
smartSearchDto: SmartSearchDto;
|
smartSearchDto: SmartSearchDto;
|
||||||
}, opts?: Oazapfts.RequestOpts) {
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common';
|
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common';
|
||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
|
import { EndpointLifecycle } from 'src/decorators';
|
||||||
import { AssetResponseDto, MemoryLaneResponseDto } from 'src/dtos/asset-response.dto';
|
import { AssetResponseDto, MemoryLaneResponseDto } from 'src/dtos/asset-response.dto';
|
||||||
import {
|
import {
|
||||||
AssetBulkDeleteDto,
|
AssetBulkDeleteDto,
|
||||||
@ -31,6 +32,7 @@ export class AssetController {
|
|||||||
|
|
||||||
@Get('random')
|
@Get('random')
|
||||||
@Authenticated()
|
@Authenticated()
|
||||||
|
@EndpointLifecycle({ deprecatedAt: 'v1.116.0' })
|
||||||
getRandom(@Auth() auth: AuthDto, @Query() dto: RandomAssetsDto): Promise<AssetResponseDto[]> {
|
getRandom(@Auth() auth: AuthDto, @Query() dto: RandomAssetsDto): Promise<AssetResponseDto[]> {
|
||||||
return this.service.getRandom(auth, dto.count ?? 1);
|
return this.service.getRandom(auth, dto.count ?? 1);
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import { PersonResponseDto } from 'src/dtos/person.dto';
|
|||||||
import {
|
import {
|
||||||
MetadataSearchDto,
|
MetadataSearchDto,
|
||||||
PlacesResponseDto,
|
PlacesResponseDto,
|
||||||
|
RandomSearchDto,
|
||||||
SearchExploreResponseDto,
|
SearchExploreResponseDto,
|
||||||
SearchPeopleDto,
|
SearchPeopleDto,
|
||||||
SearchPlacesDto,
|
SearchPlacesDto,
|
||||||
@ -28,6 +29,13 @@ export class SearchController {
|
|||||||
return this.service.searchMetadata(auth, dto);
|
return this.service.searchMetadata(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('random')
|
||||||
|
@HttpCode(HttpStatus.OK)
|
||||||
|
@Authenticated()
|
||||||
|
searchRandom(@Auth() auth: AuthDto, @Body() dto: RandomSearchDto): Promise<SearchResponseDto> {
|
||||||
|
return this.service.searchRandom(auth, dto);
|
||||||
|
}
|
||||||
|
|
||||||
@Post('smart')
|
@Post('smart')
|
||||||
@HttpCode(HttpStatus.OK)
|
@HttpCode(HttpStatus.OK)
|
||||||
@Authenticated()
|
@Authenticated()
|
||||||
|
@ -119,7 +119,15 @@ class BaseSearchDto {
|
|||||||
personIds?: string[];
|
personIds?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MetadataSearchDto extends BaseSearchDto {
|
export class RandomSearchDto extends BaseSearchDto {
|
||||||
|
@ValidateBoolean({ optional: true })
|
||||||
|
withStacked?: boolean;
|
||||||
|
|
||||||
|
@ValidateBoolean({ optional: true })
|
||||||
|
withPeople?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MetadataSearchDto extends RandomSearchDto {
|
||||||
@ValidateUUID({ optional: true })
|
@ValidateUUID({ optional: true })
|
||||||
id?: string;
|
id?: string;
|
||||||
|
|
||||||
@ -133,12 +141,6 @@ export class MetadataSearchDto extends BaseSearchDto {
|
|||||||
@Optional()
|
@Optional()
|
||||||
checksum?: string;
|
checksum?: string;
|
||||||
|
|
||||||
@ValidateBoolean({ optional: true })
|
|
||||||
withStacked?: boolean;
|
|
||||||
|
|
||||||
@ValidateBoolean({ optional: true })
|
|
||||||
withPeople?: boolean;
|
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@Optional()
|
@Optional()
|
||||||
|
@ -116,6 +116,7 @@ export interface SearchPeopleOptions {
|
|||||||
|
|
||||||
export interface SearchOrderOptions {
|
export interface SearchOrderOptions {
|
||||||
orderDirection?: 'ASC' | 'DESC';
|
orderDirection?: 'ASC' | 'DESC';
|
||||||
|
random?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SearchPaginationOptions {
|
export interface SearchPaginationOptions {
|
||||||
|
@ -73,8 +73,13 @@ export class SearchRepository implements ISearchRepository {
|
|||||||
async searchMetadata(pagination: SearchPaginationOptions, options: AssetSearchOptions): Paginated<AssetEntity> {
|
async searchMetadata(pagination: SearchPaginationOptions, options: AssetSearchOptions): Paginated<AssetEntity> {
|
||||||
let builder = this.assetRepository.createQueryBuilder('asset');
|
let builder = this.assetRepository.createQueryBuilder('asset');
|
||||||
builder = searchAssetBuilder(builder, options);
|
builder = searchAssetBuilder(builder, options);
|
||||||
|
|
||||||
builder.orderBy('asset.fileCreatedAt', options.orderDirection ?? 'DESC');
|
builder.orderBy('asset.fileCreatedAt', options.orderDirection ?? 'DESC');
|
||||||
|
|
||||||
|
if (options.random) {
|
||||||
|
// TODO replace with complicated SQL magic after kysely migration
|
||||||
|
builder.addSelect('RANDOM() as r').orderBy('r');
|
||||||
|
}
|
||||||
|
|
||||||
return paginatedBuilder<AssetEntity>(builder, {
|
return paginatedBuilder<AssetEntity>(builder, {
|
||||||
mode: PaginationMode.SKIP_TAKE,
|
mode: PaginationMode.SKIP_TAKE,
|
||||||
skip: (pagination.page - 1) * pagination.size,
|
skip: (pagination.page - 1) * pagination.size,
|
||||||
|
@ -6,6 +6,7 @@ import { PersonResponseDto } from 'src/dtos/person.dto';
|
|||||||
import {
|
import {
|
||||||
MetadataSearchDto,
|
MetadataSearchDto,
|
||||||
PlacesResponseDto,
|
PlacesResponseDto,
|
||||||
|
RandomSearchDto,
|
||||||
SearchPeopleDto,
|
SearchPeopleDto,
|
||||||
SearchPlacesDto,
|
SearchPlacesDto,
|
||||||
SearchResponseDto,
|
SearchResponseDto,
|
||||||
@ -93,6 +94,22 @@ export class SearchService {
|
|||||||
return this.mapResponse(items, hasNextPage ? (page + 1).toString() : null, { auth });
|
return this.mapResponse(items, hasNextPage ? (page + 1).toString() : null, { auth });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async searchRandom(auth: AuthDto, dto: RandomSearchDto): Promise<SearchResponseDto> {
|
||||||
|
const userIds = await this.getUserIdsToSearch(auth);
|
||||||
|
const page = dto.page ?? 1;
|
||||||
|
const size = dto.size || 250;
|
||||||
|
const { hasNextPage, items } = await this.searchRepository.searchMetadata(
|
||||||
|
{ page, size },
|
||||||
|
{
|
||||||
|
...dto,
|
||||||
|
userIds,
|
||||||
|
random: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return this.mapResponse(items, hasNextPage ? (page + 1).toString() : null, { auth });
|
||||||
|
}
|
||||||
|
|
||||||
async searchSmart(auth: AuthDto, dto: SmartSearchDto): Promise<SearchResponseDto> {
|
async searchSmart(auth: AuthDto, dto: SmartSearchDto): Promise<SearchResponseDto> {
|
||||||
const { machineLearning } = await this.configCore.getConfig({ withCache: false });
|
const { machineLearning } = await this.configCore.getConfig({ withCache: false });
|
||||||
if (!isSmartSearchEnabled(machineLearning)) {
|
if (!isSmartSearchEnabled(machineLearning)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user