diff --git a/lib/logic/api_maps/rest_maps/server_providers/digital_ocean/digital_ocean.dart b/lib/logic/api_maps/rest_maps/server_providers/digital_ocean/digital_ocean.dart index 2354e5ab..798fc54b 100644 --- a/lib/logic/api_maps/rest_maps/server_providers/digital_ocean/digital_ocean.dart +++ b/lib/logic/api_maps/rest_maps/server_providers/digital_ocean/digital_ocean.dart @@ -11,6 +11,7 @@ import 'package:selfprivacy/logic/models/hive/server_details.dart'; import 'package:selfprivacy/logic/models/hive/user.dart'; import 'package:selfprivacy/logic/models/price.dart'; import 'package:selfprivacy/logic/models/server_basic_info.dart'; +import 'package:selfprivacy/logic/models/server_provider_location.dart'; import 'package:selfprivacy/utils/password_generator.dart'; class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi { @@ -538,6 +539,69 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi { return servers; } + String? getEmojiFlag(final String query) { + String? emoji; + + switch (query.toLowerCase().substring(0, 2)) { + case 'fra': + emoji = '🇩🇪'; + break; + + case 'ams': + emoji = '🇳🇱'; + break; + + case 'sgp': + emoji = '🇸🇬'; + break; + + case 'lon': + emoji = '🇬🇧'; + break; + + case 'tor': + emoji = '🇨🇦'; + break; + + case 'blr': + emoji = '🇮🇳'; + break; + + case 'nyc': + case 'sfo': + emoji = '🇺🇸'; + break; + } + + return emoji; + } + + @override + Future> getAvailableLocations() async { + List locations = []; + + final Dio client = await getClient(); + try { + final Response response = await client.post( + '/locations', + ); + + locations = response.data!['locations'].map( + (final location) => ServerProviderLocation( + title: location['slug'], + description: location['name'], + flag: getEmojiFlag(location['slug']), + ), + ); + } catch (e) { + print(e); + } finally { + close(client); + } + + return locations; + } + @override Future createReverseDns({ required final ServerHostingDetails serverDetails, diff --git a/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner.dart b/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner.dart index fe577c03..2c0b70db 100644 --- a/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner.dart +++ b/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner.dart @@ -11,10 +11,15 @@ import 'package:selfprivacy/logic/models/hive/server_details.dart'; import 'package:selfprivacy/logic/models/hive/user.dart'; import 'package:selfprivacy/logic/models/price.dart'; import 'package:selfprivacy/logic/models/server_basic_info.dart'; +import 'package:selfprivacy/logic/models/server_provider_location.dart'; import 'package:selfprivacy/utils/password_generator.dart'; class HetznerApi extends ServerProviderApi with VolumeProviderApi { - HetznerApi({required this.region, this.hasLogger = false, this.isWithToken = true,}); + HetznerApi({ + required this.region, + this.hasLogger = false, + this.isWithToken = true, + }); @override bool hasLogger; @override @@ -536,6 +541,52 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi { return servers; } + String? getEmojiFlag(final String query) { + String? emoji; + + switch (query.toLowerCase()) { + case 'de': + emoji = '🇩🇪'; + break; + + case 'fi': + emoji = '🇫🇮'; + break; + + case 'us': + emoji = '🇺🇸'; + break; + } + + return emoji; + } + + @override + Future> getAvailableLocations() async { + List locations = []; + + final Dio client = await getClient(); + try { + final Response response = await client.post( + '/locations', + ); + + locations = response.data!['locations'].map( + (final location) => ServerProviderLocation( + title: location['city'], + description: location['description'], + flag: getEmojiFlag(location['country']), + ), + ); + } catch (e) { + print(e); + } finally { + close(client); + } + + return locations; + } + @override Future createReverseDns({ required final ServerHostingDetails serverDetails, diff --git a/lib/logic/api_maps/rest_maps/server_providers/server_provider.dart b/lib/logic/api_maps/rest_maps/server_providers/server_provider.dart index c2bfd533..d4b61721 100644 --- a/lib/logic/api_maps/rest_maps/server_providers/server_provider.dart +++ b/lib/logic/api_maps/rest_maps/server_providers/server_provider.dart @@ -3,9 +3,11 @@ import 'package:selfprivacy/logic/models/hive/server_details.dart'; import 'package:selfprivacy/logic/models/hive/server_domain.dart'; import 'package:selfprivacy/logic/models/hive/user.dart'; import 'package:selfprivacy/logic/models/server_basic_info.dart'; +import 'package:selfprivacy/logic/models/server_provider_location.dart'; abstract class ServerProviderApi extends ApiMap { Future> getServers(); + Future> getAvailableLocations(); Future restart(); Future powerOn(); diff --git a/lib/logic/cubit/hetzner_metrics/hetzner_metrics_repository.dart b/lib/logic/cubit/hetzner_metrics/hetzner_metrics_repository.dart index 5b363406..18137fdc 100644 --- a/lib/logic/cubit/hetzner_metrics/hetzner_metrics_repository.dart +++ b/lib/logic/cubit/hetzner_metrics/hetzner_metrics_repository.dart @@ -26,7 +26,10 @@ class HetznerMetricsRepository { break; } - final HetznerApi api = HetznerApi(hasLogger: false, region: 'fra1',); + final HetznerApi api = HetznerApi( + hasLogger: false, + region: 'fra1', + ); final List> results = await Future.wait([ api.getMetrics(start, end, 'cpu'), diff --git a/lib/logic/cubit/provider_volumes/provider_volume_cubit.dart b/lib/logic/cubit/provider_volumes/provider_volume_cubit.dart index 1eb47bf3..95b0d362 100644 --- a/lib/logic/cubit/provider_volumes/provider_volume_cubit.dart +++ b/lib/logic/cubit/provider_volumes/provider_volume_cubit.dart @@ -34,8 +34,13 @@ class ApiProviderVolumeCubit } } - Future getPricePerGb() async => - providerApi!.getVolumeProvider(settings: const ServerProviderApiSettings(region: 'fra1',),).getPricePerGb(); + Future getPricePerGb() async => providerApi! + .getVolumeProvider( + settings: const ServerProviderApiSettings( + region: 'fra1', + ), + ) + .getPricePerGb(); Future refresh() async { emit(const ApiProviderVolumeState([], LoadingStatus.refreshing, false)); @@ -47,8 +52,13 @@ class ApiProviderVolumeCubit return emit(const ApiProviderVolumeState([], LoadingStatus.error, false)); } - final List volumes = - await providerApi!.getVolumeProvider(settings: const ServerProviderApiSettings(region: 'fra1',),).getVolumes(); + final List volumes = await providerApi! + .getVolumeProvider( + settings: const ServerProviderApiSettings( + region: 'fra1', + ), + ) + .getVolumes(); if (volumes.isEmpty) { return emit(const ApiProviderVolumeState([], LoadingStatus.error, false)); @@ -60,14 +70,22 @@ class ApiProviderVolumeCubit Future attachVolume(final DiskVolume volume) async { final ServerHostingDetails server = getIt().serverDetails!; await providerApi! - .getVolumeProvider(settings: const ServerProviderApiSettings(region: 'fra1',),) + .getVolumeProvider( + settings: const ServerProviderApiSettings( + region: 'fra1', + ), + ) .attachVolume(volume.providerVolume!.id.toString(), server.id); refresh(); } Future detachVolume(final DiskVolume volume) async { await providerApi! - .getVolumeProvider(settings: const ServerProviderApiSettings(region: 'fra1',),) + .getVolumeProvider( + settings: const ServerProviderApiSettings( + region: 'fra1', + ), + ) .detachVolume(volume.providerVolume!.id.toString()); refresh(); } @@ -81,7 +99,13 @@ class ApiProviderVolumeCubit 'Starting resize', ); emit(state.copyWith(isResizing: true)); - final bool resized = await providerApi!.getVolumeProvider(settings: const ServerProviderApiSettings(region: 'fra1',),).resizeVolume( + final bool resized = await providerApi! + .getVolumeProvider( + settings: const ServerProviderApiSettings( + region: 'fra1', + ), + ) + .resizeVolume( volume.providerVolume!.id.toString(), newSizeGb, ); @@ -117,8 +141,13 @@ class ApiProviderVolumeCubit } Future createVolume() async { - final ServerVolume? volume = - await providerApi!.getVolumeProvider(settings: const ServerProviderApiSettings(region: 'fra1',),).createVolume(); + final ServerVolume? volume = await providerApi! + .getVolumeProvider( + settings: const ServerProviderApiSettings( + region: 'fra1', + ), + ) + .createVolume(); final diskVolume = DiskVolume(providerVolume: volume); await attachVolume(diskVolume); @@ -131,7 +160,11 @@ class ApiProviderVolumeCubit Future deleteVolume(final DiskVolume volume) async { await providerApi! - .getVolumeProvider(settings: const ServerProviderApiSettings(region: 'fra1',),) + .getVolumeProvider( + settings: const ServerProviderApiSettings( + region: 'fra1', + ), + ) .deleteVolume(volume.providerVolume!.id.toString()); refresh(); } diff --git a/lib/logic/cubit/server_installation/server_installation_cubit.dart b/lib/logic/cubit/server_installation/server_installation_cubit.dart index 8e121044..99dd1d82 100644 --- a/lib/logic/cubit/server_installation/server_installation_cubit.dart +++ b/lib/logic/cubit/server_installation/server_installation_cubit.dart @@ -63,7 +63,11 @@ class ServerInstallationCubit extends Cubit { RegExp getServerProviderApiTokenValidation() => repository.serverProviderApiFactory! - .getServerProvider(settings: const ServerProviderApiSettings(region: 'fra1',),) + .getServerProvider( + settings: const ServerProviderApiSettings( + region: 'fra1', + ), + ) .getApiTokenValidation(); RegExp getDnsProviderApiTokenValidation() => repository.dnsProviderApiFactory! @@ -75,7 +79,8 @@ class ServerInstallationCubit extends Cubit { ) async => repository.serverProviderApiFactory! .getServerProvider( - settings: const ServerProviderApiSettings(region: 'fra1', isWithToken: false), + settings: const ServerProviderApiSettings( + region: 'fra1', isWithToken: false), ) .isApiTokenValid(providerToken); diff --git a/lib/logic/cubit/server_installation/server_installation_repository.dart b/lib/logic/cubit/server_installation/server_installation_repository.dart index 10306c61..4fe10b1f 100644 --- a/lib/logic/cubit/server_installation/server_installation_repository.dart +++ b/lib/logic/cubit/server_installation/server_installation_repository.dart @@ -153,7 +153,11 @@ class ServerInstallationRepository { ) async { ServerHostingDetails serverDetails; - final ServerProviderApi api = serverProviderApiFactory!.getServerProvider(settings: const ServerProviderApiSettings(region: 'fra1',),); + final ServerProviderApi api = serverProviderApiFactory!.getServerProvider( + settings: const ServerProviderApiSettings( + region: 'fra1', + ), + ); serverDetails = await api.powerOn(); return serverDetails; @@ -229,7 +233,11 @@ class ServerInstallationRepository { required final Future Function(ServerHostingDetails serverDetails) onSuccess, }) async { - final ServerProviderApi api = serverProviderApiFactory!.getServerProvider(settings: const ServerProviderApiSettings(region: 'fra1',),); + final ServerProviderApi api = serverProviderApiFactory!.getServerProvider( + settings: const ServerProviderApiSettings( + region: 'fra1', + ), + ); try { final ServerHostingDetails? serverDetails = await api.createServer( dnsApiToken: cloudFlareKey, @@ -334,7 +342,11 @@ class ServerInstallationRepository { final DnsProviderApi dnsProviderApi = dnsProviderApiFactory!.getDnsProvider(); final ServerProviderApi serverApi = - serverProviderApiFactory!.getServerProvider(settings: const ServerProviderApiSettings(region: 'fra1',),); + serverProviderApiFactory!.getServerProvider( + settings: const ServerProviderApiSettings( + region: 'fra1', + ), + ); await dnsProviderApi.removeSimilarRecords( ip4: serverDetails.ip4, @@ -406,12 +418,20 @@ class ServerInstallationRepository { } Future restart() async { - final ServerProviderApi api = serverProviderApiFactory!.getServerProvider(settings: const ServerProviderApiSettings(region: 'fra1',),); + final ServerProviderApi api = serverProviderApiFactory!.getServerProvider( + settings: const ServerProviderApiSettings( + region: 'fra1', + ), + ); return api.restart(); } Future powerOn() async { - final ServerProviderApi api = serverProviderApiFactory!.getServerProvider(settings: const ServerProviderApiSettings(region: 'fra1',),); + final ServerProviderApi api = serverProviderApiFactory!.getServerProvider( + settings: const ServerProviderApiSettings( + region: 'fra1', + ), + ); return api.powerOn(); } @@ -654,7 +674,11 @@ class ServerInstallationRepository { } Future> getServersOnProviderAccount() async { - final ServerProviderApi api = serverProviderApiFactory!.getServerProvider(settings: const ServerProviderApiSettings(region: 'fra1',),); + final ServerProviderApi api = serverProviderApiFactory!.getServerProvider( + settings: const ServerProviderApiSettings( + region: 'fra1', + ), + ); return api.getServers(); } @@ -732,7 +756,11 @@ class ServerInstallationRepository { } Future deleteServer(final ServerDomain serverDomain) async { - final ServerProviderApi api = serverProviderApiFactory!.getServerProvider(settings: const ServerProviderApiSettings(region: 'fra1',),); + final ServerProviderApi api = serverProviderApiFactory!.getServerProvider( + settings: const ServerProviderApiSettings( + region: 'fra1', + ), + ); final DnsProviderApi dnsProviderApi = dnsProviderApiFactory!.getDnsProvider(); diff --git a/lib/logic/models/server_provider_location.dart b/lib/logic/models/server_provider_location.dart new file mode 100644 index 00000000..dea063a4 --- /dev/null +++ b/lib/logic/models/server_provider_location.dart @@ -0,0 +1,13 @@ +class ServerProviderLocation { + ServerProviderLocation({ + required this.title, + this.description, + this.flag, + }); + + final String title; + final String? description; + + /// as emoji + final String? flag; +}