2023-07-09 23:00:00 +02:00
|
|
|
import 'dart:async';
|
|
|
|
import 'dart:convert';
|
|
|
|
import 'package:dartz/dartz.dart';
|
|
|
|
import 'package:http/http.dart' as http;
|
2024-01-27 23:07:06 +01:00
|
|
|
import 'package:shlink_app/API/Classes/ShortURL/visits_summary.dart';
|
|
|
|
import '../Classes/ShlinkStats/shlink_stats.dart';
|
|
|
|
import '../server_manager.dart';
|
2023-07-09 23:00:00 +02:00
|
|
|
|
2024-01-27 23:07:06 +01:00
|
|
|
/// Gets statistics about the Shlink server
|
|
|
|
FutureOr<Either<ShlinkStats, Failure>> apiGetShlinkStats(String? apiKey, String? serverUrl, String apiVersion) async {
|
2023-07-09 23:00:00 +02:00
|
|
|
|
|
|
|
var nonOrphanVisits;
|
|
|
|
var orphanVisits;
|
|
|
|
var shortUrlsCount;
|
|
|
|
var tagsCount;
|
|
|
|
var failure;
|
|
|
|
|
2024-01-27 23:07:06 +01:00
|
|
|
var visitStatsResponse = await _getVisitStats(apiKey, serverUrl, apiVersion);
|
2023-07-09 23:00:00 +02:00
|
|
|
visitStatsResponse.fold((l) {
|
|
|
|
nonOrphanVisits = l.nonOrphanVisits;
|
|
|
|
orphanVisits = l.orphanVisits;
|
|
|
|
}, (r) {
|
|
|
|
failure = r;
|
|
|
|
return right(r);
|
|
|
|
});
|
|
|
|
|
2024-01-27 23:07:06 +01:00
|
|
|
var shortUrlsCountResponse = await _getShortUrlsCount(apiKey, serverUrl, apiVersion);
|
2023-07-09 23:00:00 +02:00
|
|
|
shortUrlsCountResponse.fold((l) {
|
|
|
|
shortUrlsCount = l;
|
|
|
|
}, (r) {
|
|
|
|
failure = r;
|
|
|
|
return right(r);
|
|
|
|
});
|
|
|
|
|
2024-01-27 23:07:06 +01:00
|
|
|
var tagsCountResponse = await _getTagsCount(apiKey, serverUrl, apiVersion);
|
2023-07-09 23:00:00 +02:00
|
|
|
tagsCountResponse.fold((l) {
|
|
|
|
tagsCount = l;
|
|
|
|
}, (r) {
|
|
|
|
failure = r;
|
|
|
|
return right(r);
|
|
|
|
});
|
|
|
|
|
|
|
|
while(failure == null && (nonOrphanVisits == null || orphanVisits == null || shortUrlsCount == null || tagsCount == null)) {
|
2024-01-27 23:07:06 +01:00
|
|
|
await Future.delayed(const Duration(milliseconds: 100));
|
2023-07-09 23:00:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (failure != null) {
|
|
|
|
return right(failure);
|
|
|
|
}
|
|
|
|
return left(ShlinkStats(nonOrphanVisits, orphanVisits, shortUrlsCount, tagsCount));
|
|
|
|
}
|
|
|
|
|
|
|
|
class _ShlinkVisitStats {
|
2024-01-27 23:07:06 +01:00
|
|
|
VisitsSummary nonOrphanVisits;
|
|
|
|
VisitsSummary orphanVisits;
|
2023-07-09 23:00:00 +02:00
|
|
|
|
|
|
|
_ShlinkVisitStats(this.nonOrphanVisits, this.orphanVisits);
|
|
|
|
}
|
|
|
|
|
2024-01-27 23:07:06 +01:00
|
|
|
/// Gets visitor statistics about the entire server
|
|
|
|
FutureOr<Either<_ShlinkVisitStats, Failure>> _getVisitStats(String? apiKey, String? serverUrl, String apiVersion) async {
|
2023-07-09 23:00:00 +02:00
|
|
|
try {
|
2024-01-27 23:07:06 +01:00
|
|
|
final response = await http.get(Uri.parse("$serverUrl/rest/v$apiVersion/visits"), headers: {
|
|
|
|
"X-Api-Key": apiKey ?? "",
|
2023-07-09 23:00:00 +02:00
|
|
|
});
|
|
|
|
if (response.statusCode == 200) {
|
|
|
|
var jsonResponse = jsonDecode(response.body);
|
2024-01-27 23:07:06 +01:00
|
|
|
var nonOrphanVisits = VisitsSummary.fromJson(jsonResponse["visits"]["nonOrphanVisits"]);
|
|
|
|
var orphanVisits = VisitsSummary.fromJson(jsonResponse["visits"]["orphanVisits"]);
|
2023-07-09 23:00:00 +02:00
|
|
|
return left(_ShlinkVisitStats(nonOrphanVisits, orphanVisits));
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
try {
|
|
|
|
var jsonBody = jsonDecode(response.body);
|
|
|
|
return right(ApiFailure(type: jsonBody["type"], detail: jsonBody["detail"], title: jsonBody["title"], status: jsonBody["status"]));
|
|
|
|
}
|
|
|
|
catch(resErr) {
|
|
|
|
return right(RequestFailure(response.statusCode, resErr.toString()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(reqErr) {
|
|
|
|
return right(RequestFailure(0, reqErr.toString()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-27 23:07:06 +01:00
|
|
|
/// Gets amount of short URLs
|
|
|
|
FutureOr<Either<int, Failure>> _getShortUrlsCount(String? apiKey, String? serverUrl, String apiVersion) async {
|
2023-07-09 23:00:00 +02:00
|
|
|
try {
|
2024-01-27 23:07:06 +01:00
|
|
|
final response = await http.get(Uri.parse("$serverUrl/rest/v$apiVersion/short-urls"), headers: {
|
|
|
|
"X-Api-Key": apiKey ?? "",
|
2023-07-09 23:00:00 +02:00
|
|
|
});
|
|
|
|
if (response.statusCode == 200) {
|
|
|
|
var jsonResponse = jsonDecode(response.body);
|
|
|
|
return left(jsonResponse["shortUrls"]["pagination"]["totalItems"]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
try {
|
|
|
|
var jsonBody = jsonDecode(response.body);
|
|
|
|
return right(ApiFailure(type: jsonBody["type"], detail: jsonBody["detail"], title: jsonBody["title"], status: jsonBody["status"]));
|
|
|
|
}
|
|
|
|
catch(resErr) {
|
|
|
|
return right(RequestFailure(response.statusCode, resErr.toString()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(reqErr) {
|
|
|
|
return right(RequestFailure(0, reqErr.toString()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-27 23:07:06 +01:00
|
|
|
/// Gets amount of tags
|
|
|
|
FutureOr<Either<int, Failure>> _getTagsCount(String? apiKey, String? serverUrl, String apiVersion) async {
|
2023-07-09 23:00:00 +02:00
|
|
|
try {
|
2024-01-27 23:07:06 +01:00
|
|
|
final response = await http.get(Uri.parse("$serverUrl/rest/v$apiVersion/tags"), headers: {
|
|
|
|
"X-Api-Key": apiKey ?? "",
|
2023-07-09 23:00:00 +02:00
|
|
|
});
|
|
|
|
if (response.statusCode == 200) {
|
|
|
|
var jsonResponse = jsonDecode(response.body);
|
|
|
|
return left(jsonResponse["tags"]["pagination"]["totalItems"]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
try {
|
|
|
|
var jsonBody = jsonDecode(response.body);
|
|
|
|
return right(ApiFailure(type: jsonBody["type"], detail: jsonBody["detail"], title: jsonBody["title"], status: jsonBody["status"]));
|
|
|
|
}
|
|
|
|
catch(resErr) {
|
|
|
|
return right(RequestFailure(response.statusCode, resErr.toString()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(reqErr) {
|
|
|
|
return right(RequestFailure(0, reqErr.toString()));
|
|
|
|
}
|
|
|
|
}
|