From cbf19aede97f41898f1b44c6e1cc9e740c27f096 Mon Sep 17 00:00:00 2001
From: codeking <t@libertyoceanhorizons.com>
Date: Fri, 14 Mar 2025 16:31:36 +0100
Subject: [PATCH] Add support for composite location arguments

---
 cli/__main__.py | 39 ++++++++++++++++++---------------------
 1 file changed, 18 insertions(+), 21 deletions(-)

diff --git a/cli/__main__.py b/cli/__main__.py
index 294e082..586815e 100644
--- a/cli/__main__.py
+++ b/cli/__main__.py
@@ -24,7 +24,6 @@ from pathlib import Path
 from typing import Optional, Union
 import argparse
 import pprint
-import re
 import sys
 
 if __name__ == '__main__':
@@ -60,17 +59,14 @@ if __name__ == '__main__':
     def __get_version():
         return metadata.version(__get_name())
 
-    def __parse_application_string(application_string: Optional[str] = None):
+    def __parse_composite_argument(argument: str, first_key: str, second_key: str, separator: str = ':'):
+        return dict(zip([first_key, second_key], argument.split(separator) + ['']))
 
-        if application_string is None:
-            return dict(application_code='', version_number='')
+    def __parse_application_argument(application_argument: str):
+        return __parse_composite_argument(application_argument, 'application_code', 'version_number')
 
-        parsed_application_string = re.match('^(?P<application_code>.*?):(?P<version_number>.*?)$', application_string)
-
-        if parsed_application_string is None:
-            return dict(application_code='', version_number='')
-        else:
-            return parsed_application_string.groupdict()
+    def __parse_location_argument(location_argument: str):
+        return __parse_composite_argument(location_argument, 'country_code', 'code')
 
     def __sanitize_profile(candidate: Optional[Union[SessionProfile, SystemProfile]]):
 
@@ -117,7 +113,7 @@ if __name__ == '__main__':
     session_profile_create_parser = profile_create_subparsers.add_parser('session', parents=[profile_base_parser, safe_parser])
 
     session_profile_create_parser.add_argument('--name', '-n', default='')
-    session_profile_create_parser.add_argument('--location', '-l', dest='location_code', default=None)
+    session_profile_create_parser.add_argument('--location', '-l', default='')
     session_profile_create_parser.add_argument('--application', '-a', required=True)
     session_profile_create_parser.add_argument('--connection', '-c', dest='connection_type', choices=['system', 'tor', 'wireguard'], default='system')
     session_profile_create_parser.add_argument('--mask-connection', '-m', action='store_true')
@@ -126,7 +122,7 @@ if __name__ == '__main__':
     system_profile_create_parser = profile_create_subparsers.add_parser('system', parents=[profile_base_parser, safe_parser])
 
     system_profile_create_parser.add_argument('--name', '-n', default='')
-    system_profile_create_parser.add_argument('--location', '-l', dest='location_code', default=None)
+    system_profile_create_parser.add_argument('--location', '-l', default='')
     system_profile_create_parser.add_argument('--connection', '-c', dest='connection_type', choices=['wireguard'], default='wireguard')
 
     profile_subparsers.add_parser('destroy', parents=[profile_base_parser, safe_parser])
@@ -187,15 +183,16 @@ if __name__ == '__main__':
 
         elif arguments.subcommand == 'create':
 
-            location = LocationController.get(arguments.location_code)
+            location_details = __parse_location_argument(arguments.location)
+            location = LocationController.get(location_details.get('country_code'), location_details.get('code'))
 
             if location is None:
                 main_parser.error('the following argument should be a valid reference: --location/-l')
 
             if arguments.profile_type == 'session':
 
-                application_details = __parse_application_string(arguments.application)
-                application_version = ApplicationVersionController.get(application_details.get('application_code'), application_details.get('version_number'))
+                application_version_details = __parse_application_argument(arguments.application)
+                application_version = ApplicationVersionController.get(application_version_details.get('application_code'), application_version_details.get('version_number'))
 
                 if application_version is None:
                     main_parser.error('the following argument should be a valid reference: --application/-a')
@@ -333,8 +330,8 @@ if __name__ == '__main__':
 
         elif arguments.subcommand == 'show':
 
-            application_details = __parse_application_string(arguments.application)
-            application_version = ApplicationVersionController.get(application_details.get('application_code'), application_details.get('version_number'))
+            application_version_details = __parse_application_argument(arguments.application)
+            application_version = ApplicationVersionController.get(application_version_details.get('application_code'), application_version_details.get('version_number'))
 
             if application_version is not None:
                 pprint.pp(application_version)
@@ -343,8 +340,8 @@ if __name__ == '__main__':
 
         elif arguments.subcommand == 'install':
 
-            application_details = __parse_application_string(arguments.application)
-            application_version = ApplicationVersionController.get(application_details.get('application_code'), application_details.get('version_number'))
+            application_version_details = __parse_application_argument(arguments.application)
+            application_version = ApplicationVersionController.get(application_version_details.get('application_code'), application_version_details.get('version_number'))
 
             if application_version is not None:
                 ApplicationVersionController.install(application_version, arguments.reinstall, application_version_observer=application_version_observer, connection_observer=connection_observer)
@@ -353,8 +350,8 @@ if __name__ == '__main__':
 
         elif arguments.subcommand == 'uninstall':
 
-            application_details = __parse_application_string(arguments.application)
-            application_version = ApplicationVersionController.get(application_details.get('application_code'), application_details.get('version_number'))
+            application_version_details = __parse_application_argument(arguments.application)
+            application_version = ApplicationVersionController.get(application_version_details.get('application_code'), application_version_details.get('version_number'))
 
             if application_version is not None:
                 ApplicationVersionController.uninstall(application_version)