mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-02-02 06:46:22 +01:00
Tidy up source files
This commit is contained in:
parent
6694149c29
commit
5459919fab
7 changed files with 753 additions and 743 deletions
|
@ -10,6 +10,11 @@ import 'package:to_string/to_string.dart';
|
||||||
import 'package:xml/xml.dart';
|
import 'package:xml/xml.dart';
|
||||||
|
|
||||||
part 'api.g.dart';
|
part 'api.g.dart';
|
||||||
|
part 'direct_api.dart';
|
||||||
|
part 'face_recognition_api.dart';
|
||||||
|
part 'files_api.dart';
|
||||||
|
part 'files_sharing_api.dart';
|
||||||
|
part 'systemtag_api.dart';
|
||||||
|
|
||||||
@toString
|
@toString
|
||||||
class Response {
|
class Response {
|
||||||
|
@ -133,344 +138,6 @@ class Api {
|
||||||
|
|
||||||
bool _isHttpStatusGood(int status) => status ~/ 100 == 2;
|
bool _isHttpStatusGood(int status) => status ~/ 100 == 2;
|
||||||
|
|
||||||
@npLog
|
|
||||||
class ApiFiles {
|
|
||||||
ApiFiles(this._api);
|
|
||||||
|
|
||||||
final Api _api;
|
|
||||||
|
|
||||||
Future<Response> delete({
|
|
||||||
required String path,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
return await _api.request("DELETE", path);
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[delete] Failed while delete", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<Response> get({
|
|
||||||
required String path,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
return await _api.request("GET", path, isResponseString: false);
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[get] Failed while get", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<Response> put({
|
|
||||||
required String path,
|
|
||||||
String mime = "application/octet-stream",
|
|
||||||
required Uint8List content,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
return await _api.request(
|
|
||||||
"PUT",
|
|
||||||
path,
|
|
||||||
header: {
|
|
||||||
"Content-Type": mime,
|
|
||||||
},
|
|
||||||
bodyBytes: content,
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[put] Failed while put", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<Response> propfind({
|
|
||||||
required String path,
|
|
||||||
int? depth,
|
|
||||||
getlastmodified,
|
|
||||||
getetag,
|
|
||||||
getcontenttype,
|
|
||||||
resourcetype,
|
|
||||||
getcontentlength,
|
|
||||||
id,
|
|
||||||
fileid,
|
|
||||||
favorite,
|
|
||||||
commentsHref,
|
|
||||||
commentsCount,
|
|
||||||
commentsUnread,
|
|
||||||
ownerId,
|
|
||||||
ownerDisplayName,
|
|
||||||
shareTypes,
|
|
||||||
checksums,
|
|
||||||
hasPreview,
|
|
||||||
size,
|
|
||||||
richWorkspace,
|
|
||||||
trashbinFilename,
|
|
||||||
trashbinOriginalLocation,
|
|
||||||
trashbinDeletionTime,
|
|
||||||
Map<String, String>? customNamespaces,
|
|
||||||
List<String>? customProperties,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
final bool hasDavNs = (getlastmodified != null ||
|
|
||||||
getetag != null ||
|
|
||||||
getcontenttype != null ||
|
|
||||||
resourcetype != null ||
|
|
||||||
getcontentlength != null);
|
|
||||||
final bool hasOcNs = (id != null ||
|
|
||||||
fileid != null ||
|
|
||||||
favorite != null ||
|
|
||||||
commentsHref != null ||
|
|
||||||
commentsCount != null ||
|
|
||||||
commentsUnread != null ||
|
|
||||||
ownerId != null ||
|
|
||||||
ownerDisplayName != null ||
|
|
||||||
shareTypes != null ||
|
|
||||||
checksums != null ||
|
|
||||||
size != null);
|
|
||||||
final bool hasNcNs = (hasPreview != null ||
|
|
||||||
richWorkspace != null ||
|
|
||||||
trashbinFilename != null ||
|
|
||||||
trashbinOriginalLocation != null ||
|
|
||||||
trashbinDeletionTime != null);
|
|
||||||
if (!hasDavNs && !hasOcNs && !hasNcNs) {
|
|
||||||
// no body
|
|
||||||
return await _api.request("PROPFIND", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
final namespaces = <String, String>{
|
|
||||||
"DAV:": "d",
|
|
||||||
if (hasOcNs) "http://owncloud.org/ns": "oc",
|
|
||||||
if (hasNcNs) "http://nextcloud.org/ns": "nc",
|
|
||||||
}..addAll(customNamespaces ?? {});
|
|
||||||
final builder = XmlBuilder();
|
|
||||||
builder
|
|
||||||
..processing("xml", "version=\"1.0\"")
|
|
||||||
..element("d:propfind", namespaces: namespaces, nest: () {
|
|
||||||
builder.element("d:prop", nest: () {
|
|
||||||
if (getlastmodified != null) {
|
|
||||||
builder.element("d:getlastmodified");
|
|
||||||
}
|
|
||||||
if (getetag != null) {
|
|
||||||
builder.element("d:getetag");
|
|
||||||
}
|
|
||||||
if (getcontenttype != null) {
|
|
||||||
builder.element("d:getcontenttype");
|
|
||||||
}
|
|
||||||
if (resourcetype != null) {
|
|
||||||
builder.element("d:resourcetype");
|
|
||||||
}
|
|
||||||
if (getcontentlength != null) {
|
|
||||||
builder.element("d:getcontentlength");
|
|
||||||
}
|
|
||||||
if (id != null) {
|
|
||||||
builder.element("oc:id");
|
|
||||||
}
|
|
||||||
if (fileid != null) {
|
|
||||||
builder.element("oc:fileid");
|
|
||||||
}
|
|
||||||
if (favorite != null) {
|
|
||||||
builder.element("oc:favorite");
|
|
||||||
}
|
|
||||||
if (commentsHref != null) {
|
|
||||||
builder.element("oc:comments-href");
|
|
||||||
}
|
|
||||||
if (commentsCount != null) {
|
|
||||||
builder.element("oc:comments-count");
|
|
||||||
}
|
|
||||||
if (commentsUnread != null) {
|
|
||||||
builder.element("oc:comments-unread");
|
|
||||||
}
|
|
||||||
if (ownerId != null) {
|
|
||||||
builder.element("oc:owner-id");
|
|
||||||
}
|
|
||||||
if (ownerDisplayName != null) {
|
|
||||||
builder.element("oc:owner-display-name");
|
|
||||||
}
|
|
||||||
if (shareTypes != null) {
|
|
||||||
builder.element("oc:share-types");
|
|
||||||
}
|
|
||||||
if (checksums != null) {
|
|
||||||
builder.element("oc:checksums");
|
|
||||||
}
|
|
||||||
if (size != null) {
|
|
||||||
builder.element("oc:size");
|
|
||||||
}
|
|
||||||
if (hasPreview != null) {
|
|
||||||
builder.element("nc:has-preview");
|
|
||||||
}
|
|
||||||
if (richWorkspace != null) {
|
|
||||||
builder.element("nc:rich-workspace");
|
|
||||||
}
|
|
||||||
if (trashbinFilename != null) {
|
|
||||||
builder.element("nc:trashbin-filename");
|
|
||||||
}
|
|
||||||
if (trashbinOriginalLocation != null) {
|
|
||||||
builder.element("nc:trashbin-original-location");
|
|
||||||
}
|
|
||||||
if (trashbinDeletionTime != null) {
|
|
||||||
builder.element("nc:trashbin-deletion-time");
|
|
||||||
}
|
|
||||||
for (final p in customProperties ?? []) {
|
|
||||||
builder.element(p);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return await _api.request("PROPFIND", path,
|
|
||||||
header: {
|
|
||||||
"Content-Type": "application/xml",
|
|
||||||
if (depth != null) "Depth": depth.toString(),
|
|
||||||
},
|
|
||||||
body: builder.buildDocument().toXmlString());
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[propfind] Failed while propfind", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set or remove custom properties
|
|
||||||
///
|
|
||||||
/// [namespaces] should be specified in the format {"URI": "prefix"}, eg,
|
|
||||||
/// {"DAV:": "d"}
|
|
||||||
Future<Response> proppatch({
|
|
||||||
required String path,
|
|
||||||
Map<String, String>? namespaces,
|
|
||||||
Map<String, dynamic>? set,
|
|
||||||
List<String>? remove,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
final ns = <String, String>{
|
|
||||||
"DAV:": "d",
|
|
||||||
}..addAll(namespaces ?? {});
|
|
||||||
final builder = XmlBuilder();
|
|
||||||
builder
|
|
||||||
..processing("xml", "version=\"1.0\"")
|
|
||||||
..element("d:propertyupdate", namespaces: ns, nest: () {
|
|
||||||
if (set != null && set.isNotEmpty) {
|
|
||||||
builder.element("d:set", nest: () {
|
|
||||||
builder.element("d:prop", nest: () {
|
|
||||||
for (final e in set.entries) {
|
|
||||||
builder.element(e.key, nest: () {
|
|
||||||
builder.text("${e.value}");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (remove != null && remove.isNotEmpty) {
|
|
||||||
builder.element("d:remove", nest: () {
|
|
||||||
builder.element("d:prop", nest: () {
|
|
||||||
for (final e in remove) {
|
|
||||||
builder.element(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return await _api.request(
|
|
||||||
"PROPPATCH",
|
|
||||||
path,
|
|
||||||
header: {
|
|
||||||
"Content-Type": "application/xml",
|
|
||||||
},
|
|
||||||
body: builder.buildDocument().toXmlString(),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[proppatch] Failed while proppatch", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A folder can be created by sending a MKCOL request to the folder
|
|
||||||
Future<Response> mkcol({
|
|
||||||
required String path,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
return await _api.request("MKCOL", path);
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[mkcol] Failed while get", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A file or folder can be copied by sending a COPY request to the file or
|
|
||||||
/// folder and specifying the [destinationUrl] as full url
|
|
||||||
Future<Response> copy({
|
|
||||||
required String path,
|
|
||||||
required String destinationUrl,
|
|
||||||
bool? overwrite,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
return await _api.request("COPY", path, header: {
|
|
||||||
"Destination": Uri.parse(destinationUrl).toString(),
|
|
||||||
if (overwrite != null) "Overwrite": overwrite ? "T" : "F",
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[copy] Failed while delete", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A file or folder can be moved by sending a MOVE request to the file or
|
|
||||||
/// folder and specifying the [destinationUrl] as full url
|
|
||||||
Future<Response> move({
|
|
||||||
required String path,
|
|
||||||
required String destinationUrl,
|
|
||||||
bool? overwrite,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
return await _api.request("MOVE", path, header: {
|
|
||||||
"Destination": Uri.parse(destinationUrl).toString(),
|
|
||||||
if (overwrite != null) "Overwrite": overwrite ? "T" : "F",
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[move] Failed while delete", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<Response> report({
|
|
||||||
required String path,
|
|
||||||
bool? favorite,
|
|
||||||
List<int>? systemtag,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
final namespaces = <String, String>{
|
|
||||||
"DAV:": "d",
|
|
||||||
"http://owncloud.org/ns": "oc",
|
|
||||||
};
|
|
||||||
final builder = XmlBuilder();
|
|
||||||
builder
|
|
||||||
..processing("xml", "version=\"1.0\"")
|
|
||||||
..element("oc:filter-files", namespaces: namespaces, nest: () {
|
|
||||||
builder.element("oc:filter-rules", nest: () {
|
|
||||||
if (favorite != null) {
|
|
||||||
builder.element("oc:favorite", nest: () {
|
|
||||||
builder.text(favorite ? "1" : "0");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
for (final t in systemtag ?? []) {
|
|
||||||
builder.element("oc:systemtag", nest: () {
|
|
||||||
builder.text(t);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.element("d:prop", nest: () {
|
|
||||||
builder.element("oc:fileid");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return await _api.request(
|
|
||||||
"REPORT",
|
|
||||||
path,
|
|
||||||
header: {
|
|
||||||
"Content-Type": "application/xml",
|
|
||||||
},
|
|
||||||
body: builder.buildDocument().toXmlString(),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[report] Failed while report", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ApiOcs {
|
class ApiOcs {
|
||||||
ApiOcs(this._api);
|
ApiOcs(this._api);
|
||||||
|
|
||||||
|
@ -490,401 +157,3 @@ class ApiOcsDav {
|
||||||
|
|
||||||
final ApiOcs _ocs;
|
final ApiOcs _ocs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@npLog
|
|
||||||
class ApiOcsDavDirect {
|
|
||||||
ApiOcsDavDirect(this._dav);
|
|
||||||
|
|
||||||
Future<Response> post({
|
|
||||||
required int fileId,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
return await _dav._ocs._api.request(
|
|
||||||
"POST",
|
|
||||||
"ocs/v2.php/apps/dav/api/v1/direct",
|
|
||||||
header: {
|
|
||||||
"OCS-APIRequest": "true",
|
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
|
||||||
},
|
|
||||||
queryParameters: {
|
|
||||||
"format": "json",
|
|
||||||
},
|
|
||||||
body: "fileId=$fileId",
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[post] Failed while post", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final ApiOcsDav _dav;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ApiOcsFacerecognition {
|
|
||||||
ApiOcsFacerecognition(this._ocs);
|
|
||||||
|
|
||||||
ApiOcsFacerecognitionPersons persons() => ApiOcsFacerecognitionPersons(this);
|
|
||||||
|
|
||||||
ApiOcsFacerecognitionPerson person(String name) =>
|
|
||||||
ApiOcsFacerecognitionPerson(this, name);
|
|
||||||
|
|
||||||
final ApiOcs _ocs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@npLog
|
|
||||||
class ApiOcsFacerecognitionPersons {
|
|
||||||
ApiOcsFacerecognitionPersons(this._facerecognition);
|
|
||||||
|
|
||||||
Future<Response> get() async {
|
|
||||||
try {
|
|
||||||
return await _facerecognition._ocs._api.request(
|
|
||||||
"GET",
|
|
||||||
"ocs/v2.php/apps/facerecognition/api/v1/persons",
|
|
||||||
header: {
|
|
||||||
"OCS-APIRequest": "true",
|
|
||||||
},
|
|
||||||
queryParameters: {
|
|
||||||
"format": "json",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[get] Failed while get", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final ApiOcsFacerecognition _facerecognition;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ApiOcsFacerecognitionPerson {
|
|
||||||
ApiOcsFacerecognitionPerson(this._facerecognition, this._name);
|
|
||||||
|
|
||||||
ApiOcsFacerecognitionPersonFaces faces() =>
|
|
||||||
ApiOcsFacerecognitionPersonFaces(this);
|
|
||||||
|
|
||||||
final ApiOcsFacerecognition _facerecognition;
|
|
||||||
final String _name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@npLog
|
|
||||||
class ApiOcsFacerecognitionPersonFaces {
|
|
||||||
ApiOcsFacerecognitionPersonFaces(this._person);
|
|
||||||
|
|
||||||
Future<Response> get() async {
|
|
||||||
try {
|
|
||||||
return await _person._facerecognition._ocs._api.request(
|
|
||||||
"GET",
|
|
||||||
"ocs/v2.php/apps/facerecognition/api/v1/person/${_person._name}/faces",
|
|
||||||
header: {
|
|
||||||
"OCS-APIRequest": "true",
|
|
||||||
},
|
|
||||||
queryParameters: {
|
|
||||||
"format": "json",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[get] Failed while get", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final ApiOcsFacerecognitionPerson _person;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ApiOcsFilesSharing {
|
|
||||||
ApiOcsFilesSharing(this._ocs);
|
|
||||||
|
|
||||||
ApiOcsFilesSharingShares shares() => ApiOcsFilesSharingShares(this);
|
|
||||||
|
|
||||||
ApiOcsFilesSharingShare share(String shareId) =>
|
|
||||||
ApiOcsFilesSharingShare(this, shareId);
|
|
||||||
|
|
||||||
ApiOcsFilesSharingSharees sharees() => ApiOcsFilesSharingSharees(this);
|
|
||||||
|
|
||||||
final ApiOcs _ocs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@npLog
|
|
||||||
class ApiOcsFilesSharingShares {
|
|
||||||
ApiOcsFilesSharingShares(this._filesSharing);
|
|
||||||
|
|
||||||
/// Get Shares from a specific file or folder
|
|
||||||
///
|
|
||||||
/// If [sharedWithMe] is not null, [subfiles] and [path] are ignored. This is
|
|
||||||
/// a limitation of the server API.
|
|
||||||
///
|
|
||||||
/// See: https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-share-api.html#get-shares-from-a-specific-file-or-folder
|
|
||||||
/// See: https://doc.owncloud.com/server/latest/developer_manual/core/apis/ocs-share-api.html#get-all-shares
|
|
||||||
Future<Response> get({
|
|
||||||
String? path,
|
|
||||||
bool? reshares,
|
|
||||||
bool? subfiles,
|
|
||||||
bool? sharedWithMe,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
return await _filesSharing._ocs._api.request(
|
|
||||||
"GET",
|
|
||||||
"ocs/v2.php/apps/files_sharing/api/v1/shares",
|
|
||||||
header: {
|
|
||||||
"OCS-APIRequest": "true",
|
|
||||||
},
|
|
||||||
queryParameters: {
|
|
||||||
"format": "json",
|
|
||||||
if (path != null) "path": path,
|
|
||||||
if (reshares != null) "reshares": reshares.toString(),
|
|
||||||
if (subfiles != null) "subfiles": subfiles.toString(),
|
|
||||||
if (sharedWithMe != null) "shared_with_me": sharedWithMe.toString(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[get] Failed while get", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new Share
|
|
||||||
///
|
|
||||||
/// See: https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-share-api.html#create-a-new-share
|
|
||||||
Future<Response> post({
|
|
||||||
required String path,
|
|
||||||
required int shareType,
|
|
||||||
String? shareWith,
|
|
||||||
String? publicUpload,
|
|
||||||
String? password,
|
|
||||||
int? permissions,
|
|
||||||
String? expireDate,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
return await _filesSharing._ocs._api.request(
|
|
||||||
"POST",
|
|
||||||
"ocs/v2.php/apps/files_sharing/api/v1/shares",
|
|
||||||
header: {
|
|
||||||
"OCS-APIRequest": "true",
|
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
|
||||||
},
|
|
||||||
queryParameters: {
|
|
||||||
"format": "json",
|
|
||||||
"path": path,
|
|
||||||
"shareType": shareType.toString(),
|
|
||||||
if (shareWith != null) "shareWith": shareWith,
|
|
||||||
if (publicUpload != null) "publicUpload": publicUpload,
|
|
||||||
if (password != null) "password": password,
|
|
||||||
if (password != null) "password": password,
|
|
||||||
if (expireDate != null) "expireDate": expireDate.toString(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[post] Failed while post", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final ApiOcsFilesSharing _filesSharing;
|
|
||||||
}
|
|
||||||
|
|
||||||
@npLog
|
|
||||||
class ApiOcsFilesSharingShare {
|
|
||||||
ApiOcsFilesSharingShare(this._filesSharing, this._shareId);
|
|
||||||
|
|
||||||
/// Remove the given share
|
|
||||||
///
|
|
||||||
/// See: https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-share-api.html#delete-share
|
|
||||||
/// * The type of share ID is listed as int in the document, however, the
|
|
||||||
/// share ID returned in [ApiOcsFilesSharingShares.get] is actually a string. To
|
|
||||||
/// keep it consistent, we'll use string instead
|
|
||||||
Future<Response> delete() async {
|
|
||||||
try {
|
|
||||||
return await _filesSharing._ocs._api.request(
|
|
||||||
"DELETE",
|
|
||||||
"ocs/v2.php/apps/files_sharing/api/v1/shares/$_shareId",
|
|
||||||
header: {
|
|
||||||
"OCS-APIRequest": "true",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[delete] Failed while delete", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final ApiOcsFilesSharing _filesSharing;
|
|
||||||
final String _shareId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@npLog
|
|
||||||
class ApiOcsFilesSharingSharees {
|
|
||||||
ApiOcsFilesSharingSharees(this._filesSharing);
|
|
||||||
|
|
||||||
/// Get all sharees matching a search term
|
|
||||||
///
|
|
||||||
/// See: https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-sharee-api.html#search-sharees
|
|
||||||
Future<Response> get({
|
|
||||||
String? search,
|
|
||||||
bool? lookup,
|
|
||||||
int? perPage,
|
|
||||||
String? itemType,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
return await _filesSharing._ocs._api.request(
|
|
||||||
"GET",
|
|
||||||
"ocs/v1.php/apps/files_sharing/api/v1/sharees",
|
|
||||||
header: {
|
|
||||||
"OCS-APIRequest": "true",
|
|
||||||
},
|
|
||||||
queryParameters: {
|
|
||||||
"format": "json",
|
|
||||||
if (search != null) "search": search,
|
|
||||||
if (lookup != null) "lookup": lookup.toString(),
|
|
||||||
if (perPage != null) "perPage": perPage.toString(),
|
|
||||||
if (itemType != null) "itemType": itemType,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[get] Failed while get", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final ApiOcsFilesSharing _filesSharing;
|
|
||||||
}
|
|
||||||
|
|
||||||
@npLog
|
|
||||||
class ApiSystemtags {
|
|
||||||
const ApiSystemtags(this.api);
|
|
||||||
|
|
||||||
/// Retrieve a list of all tags
|
|
||||||
///
|
|
||||||
/// See: https://doc.owncloud.com/server/10.10/developer_manual/webdav_api/tags.html#list-tags
|
|
||||||
Future<Response> propfind({
|
|
||||||
id,
|
|
||||||
displayName,
|
|
||||||
userVisible,
|
|
||||||
userAssignable,
|
|
||||||
}) async {
|
|
||||||
const endpoint = "remote.php/dav/systemtags";
|
|
||||||
try {
|
|
||||||
if (id == null &&
|
|
||||||
displayName == null &&
|
|
||||||
userVisible == null &&
|
|
||||||
userAssignable == null) {
|
|
||||||
// no body
|
|
||||||
return await api.request("PROPFIND", endpoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
final namespaces = <String, String>{
|
|
||||||
"DAV:": "d",
|
|
||||||
"http://owncloud.org/ns": "oc",
|
|
||||||
};
|
|
||||||
final builder = XmlBuilder();
|
|
||||||
builder
|
|
||||||
..processing("xml", "version=\"1.0\"")
|
|
||||||
..element("d:propfind", namespaces: namespaces, nest: () {
|
|
||||||
builder.element("d:prop", nest: () {
|
|
||||||
if (id != null) {
|
|
||||||
builder.element("oc:id");
|
|
||||||
}
|
|
||||||
if (displayName != null) {
|
|
||||||
builder.element("oc:display-name");
|
|
||||||
}
|
|
||||||
if (userVisible != null) {
|
|
||||||
builder.element("oc:user-visible");
|
|
||||||
}
|
|
||||||
if (userAssignable != null) {
|
|
||||||
builder.element("oc:user-assignable");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return await api.request(
|
|
||||||
"PROPFIND",
|
|
||||||
endpoint,
|
|
||||||
header: {
|
|
||||||
"Content-Type": "application/xml",
|
|
||||||
},
|
|
||||||
body: builder.buildDocument().toXmlString(),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[propfind] Failed while propfind", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final Api api;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ApiSystemtagsRelations {
|
|
||||||
const ApiSystemtagsRelations(this.api);
|
|
||||||
|
|
||||||
ApiSystemtagsRelationsFiles files(int fileId) =>
|
|
||||||
ApiSystemtagsRelationsFiles(this, fileId);
|
|
||||||
|
|
||||||
final Api api;
|
|
||||||
}
|
|
||||||
|
|
||||||
@npLog
|
|
||||||
class ApiSystemtagsRelationsFiles {
|
|
||||||
const ApiSystemtagsRelationsFiles(this.systemtagsRelations, this.fileId);
|
|
||||||
|
|
||||||
/// Retrieve the tag ids and metadata of a given file
|
|
||||||
///
|
|
||||||
/// See: https://doc.owncloud.com/server/10.10/developer_manual/webdav_api/tags.html#retrieve-the-tag-ids-and-metadata-of-a-given-file
|
|
||||||
Future<Response> propfind({
|
|
||||||
id,
|
|
||||||
displayName,
|
|
||||||
userVisible,
|
|
||||||
userAssignable,
|
|
||||||
canAssign,
|
|
||||||
}) async {
|
|
||||||
final endpoint = "remote.php/dav/systemtags-relations/files/$fileId";
|
|
||||||
try {
|
|
||||||
if (id == null &&
|
|
||||||
displayName == null &&
|
|
||||||
userVisible == null &&
|
|
||||||
userAssignable == null &&
|
|
||||||
canAssign == null) {
|
|
||||||
// no body
|
|
||||||
return await systemtagsRelations.api.request("PROPFIND", endpoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
final namespaces = <String, String>{
|
|
||||||
"DAV:": "d",
|
|
||||||
"http://owncloud.org/ns": "oc",
|
|
||||||
};
|
|
||||||
final builder = XmlBuilder();
|
|
||||||
builder
|
|
||||||
..processing("xml", "version=\"1.0\"")
|
|
||||||
..element("d:propfind", namespaces: namespaces, nest: () {
|
|
||||||
builder.element("d:prop", nest: () {
|
|
||||||
if (id != null) {
|
|
||||||
builder.element("oc:id");
|
|
||||||
}
|
|
||||||
if (displayName != null) {
|
|
||||||
builder.element("oc:display-name");
|
|
||||||
}
|
|
||||||
if (userVisible != null) {
|
|
||||||
builder.element("oc:user-visible");
|
|
||||||
}
|
|
||||||
if (userAssignable != null) {
|
|
||||||
builder.element("oc:user-assignable");
|
|
||||||
}
|
|
||||||
if (canAssign != null) {
|
|
||||||
builder.element("oc:can-assign");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return await systemtagsRelations.api.request(
|
|
||||||
"PROPFIND",
|
|
||||||
endpoint,
|
|
||||||
header: {
|
|
||||||
"Content-Type": "application/xml",
|
|
||||||
},
|
|
||||||
body: builder.buildDocument().toXmlString(),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
_log.severe("[propfind] Failed while propfind", e);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final ApiSystemtagsRelations systemtagsRelations;
|
|
||||||
final int fileId;
|
|
||||||
}
|
|
||||||
|
|
|
@ -13,13 +13,6 @@ extension _$ApiNpLog on Api {
|
||||||
static final log = Logger("api.api.Api");
|
static final log = Logger("api.api.Api");
|
||||||
}
|
}
|
||||||
|
|
||||||
extension _$ApiFilesNpLog on ApiFiles {
|
|
||||||
// ignore: unused_element
|
|
||||||
Logger get _log => log;
|
|
||||||
|
|
||||||
static final log = Logger("api.api.ApiFiles");
|
|
||||||
}
|
|
||||||
|
|
||||||
extension _$ApiOcsDavDirectNpLog on ApiOcsDavDirect {
|
extension _$ApiOcsDavDirectNpLog on ApiOcsDavDirect {
|
||||||
// ignore: unused_element
|
// ignore: unused_element
|
||||||
Logger get _log => log;
|
Logger get _log => log;
|
||||||
|
@ -42,6 +35,13 @@ extension _$ApiOcsFacerecognitionPersonFacesNpLog
|
||||||
static final log = Logger("api.api.ApiOcsFacerecognitionPersonFaces");
|
static final log = Logger("api.api.ApiOcsFacerecognitionPersonFaces");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension _$ApiFilesNpLog on ApiFiles {
|
||||||
|
// ignore: unused_element
|
||||||
|
Logger get _log => log;
|
||||||
|
|
||||||
|
static final log = Logger("api.api.ApiFiles");
|
||||||
|
}
|
||||||
|
|
||||||
extension _$ApiOcsFilesSharingSharesNpLog on ApiOcsFilesSharingShares {
|
extension _$ApiOcsFilesSharingSharesNpLog on ApiOcsFilesSharingShares {
|
||||||
// ignore: unused_element
|
// ignore: unused_element
|
||||||
Logger get _log => log;
|
Logger get _log => log;
|
||||||
|
|
30
app/lib/api/direct_api.dart
Normal file
30
app/lib/api/direct_api.dart
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
part of 'api.dart';
|
||||||
|
|
||||||
|
@npLog
|
||||||
|
class ApiOcsDavDirect {
|
||||||
|
ApiOcsDavDirect(this._dav);
|
||||||
|
|
||||||
|
Future<Response> post({
|
||||||
|
required int fileId,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
return await _dav._ocs._api.request(
|
||||||
|
"POST",
|
||||||
|
"ocs/v2.php/apps/dav/api/v1/direct",
|
||||||
|
header: {
|
||||||
|
"OCS-APIRequest": "true",
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
},
|
||||||
|
queryParameters: {
|
||||||
|
"format": "json",
|
||||||
|
},
|
||||||
|
body: "fileId=$fileId",
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[post] Failed while post", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final ApiOcsDav _dav;
|
||||||
|
}
|
72
app/lib/api/face_recognition_api.dart
Normal file
72
app/lib/api/face_recognition_api.dart
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
part of 'api.dart';
|
||||||
|
|
||||||
|
class ApiOcsFacerecognition {
|
||||||
|
ApiOcsFacerecognition(this._ocs);
|
||||||
|
|
||||||
|
ApiOcsFacerecognitionPersons persons() => ApiOcsFacerecognitionPersons(this);
|
||||||
|
|
||||||
|
ApiOcsFacerecognitionPerson person(String name) =>
|
||||||
|
ApiOcsFacerecognitionPerson(this, name);
|
||||||
|
|
||||||
|
final ApiOcs _ocs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@npLog
|
||||||
|
class ApiOcsFacerecognitionPersons {
|
||||||
|
ApiOcsFacerecognitionPersons(this._facerecognition);
|
||||||
|
|
||||||
|
Future<Response> get() async {
|
||||||
|
try {
|
||||||
|
return await _facerecognition._ocs._api.request(
|
||||||
|
"GET",
|
||||||
|
"ocs/v2.php/apps/facerecognition/api/v1/persons",
|
||||||
|
header: {
|
||||||
|
"OCS-APIRequest": "true",
|
||||||
|
},
|
||||||
|
queryParameters: {
|
||||||
|
"format": "json",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[get] Failed while get", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final ApiOcsFacerecognition _facerecognition;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ApiOcsFacerecognitionPerson {
|
||||||
|
ApiOcsFacerecognitionPerson(this._facerecognition, this._name);
|
||||||
|
|
||||||
|
ApiOcsFacerecognitionPersonFaces faces() =>
|
||||||
|
ApiOcsFacerecognitionPersonFaces(this);
|
||||||
|
|
||||||
|
final ApiOcsFacerecognition _facerecognition;
|
||||||
|
final String _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@npLog
|
||||||
|
class ApiOcsFacerecognitionPersonFaces {
|
||||||
|
ApiOcsFacerecognitionPersonFaces(this._person);
|
||||||
|
|
||||||
|
Future<Response> get() async {
|
||||||
|
try {
|
||||||
|
return await _person._facerecognition._ocs._api.request(
|
||||||
|
"GET",
|
||||||
|
"ocs/v2.php/apps/facerecognition/api/v1/person/${_person._name}/faces",
|
||||||
|
header: {
|
||||||
|
"OCS-APIRequest": "true",
|
||||||
|
},
|
||||||
|
queryParameters: {
|
||||||
|
"format": "json",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[get] Failed while get", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final ApiOcsFacerecognitionPerson _person;
|
||||||
|
}
|
339
app/lib/api/files_api.dart
Normal file
339
app/lib/api/files_api.dart
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
part of 'api.dart';
|
||||||
|
|
||||||
|
@npLog
|
||||||
|
class ApiFiles {
|
||||||
|
ApiFiles(this._api);
|
||||||
|
|
||||||
|
final Api _api;
|
||||||
|
|
||||||
|
Future<Response> delete({
|
||||||
|
required String path,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
return await _api.request("DELETE", path);
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[delete] Failed while delete", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> get({
|
||||||
|
required String path,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
return await _api.request("GET", path, isResponseString: false);
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[get] Failed while get", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> put({
|
||||||
|
required String path,
|
||||||
|
String mime = "application/octet-stream",
|
||||||
|
required Uint8List content,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
return await _api.request(
|
||||||
|
"PUT",
|
||||||
|
path,
|
||||||
|
header: {
|
||||||
|
"Content-Type": mime,
|
||||||
|
},
|
||||||
|
bodyBytes: content,
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[put] Failed while put", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> propfind({
|
||||||
|
required String path,
|
||||||
|
int? depth,
|
||||||
|
getlastmodified,
|
||||||
|
getetag,
|
||||||
|
getcontenttype,
|
||||||
|
resourcetype,
|
||||||
|
getcontentlength,
|
||||||
|
id,
|
||||||
|
fileid,
|
||||||
|
favorite,
|
||||||
|
commentsHref,
|
||||||
|
commentsCount,
|
||||||
|
commentsUnread,
|
||||||
|
ownerId,
|
||||||
|
ownerDisplayName,
|
||||||
|
shareTypes,
|
||||||
|
checksums,
|
||||||
|
hasPreview,
|
||||||
|
size,
|
||||||
|
richWorkspace,
|
||||||
|
trashbinFilename,
|
||||||
|
trashbinOriginalLocation,
|
||||||
|
trashbinDeletionTime,
|
||||||
|
Map<String, String>? customNamespaces,
|
||||||
|
List<String>? customProperties,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final bool hasDavNs = (getlastmodified != null ||
|
||||||
|
getetag != null ||
|
||||||
|
getcontenttype != null ||
|
||||||
|
resourcetype != null ||
|
||||||
|
getcontentlength != null);
|
||||||
|
final bool hasOcNs = (id != null ||
|
||||||
|
fileid != null ||
|
||||||
|
favorite != null ||
|
||||||
|
commentsHref != null ||
|
||||||
|
commentsCount != null ||
|
||||||
|
commentsUnread != null ||
|
||||||
|
ownerId != null ||
|
||||||
|
ownerDisplayName != null ||
|
||||||
|
shareTypes != null ||
|
||||||
|
checksums != null ||
|
||||||
|
size != null);
|
||||||
|
final bool hasNcNs = (hasPreview != null ||
|
||||||
|
richWorkspace != null ||
|
||||||
|
trashbinFilename != null ||
|
||||||
|
trashbinOriginalLocation != null ||
|
||||||
|
trashbinDeletionTime != null);
|
||||||
|
if (!hasDavNs && !hasOcNs && !hasNcNs) {
|
||||||
|
// no body
|
||||||
|
return await _api.request("PROPFIND", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
final namespaces = <String, String>{
|
||||||
|
"DAV:": "d",
|
||||||
|
if (hasOcNs) "http://owncloud.org/ns": "oc",
|
||||||
|
if (hasNcNs) "http://nextcloud.org/ns": "nc",
|
||||||
|
}..addAll(customNamespaces ?? {});
|
||||||
|
final builder = XmlBuilder();
|
||||||
|
builder
|
||||||
|
..processing("xml", "version=\"1.0\"")
|
||||||
|
..element("d:propfind", namespaces: namespaces, nest: () {
|
||||||
|
builder.element("d:prop", nest: () {
|
||||||
|
if (getlastmodified != null) {
|
||||||
|
builder.element("d:getlastmodified");
|
||||||
|
}
|
||||||
|
if (getetag != null) {
|
||||||
|
builder.element("d:getetag");
|
||||||
|
}
|
||||||
|
if (getcontenttype != null) {
|
||||||
|
builder.element("d:getcontenttype");
|
||||||
|
}
|
||||||
|
if (resourcetype != null) {
|
||||||
|
builder.element("d:resourcetype");
|
||||||
|
}
|
||||||
|
if (getcontentlength != null) {
|
||||||
|
builder.element("d:getcontentlength");
|
||||||
|
}
|
||||||
|
if (id != null) {
|
||||||
|
builder.element("oc:id");
|
||||||
|
}
|
||||||
|
if (fileid != null) {
|
||||||
|
builder.element("oc:fileid");
|
||||||
|
}
|
||||||
|
if (favorite != null) {
|
||||||
|
builder.element("oc:favorite");
|
||||||
|
}
|
||||||
|
if (commentsHref != null) {
|
||||||
|
builder.element("oc:comments-href");
|
||||||
|
}
|
||||||
|
if (commentsCount != null) {
|
||||||
|
builder.element("oc:comments-count");
|
||||||
|
}
|
||||||
|
if (commentsUnread != null) {
|
||||||
|
builder.element("oc:comments-unread");
|
||||||
|
}
|
||||||
|
if (ownerId != null) {
|
||||||
|
builder.element("oc:owner-id");
|
||||||
|
}
|
||||||
|
if (ownerDisplayName != null) {
|
||||||
|
builder.element("oc:owner-display-name");
|
||||||
|
}
|
||||||
|
if (shareTypes != null) {
|
||||||
|
builder.element("oc:share-types");
|
||||||
|
}
|
||||||
|
if (checksums != null) {
|
||||||
|
builder.element("oc:checksums");
|
||||||
|
}
|
||||||
|
if (size != null) {
|
||||||
|
builder.element("oc:size");
|
||||||
|
}
|
||||||
|
if (hasPreview != null) {
|
||||||
|
builder.element("nc:has-preview");
|
||||||
|
}
|
||||||
|
if (richWorkspace != null) {
|
||||||
|
builder.element("nc:rich-workspace");
|
||||||
|
}
|
||||||
|
if (trashbinFilename != null) {
|
||||||
|
builder.element("nc:trashbin-filename");
|
||||||
|
}
|
||||||
|
if (trashbinOriginalLocation != null) {
|
||||||
|
builder.element("nc:trashbin-original-location");
|
||||||
|
}
|
||||||
|
if (trashbinDeletionTime != null) {
|
||||||
|
builder.element("nc:trashbin-deletion-time");
|
||||||
|
}
|
||||||
|
for (final p in customProperties ?? []) {
|
||||||
|
builder.element(p);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return await _api.request("PROPFIND", path,
|
||||||
|
header: {
|
||||||
|
"Content-Type": "application/xml",
|
||||||
|
if (depth != null) "Depth": depth.toString(),
|
||||||
|
},
|
||||||
|
body: builder.buildDocument().toXmlString());
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[propfind] Failed while propfind", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set or remove custom properties
|
||||||
|
///
|
||||||
|
/// [namespaces] should be specified in the format {"URI": "prefix"}, eg,
|
||||||
|
/// {"DAV:": "d"}
|
||||||
|
Future<Response> proppatch({
|
||||||
|
required String path,
|
||||||
|
Map<String, String>? namespaces,
|
||||||
|
Map<String, dynamic>? set,
|
||||||
|
List<String>? remove,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final ns = <String, String>{
|
||||||
|
"DAV:": "d",
|
||||||
|
}..addAll(namespaces ?? {});
|
||||||
|
final builder = XmlBuilder();
|
||||||
|
builder
|
||||||
|
..processing("xml", "version=\"1.0\"")
|
||||||
|
..element("d:propertyupdate", namespaces: ns, nest: () {
|
||||||
|
if (set != null && set.isNotEmpty) {
|
||||||
|
builder.element("d:set", nest: () {
|
||||||
|
builder.element("d:prop", nest: () {
|
||||||
|
for (final e in set.entries) {
|
||||||
|
builder.element(e.key, nest: () {
|
||||||
|
builder.text("${e.value}");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (remove != null && remove.isNotEmpty) {
|
||||||
|
builder.element("d:remove", nest: () {
|
||||||
|
builder.element("d:prop", nest: () {
|
||||||
|
for (final e in remove) {
|
||||||
|
builder.element(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return await _api.request(
|
||||||
|
"PROPPATCH",
|
||||||
|
path,
|
||||||
|
header: {
|
||||||
|
"Content-Type": "application/xml",
|
||||||
|
},
|
||||||
|
body: builder.buildDocument().toXmlString(),
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[proppatch] Failed while proppatch", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A folder can be created by sending a MKCOL request to the folder
|
||||||
|
Future<Response> mkcol({
|
||||||
|
required String path,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
return await _api.request("MKCOL", path);
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[mkcol] Failed while get", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A file or folder can be copied by sending a COPY request to the file or
|
||||||
|
/// folder and specifying the [destinationUrl] as full url
|
||||||
|
Future<Response> copy({
|
||||||
|
required String path,
|
||||||
|
required String destinationUrl,
|
||||||
|
bool? overwrite,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
return await _api.request("COPY", path, header: {
|
||||||
|
"Destination": Uri.parse(destinationUrl).toString(),
|
||||||
|
if (overwrite != null) "Overwrite": overwrite ? "T" : "F",
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[copy] Failed while delete", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A file or folder can be moved by sending a MOVE request to the file or
|
||||||
|
/// folder and specifying the [destinationUrl] as full url
|
||||||
|
Future<Response> move({
|
||||||
|
required String path,
|
||||||
|
required String destinationUrl,
|
||||||
|
bool? overwrite,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
return await _api.request("MOVE", path, header: {
|
||||||
|
"Destination": Uri.parse(destinationUrl).toString(),
|
||||||
|
if (overwrite != null) "Overwrite": overwrite ? "T" : "F",
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[move] Failed while delete", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Response> report({
|
||||||
|
required String path,
|
||||||
|
bool? favorite,
|
||||||
|
List<int>? systemtag,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final namespaces = <String, String>{
|
||||||
|
"DAV:": "d",
|
||||||
|
"http://owncloud.org/ns": "oc",
|
||||||
|
};
|
||||||
|
final builder = XmlBuilder();
|
||||||
|
builder
|
||||||
|
..processing("xml", "version=\"1.0\"")
|
||||||
|
..element("oc:filter-files", namespaces: namespaces, nest: () {
|
||||||
|
builder.element("oc:filter-rules", nest: () {
|
||||||
|
if (favorite != null) {
|
||||||
|
builder.element("oc:favorite", nest: () {
|
||||||
|
builder.text(favorite ? "1" : "0");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for (final t in systemtag ?? []) {
|
||||||
|
builder.element("oc:systemtag", nest: () {
|
||||||
|
builder.text(t);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.element("d:prop", nest: () {
|
||||||
|
builder.element("oc:fileid");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return await _api.request(
|
||||||
|
"REPORT",
|
||||||
|
path,
|
||||||
|
header: {
|
||||||
|
"Content-Type": "application/xml",
|
||||||
|
},
|
||||||
|
body: builder.buildDocument().toXmlString(),
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[report] Failed while report", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
158
app/lib/api/files_sharing_api.dart
Normal file
158
app/lib/api/files_sharing_api.dart
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
part of 'api.dart';
|
||||||
|
|
||||||
|
class ApiOcsFilesSharing {
|
||||||
|
ApiOcsFilesSharing(this._ocs);
|
||||||
|
|
||||||
|
ApiOcsFilesSharingShares shares() => ApiOcsFilesSharingShares(this);
|
||||||
|
|
||||||
|
ApiOcsFilesSharingShare share(String shareId) =>
|
||||||
|
ApiOcsFilesSharingShare(this, shareId);
|
||||||
|
|
||||||
|
ApiOcsFilesSharingSharees sharees() => ApiOcsFilesSharingSharees(this);
|
||||||
|
|
||||||
|
final ApiOcs _ocs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@npLog
|
||||||
|
class ApiOcsFilesSharingShares {
|
||||||
|
ApiOcsFilesSharingShares(this._filesSharing);
|
||||||
|
|
||||||
|
/// Get Shares from a specific file or folder
|
||||||
|
///
|
||||||
|
/// If [sharedWithMe] is not null, [subfiles] and [path] are ignored. This is
|
||||||
|
/// a limitation of the server API.
|
||||||
|
///
|
||||||
|
/// See: https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-share-api.html#get-shares-from-a-specific-file-or-folder
|
||||||
|
/// See: https://doc.owncloud.com/server/latest/developer_manual/core/apis/ocs-share-api.html#get-all-shares
|
||||||
|
Future<Response> get({
|
||||||
|
String? path,
|
||||||
|
bool? reshares,
|
||||||
|
bool? subfiles,
|
||||||
|
bool? sharedWithMe,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
return await _filesSharing._ocs._api.request(
|
||||||
|
"GET",
|
||||||
|
"ocs/v2.php/apps/files_sharing/api/v1/shares",
|
||||||
|
header: {
|
||||||
|
"OCS-APIRequest": "true",
|
||||||
|
},
|
||||||
|
queryParameters: {
|
||||||
|
"format": "json",
|
||||||
|
if (path != null) "path": path,
|
||||||
|
if (reshares != null) "reshares": reshares.toString(),
|
||||||
|
if (subfiles != null) "subfiles": subfiles.toString(),
|
||||||
|
if (sharedWithMe != null) "shared_with_me": sharedWithMe.toString(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[get] Failed while get", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new Share
|
||||||
|
///
|
||||||
|
/// See: https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-share-api.html#create-a-new-share
|
||||||
|
Future<Response> post({
|
||||||
|
required String path,
|
||||||
|
required int shareType,
|
||||||
|
String? shareWith,
|
||||||
|
String? publicUpload,
|
||||||
|
String? password,
|
||||||
|
int? permissions,
|
||||||
|
String? expireDate,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
return await _filesSharing._ocs._api.request(
|
||||||
|
"POST",
|
||||||
|
"ocs/v2.php/apps/files_sharing/api/v1/shares",
|
||||||
|
header: {
|
||||||
|
"OCS-APIRequest": "true",
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
},
|
||||||
|
queryParameters: {
|
||||||
|
"format": "json",
|
||||||
|
"path": path,
|
||||||
|
"shareType": shareType.toString(),
|
||||||
|
if (shareWith != null) "shareWith": shareWith,
|
||||||
|
if (publicUpload != null) "publicUpload": publicUpload,
|
||||||
|
if (password != null) "password": password,
|
||||||
|
if (password != null) "password": password,
|
||||||
|
if (expireDate != null) "expireDate": expireDate.toString(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[post] Failed while post", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final ApiOcsFilesSharing _filesSharing;
|
||||||
|
}
|
||||||
|
|
||||||
|
@npLog
|
||||||
|
class ApiOcsFilesSharingShare {
|
||||||
|
ApiOcsFilesSharingShare(this._filesSharing, this._shareId);
|
||||||
|
|
||||||
|
/// Remove the given share
|
||||||
|
///
|
||||||
|
/// See: https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-share-api.html#delete-share
|
||||||
|
/// * The type of share ID is listed as int in the document, however, the
|
||||||
|
/// share ID returned in [ApiOcsFilesSharingShares.get] is actually a string. To
|
||||||
|
/// keep it consistent, we'll use string instead
|
||||||
|
Future<Response> delete() async {
|
||||||
|
try {
|
||||||
|
return await _filesSharing._ocs._api.request(
|
||||||
|
"DELETE",
|
||||||
|
"ocs/v2.php/apps/files_sharing/api/v1/shares/$_shareId",
|
||||||
|
header: {
|
||||||
|
"OCS-APIRequest": "true",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[delete] Failed while delete", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final ApiOcsFilesSharing _filesSharing;
|
||||||
|
final String _shareId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@npLog
|
||||||
|
class ApiOcsFilesSharingSharees {
|
||||||
|
ApiOcsFilesSharingSharees(this._filesSharing);
|
||||||
|
|
||||||
|
/// Get all sharees matching a search term
|
||||||
|
///
|
||||||
|
/// See: https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-sharee-api.html#search-sharees
|
||||||
|
Future<Response> get({
|
||||||
|
String? search,
|
||||||
|
bool? lookup,
|
||||||
|
int? perPage,
|
||||||
|
String? itemType,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
return await _filesSharing._ocs._api.request(
|
||||||
|
"GET",
|
||||||
|
"ocs/v1.php/apps/files_sharing/api/v1/sharees",
|
||||||
|
header: {
|
||||||
|
"OCS-APIRequest": "true",
|
||||||
|
},
|
||||||
|
queryParameters: {
|
||||||
|
"format": "json",
|
||||||
|
if (search != null) "search": search,
|
||||||
|
if (lookup != null) "lookup": lookup.toString(),
|
||||||
|
if (perPage != null) "perPage": perPage.toString(),
|
||||||
|
if (itemType != null) "itemType": itemType,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[get] Failed while get", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final ApiOcsFilesSharing _filesSharing;
|
||||||
|
}
|
142
app/lib/api/systemtag_api.dart
Normal file
142
app/lib/api/systemtag_api.dart
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
part of 'api.dart';
|
||||||
|
|
||||||
|
@npLog
|
||||||
|
class ApiSystemtags {
|
||||||
|
const ApiSystemtags(this.api);
|
||||||
|
|
||||||
|
/// Retrieve a list of all tags
|
||||||
|
///
|
||||||
|
/// See: https://doc.owncloud.com/server/10.10/developer_manual/webdav_api/tags.html#list-tags
|
||||||
|
Future<Response> propfind({
|
||||||
|
id,
|
||||||
|
displayName,
|
||||||
|
userVisible,
|
||||||
|
userAssignable,
|
||||||
|
}) async {
|
||||||
|
const endpoint = "remote.php/dav/systemtags";
|
||||||
|
try {
|
||||||
|
if (id == null &&
|
||||||
|
displayName == null &&
|
||||||
|
userVisible == null &&
|
||||||
|
userAssignable == null) {
|
||||||
|
// no body
|
||||||
|
return await api.request("PROPFIND", endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
final namespaces = <String, String>{
|
||||||
|
"DAV:": "d",
|
||||||
|
"http://owncloud.org/ns": "oc",
|
||||||
|
};
|
||||||
|
final builder = XmlBuilder();
|
||||||
|
builder
|
||||||
|
..processing("xml", "version=\"1.0\"")
|
||||||
|
..element("d:propfind", namespaces: namespaces, nest: () {
|
||||||
|
builder.element("d:prop", nest: () {
|
||||||
|
if (id != null) {
|
||||||
|
builder.element("oc:id");
|
||||||
|
}
|
||||||
|
if (displayName != null) {
|
||||||
|
builder.element("oc:display-name");
|
||||||
|
}
|
||||||
|
if (userVisible != null) {
|
||||||
|
builder.element("oc:user-visible");
|
||||||
|
}
|
||||||
|
if (userAssignable != null) {
|
||||||
|
builder.element("oc:user-assignable");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return await api.request(
|
||||||
|
"PROPFIND",
|
||||||
|
endpoint,
|
||||||
|
header: {
|
||||||
|
"Content-Type": "application/xml",
|
||||||
|
},
|
||||||
|
body: builder.buildDocument().toXmlString(),
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[propfind] Failed while propfind", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Api api;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ApiSystemtagsRelations {
|
||||||
|
const ApiSystemtagsRelations(this.api);
|
||||||
|
|
||||||
|
ApiSystemtagsRelationsFiles files(int fileId) =>
|
||||||
|
ApiSystemtagsRelationsFiles(this, fileId);
|
||||||
|
|
||||||
|
final Api api;
|
||||||
|
}
|
||||||
|
|
||||||
|
@npLog
|
||||||
|
class ApiSystemtagsRelationsFiles {
|
||||||
|
const ApiSystemtagsRelationsFiles(this.systemtagsRelations, this.fileId);
|
||||||
|
|
||||||
|
/// Retrieve the tag ids and metadata of a given file
|
||||||
|
///
|
||||||
|
/// See: https://doc.owncloud.com/server/10.10/developer_manual/webdav_api/tags.html#retrieve-the-tag-ids-and-metadata-of-a-given-file
|
||||||
|
Future<Response> propfind({
|
||||||
|
id,
|
||||||
|
displayName,
|
||||||
|
userVisible,
|
||||||
|
userAssignable,
|
||||||
|
canAssign,
|
||||||
|
}) async {
|
||||||
|
final endpoint = "remote.php/dav/systemtags-relations/files/$fileId";
|
||||||
|
try {
|
||||||
|
if (id == null &&
|
||||||
|
displayName == null &&
|
||||||
|
userVisible == null &&
|
||||||
|
userAssignable == null &&
|
||||||
|
canAssign == null) {
|
||||||
|
// no body
|
||||||
|
return await systemtagsRelations.api.request("PROPFIND", endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
final namespaces = <String, String>{
|
||||||
|
"DAV:": "d",
|
||||||
|
"http://owncloud.org/ns": "oc",
|
||||||
|
};
|
||||||
|
final builder = XmlBuilder();
|
||||||
|
builder
|
||||||
|
..processing("xml", "version=\"1.0\"")
|
||||||
|
..element("d:propfind", namespaces: namespaces, nest: () {
|
||||||
|
builder.element("d:prop", nest: () {
|
||||||
|
if (id != null) {
|
||||||
|
builder.element("oc:id");
|
||||||
|
}
|
||||||
|
if (displayName != null) {
|
||||||
|
builder.element("oc:display-name");
|
||||||
|
}
|
||||||
|
if (userVisible != null) {
|
||||||
|
builder.element("oc:user-visible");
|
||||||
|
}
|
||||||
|
if (userAssignable != null) {
|
||||||
|
builder.element("oc:user-assignable");
|
||||||
|
}
|
||||||
|
if (canAssign != null) {
|
||||||
|
builder.element("oc:can-assign");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return await systemtagsRelations.api.request(
|
||||||
|
"PROPFIND",
|
||||||
|
endpoint,
|
||||||
|
header: {
|
||||||
|
"Content-Type": "application/xml",
|
||||||
|
},
|
||||||
|
body: builder.buildDocument().toXmlString(),
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
_log.severe("[propfind] Failed while propfind", e);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final ApiSystemtagsRelations systemtagsRelations;
|
||||||
|
final int fileId;
|
||||||
|
}
|
Loading…
Reference in a new issue