warlock-manager 2.2.8__tar.gz → 2.2.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/PKG-INFO +1 -1
  2. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/pyproject.toml +1 -1
  3. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/apps/base_app.py +20 -20
  4. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/apps/steam_app.py +11 -11
  5. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/config/ini_config.py +5 -5
  6. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/libs/app.py +5 -5
  7. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/libs/app_runner.py +6 -27
  8. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/libs/cmd.py +24 -23
  9. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/libs/download.py +3 -3
  10. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/libs/firewall.py +11 -11
  11. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/libs/java.py +3 -4
  12. warlock_manager-2.2.9/warlock_manager/libs/logger.py +70 -0
  13. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/libs/meta.py +11 -1
  14. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/libs/tui.py +3 -3
  15. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/libs/utils.py +2 -2
  16. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/mods/base_mod.py +4 -4
  17. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/mods/warlock_nexus_mod.py +3 -3
  18. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/nexus/nexus.py +4 -8
  19. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/services/base_service.py +86 -51
  20. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/services/socket_service.py +14 -14
  21. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager.egg-info/PKG-INFO +1 -1
  22. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager.egg-info/SOURCES.txt +1 -0
  23. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/LICENSE +0 -0
  24. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/README.md +0 -0
  25. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/setup.cfg +0 -0
  26. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/tests/test_app.py +0 -0
  27. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/tests/test_base_config.py +0 -0
  28. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/tests/test_base_service.py +0 -0
  29. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/tests/test_cli_config.py +0 -0
  30. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/tests/test_cli_formatter.py +0 -0
  31. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/tests/test_cmd.py +0 -0
  32. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/tests/test_config_key.py +0 -0
  33. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/tests/test_ini_config.py +0 -0
  34. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/tests/test_sensitive_data_filter.py +0 -0
  35. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/tests/test_socket_service.py +0 -0
  36. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/tests/test_unreal_config.py +0 -0
  37. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/tests/test_unreal_config_ark_spawn_entities.py +0 -0
  38. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/tests/test_unreal_save.py +0 -0
  39. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/tests/test_version.py +0 -0
  40. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/__init__.py +0 -0
  41. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/apps/__init__.py +0 -0
  42. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/apps/manual_app.py +0 -0
  43. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/config/__init__.py +0 -0
  44. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/config/base_config.py +0 -0
  45. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/config/cli_config.py +0 -0
  46. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/config/config_key.py +0 -0
  47. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/config/json_config.py +0 -0
  48. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/config/properties_config.py +0 -0
  49. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/config/unreal_config.py +0 -0
  50. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/formatters/__init__.py +0 -0
  51. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/formatters/cli_formatter.py +0 -0
  52. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/libs/__init__.py +0 -0
  53. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/libs/cache.py +0 -0
  54. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/libs/get_wan_ip.py +0 -0
  55. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/libs/ports.py +0 -0
  56. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/libs/proton.py +0 -0
  57. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/libs/sensitive_data_filter.py +0 -0
  58. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/libs/version.py +0 -0
  59. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/mods/__init__.py +0 -0
  60. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/services/__init__.py +0 -0
  61. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/services/http_service.py +0 -0
  62. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager/services/rcon_service.py +0 -0
  63. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager.egg-info/dependency_links.txt +0 -0
  64. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager.egg-info/requires.txt +0 -0
  65. {warlock_manager-2.2.8 → warlock_manager-2.2.9}/warlock_manager.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: warlock-manager
3
- Version: 2.2.8
3
+ Version: 2.2.9
4
4
  Summary: Dependency library for game-server management applications.
5
5
  Author-email: Charlie Powell <cdp1337@bitsnbytes.dev>
6
6
  Maintainer-email: Charlie Powell <cdp1337@bitsnbytes.dev>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "warlock-manager"
7
- version = "2.2.8"
7
+ version = "2.2.9"
8
8
  description = "Dependency library for game-server management applications."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,5 +1,4 @@
1
1
  import json
2
- import logging
3
2
  import os
4
3
  import shutil
5
4
  import time
@@ -17,6 +16,7 @@ if TYPE_CHECKING:
17
16
  from warlock_manager.libs.tui import prompt_yn, prompt_text
18
17
  from warlock_manager.libs import utils
19
18
  from warlock_manager.libs.ports import get_ports
19
+ from warlock_manager.libs.logger import logger
20
20
 
21
21
 
22
22
  class BaseApp(ABC):
@@ -116,7 +116,7 @@ class BaseApp(ABC):
116
116
  elif config.path:
117
117
  # Doesn't exist, (that's fine),
118
118
  # but the directory structure should be available to make it more simple for saving
119
- self.ensure_file_parent_exists(config.path)
119
+ utils.ensure_file_parent_exists(config.path)
120
120
 
121
121
  def save(self):
122
122
  """
@@ -150,7 +150,7 @@ class BaseApp(ABC):
150
150
  if option in config.options:
151
151
  return config.get_value(option)
152
152
 
153
- logging.warning('Invalid option: %s, not present in game configuration!' % option)
153
+ logger.warning('Invalid option: %s, not present in game configuration!' % option)
154
154
  return ''
155
155
 
156
156
  def get_option_default(self, option: str) -> str:
@@ -163,7 +163,7 @@ class BaseApp(ABC):
163
163
  if option in config.options:
164
164
  return config.get_default(option)
165
165
 
166
- logging.warning('Invalid option: %s, not present in game configuration!' % option)
166
+ logger.warning('Invalid option: %s, not present in game configuration!' % option)
167
167
  return ''
168
168
 
169
169
  def get_option_type(self, option: str) -> str:
@@ -176,7 +176,7 @@ class BaseApp(ABC):
176
176
  if option in config.options:
177
177
  return config.get_type(option)
178
178
 
179
- logging.warning('Invalid option: %s, not present in game configuration!' % option)
179
+ logger.warning('Invalid option: %s, not present in game configuration!' % option)
180
180
  return ''
181
181
 
182
182
  def get_option_help(self, option: str) -> str:
@@ -189,7 +189,7 @@ class BaseApp(ABC):
189
189
  if option in config.options:
190
190
  return config.options[option].help
191
191
 
192
- logging.warning('Invalid option: %s, not present in game configuration!' % option)
192
+ logger.warning('Invalid option: %s, not present in game configuration!' % option)
193
193
  return ''
194
194
 
195
195
  def option_value_updated(self, option: str, previous_value, new_value) -> bool | None:
@@ -226,18 +226,18 @@ class BaseApp(ABC):
226
226
  post_result = self.option_value_updated(option, previous_value, new_value)
227
227
  if post_result is True:
228
228
  # Post-update either returned a successful operation or nothing at all, either is fine.
229
- logging.info('Updated option %s to %s and ran post-update actions successfully' % (option, value))
229
+ logger.info('Updated option %s to %s and ran post-update actions successfully' % (option, value))
230
230
  return True
231
231
  elif post_result is None:
232
- logging.debug('Post-update returned None, this is fine as it indicates no post-actions taken')
233
- logging.info('Updated option %s to %s' % (option, value))
232
+ logger.debug('Post-update returned None, this is fine as it indicates no post-actions taken')
233
+ logger.info('Updated option %s to %s' % (option, value))
234
234
  return True
235
235
  else:
236
236
  # Post-update explictly returned False, this indicates a problem occurred.
237
- logging.warning('Configuration saved, but unable to complete post-update actions!')
237
+ logger.warning('Configuration saved, but unable to complete post-update actions!')
238
238
  return False
239
239
 
240
- logging.warning('Invalid option: %s, not present in game configuration!' % option)
240
+ logger.warning('Invalid option: %s, not present in game configuration!' % option)
241
241
  return False
242
242
 
243
243
  def get_option_options(self, option: str):
@@ -250,7 +250,7 @@ class BaseApp(ABC):
250
250
  if option in config.options:
251
251
  return config.get_options(option)
252
252
 
253
- logging.warning('Invalid option: %s, not present in game configuration!' % option)
253
+ logger.warning('Invalid option: %s, not present in game configuration!' % option)
254
254
  return []
255
255
 
256
256
  def get_option_group(self, option: str):
@@ -263,7 +263,7 @@ class BaseApp(ABC):
263
263
  if option in config.options:
264
264
  return config.options[option].group
265
265
 
266
- logging.warning('Invalid option: %s, not present in game configuration!' % option)
266
+ logger.warning('Invalid option: %s, not present in game configuration!' % option)
267
267
  return 'Options'
268
268
 
269
269
  def prompt_option(self, option: str):
@@ -376,11 +376,11 @@ class BaseApp(ABC):
376
376
  """
377
377
 
378
378
  if action not in ['stop', 'restart', 'update']:
379
- logging.error('Invalid action for delayed action: %s' % action)
379
+ logger.error('Invalid action for delayed action: %s' % action)
380
380
  return
381
381
 
382
382
  if os.geteuid() != 0:
383
- logging.error('Unable to %s game service unless run with sudo' % action)
383
+ logger.error('Unable to %s game service unless run with sudo' % action)
384
384
  return
385
385
 
386
386
  msg = self.get_option_value('%s_delayed' % action)
@@ -391,7 +391,7 @@ class BaseApp(ABC):
391
391
  services_running = []
392
392
  services = self.get_services()
393
393
 
394
- logging.info(
394
+ logger.info(
395
395
  'Starting delayed %s action for all services, this gives current players up to an hour to log off safely' %
396
396
  action
397
397
  )
@@ -413,7 +413,7 @@ class BaseApp(ABC):
413
413
 
414
414
  if player_count == 0 or player_count is None:
415
415
  # No players online, stop the service
416
- logging.info('Stopping %s as no players are online.' % service.service)
416
+ logger.info('Stopping %s as no players are online.' % service.service)
417
417
  service.stop()
418
418
  else:
419
419
  # Still online, check to see if we should send a message
@@ -427,7 +427,7 @@ class BaseApp(ABC):
427
427
  service.send_message(player_msg)
428
428
 
429
429
  if minutes_left % 5 == 0 and minutes_left > 5:
430
- logging.info('%s minutes remaining before %s.' % (str(minutes_left), action))
430
+ logger.info('%s minutes remaining before %s.' % (str(minutes_left), action))
431
431
 
432
432
  if not still_running or minutes_left <= 0:
433
433
  # No services are running, stop the timer
@@ -443,7 +443,7 @@ class BaseApp(ABC):
443
443
  # Now that all services have been stopped, restart any that were running before
444
444
  for service in services:
445
445
  if service.service in services_running:
446
- logging.info('Starting %s' % service.service)
446
+ logger.info('Starting %s' % service.service)
447
447
  service.start()
448
448
 
449
449
  def get_services(self) -> list['BaseService']:
@@ -659,7 +659,7 @@ class BaseApp(ABC):
659
659
  for config in self.configs.values():
660
660
  if config.path and os.path.exists(config.path):
661
661
  os.remove(config.path)
662
- logging.info('Removed config file for %s at %s' % (self.name, config.path))
662
+ logger.info('Removed config file for %s at %s' % (self.name, config.path))
663
663
 
664
664
  # Cleanup directory structure
665
665
  shutil.rmtree(os.path.join(utils.get_base_directory(), 'AppFiles'))
@@ -3,11 +3,11 @@ import re
3
3
  import sys
4
4
  import time
5
5
  from abc import ABC
6
- import logging
7
6
 
8
- from .base_app import BaseApp
7
+ from warlock_manager.apps.base_app import BaseApp
9
8
  from warlock_manager.libs.cmd import Cmd
10
9
  from warlock_manager.libs import utils
10
+ from warlock_manager.libs.logger import logger
11
11
 
12
12
 
13
13
  def guess_steamcmd_path() -> str:
@@ -21,7 +21,7 @@ def guess_steamcmd_path() -> str:
21
21
  )
22
22
  for path in paths:
23
23
  if os.path.exists(path):
24
- logging.debug('Found steamcmd at %s' % path)
24
+ logger.debug('Found steamcmd at %s' % path)
25
25
  return path
26
26
  raise FileNotFoundError('steamcmd not found in common locations. Please ensure steamcmd is installed.')
27
27
 
@@ -290,11 +290,11 @@ class SteamApp(BaseApp, ABC):
290
290
  return []
291
291
 
292
292
  if 'depots' not in info:
293
- logging.warning(f"No depot information found for app {self.steam_id}.")
293
+ logger.warning(f"No depot information found for app {self.steam_id}.")
294
294
  return []
295
295
 
296
296
  if 'branches' not in info['depots']:
297
- logging.warning(f"No branch information found for app {self.steam_id}.")
297
+ logger.warning(f"No branch information found for app {self.steam_id}.")
298
298
  return []
299
299
 
300
300
  return list(info['depots']['branches'].keys())
@@ -366,18 +366,18 @@ class SteamApp(BaseApp, ABC):
366
366
 
367
367
  :return:
368
368
  """
369
- logging.info('Updating game %s via Steam...' % self.name)
369
+ logger.info('Updating game %s via Steam...' % self.name)
370
370
  # Stop any running services before updating
371
371
  services = []
372
372
  for service in self.get_services():
373
373
  if service.is_running() or service.is_starting():
374
- logging.info('Stopping service %s for update...' % service.service)
375
- services.append(service.service)
374
+ logger.info('Stopping service %s for update...' % service.service)
375
+ services.append(service)
376
376
  service.stop()
377
377
 
378
378
  if len(services) > 0:
379
379
  # Wait for all services to stop, may take 5 minutes if players are online.
380
- logging.info('Waiting up to 5 minutes for all services to stop...')
380
+ logger.info('Waiting up to 5 minutes for all services to stop...')
381
381
  counter = 0
382
382
  while counter < 30:
383
383
  all_stopped = True
@@ -390,7 +390,7 @@ class SteamApp(BaseApp, ABC):
390
390
  break
391
391
  time.sleep(10)
392
392
  else:
393
- logging.info('No running services found, proceeding with update...')
393
+ logger.info('No running services found, proceeding with update...')
394
394
 
395
395
  cmd = Cmd([
396
396
  guess_steamcmd_path(),
@@ -423,7 +423,7 @@ class SteamApp(BaseApp, ABC):
423
423
  self.post_update()
424
424
 
425
425
  if len(services) > 0:
426
- logging.info('Update completed, restarting previously running services...')
426
+ logger.info('Update completed, restarting previously running services...')
427
427
  for service in services:
428
428
  service.start()
429
429
 
@@ -3,9 +3,9 @@ from typing import Union
3
3
  import configparser
4
4
  import tempfile
5
5
  import os
6
- import logging
7
6
 
8
7
  from warlock_manager.config.base_config import BaseConfig
8
+ from warlock_manager.libs.logger import logger
9
9
 
10
10
 
11
11
  class INIConfig(BaseConfig):
@@ -65,13 +65,13 @@ class INIConfig(BaseConfig):
65
65
  section = self.group
66
66
 
67
67
  if section is None:
68
- logging.error(
68
+ logger.error(
69
69
  'Cannot set INI config value for option %s because it does not have a section defined!' %
70
70
  name
71
71
  )
72
72
  return
73
73
 
74
- logging.debug('Setting INI config value: %s => [%s] %s = %s' % (name, section, opt.key, str_value))
74
+ logger.debug('Setting INI config value: %s => [%s] %s = %s' % (name, section, opt.key, str_value))
75
75
 
76
76
  # Escape '%' characters that may be present
77
77
  str_value = str_value.replace('%', '%%')
@@ -118,10 +118,10 @@ class INIConfig(BaseConfig):
118
118
  if self.spoof_group:
119
119
  with open(self.path, 'r') as f:
120
120
  self.parser.read_string('[%s]\n' % self.group + f.read())
121
- logging.debug('Loaded INI config %s with spoofed group: %s' % (self.path, self.group))
121
+ logger.debug('Loaded INI config %s with spoofed group: %s' % (self.path, self.group))
122
122
  else:
123
123
  self.parser.read(self.path)
124
- logging.debug('Loaded INI config: %s' % self.path)
124
+ logger.debug('Loaded INI config: %s' % self.path)
125
125
 
126
126
  def save(self):
127
127
  """
@@ -1,4 +1,3 @@
1
- import logging
2
1
  import os
3
2
  import sys
4
3
 
@@ -9,6 +8,7 @@ from warlock_manager.libs.tui import print_header, Table, print_subheader, promp
9
8
  prompt_long_text
10
9
  from warlock_manager.apps.base_app import BaseApp
11
10
  from warlock_manager.services.base_service import BaseService
11
+ from warlock_manager.libs.logger import logger
12
12
 
13
13
 
14
14
  ICON_ENABLED = '✅'
@@ -223,11 +223,11 @@ def menu_mods(source: BaseService):
223
223
  if add_help is not None:
224
224
  add_help = add_help.strip().split('\n')[0].strip()
225
225
  else:
226
- logging.debug('Mod handler does not provide help for mods search.')
226
+ logger.debug('Mod handler does not provide help for mods search.')
227
227
  else:
228
- logging.debug('Mod handler does not support mods search.')
228
+ logger.debug('Mod handler does not support mods search.')
229
229
  else:
230
- logging.error('Mod handler is not available for this application.')
230
+ logger.error('Mod handler is not available for this application.')
231
231
  return
232
232
 
233
233
  counter = 0
@@ -435,7 +435,7 @@ def menu_service(service: BaseService):
435
435
 
436
436
  if opt.isdigit() and 1 <= int(opt) <= counter:
437
437
  if service.is_running():
438
- logging.warning('Cannot configure options for a service while it is running.')
438
+ logger.warning('Cannot configure options for a service while it is running.')
439
439
  else:
440
440
  menu_config_option(service, options_ordered[int(opt) - 1])
441
441
  elif opt == 'b':
@@ -1,31 +1,14 @@
1
1
  import json
2
2
  import logging
3
- import inspect
4
3
  import sys
5
4
  import typer
6
5
  from typing import Annotated
7
6
  from warlock_manager.apps.base_app import BaseApp
8
7
  from warlock_manager.services.base_service import BaseService
9
- from warlock_manager.libs.sensitive_data_filter import sensitive_data_filter
10
8
  from warlock_manager.libs.app import default_menu_main
11
9
  from warlock_manager.libs.meta import get_meta
12
10
  from warlock_manager.nexus.nexus import Nexus
13
-
14
-
15
- class ClassNameFilter(logging.Filter):
16
- def filter(self, record):
17
- # Try to get the class name from the call stack
18
- frame = inspect.currentframe()
19
- while frame:
20
- if 'self' in frame.f_locals:
21
- class_name = frame.f_locals['self'].__class__.__name__
22
- if class_name not in ['ClassNameFilter', 'RootLogger']:
23
- record.classname = frame.f_locals['self'].__class__.__name__
24
- break
25
- frame = frame.f_back
26
- else:
27
- record.classname = ''
28
- return True
11
+ from warlock_manager.libs.logger import logger
29
12
 
30
13
 
31
14
  def app_runner(game: BaseApp):
@@ -54,6 +37,7 @@ def app_runner(game: BaseApp):
54
37
  :param value:
55
38
  :return: BaseService | None
56
39
  """
40
+ logger.debug('Resolving service: %s' % value)
57
41
  if value is None:
58
42
  return None
59
43
  services = game.get_services()
@@ -127,16 +111,10 @@ def app_runner(game: BaseApp):
127
111
  debug: arg_debug = False
128
112
  ):
129
113
  log_level = logging.DEBUG if debug else logging.INFO
130
- logging.basicConfig(
131
- level=log_level,
132
- format='%(asctime)s [%(levelname)s] %(classname)s.%(funcName)s: %(message)s',
133
- force=True
134
- )
135
- logging.getLogger().addFilter(ClassNameFilter())
136
- logging.getLogger().addFilter(sensitive_data_filter)
114
+ logger.setLevel(log_level)
137
115
 
138
116
  if debug:
139
- logging.debug('Debug logging enabled')
117
+ logger.debug('Debug logging enabled')
140
118
 
141
119
  # If no subcommand was provided, call main()
142
120
  if ctx.invoked_subcommand is None:
@@ -257,7 +235,7 @@ def app_runner(game: BaseApp):
257
235
  sys.exit(0 if service.backup(max_backups) else 1)
258
236
  else:
259
237
  if len(game.get_services()) == 0:
260
- logging.warning('No services are available for backup, nothing to do.')
238
+ logger.warning('No services are available for backup, nothing to do.')
261
239
  sys.exit(1)
262
240
  success = True
263
241
  for svc in game.get_services():
@@ -394,6 +372,7 @@ def app_runner(game: BaseApp):
394
372
  :param service: BaseService | None
395
373
  :return:
396
374
  """
375
+ logger.debug('Running get_metrics()')
397
376
  nexus = Nexus()
398
377
  if service and isinstance(service, BaseService):
399
378
  services: list[BaseService] = [service]
@@ -1,11 +1,11 @@
1
1
  import os
2
2
  import subprocess
3
3
  import json
4
- import logging
5
4
  import time
6
5
  import pwd
7
6
 
8
7
  from warlock_manager.libs import cache
8
+ from warlock_manager.libs.logger import logger
9
9
 
10
10
 
11
11
  class CmdFakeResponse:
@@ -223,13 +223,13 @@ class Cmd:
223
223
  :return:
224
224
  """
225
225
  if self.result is None:
226
- logging.debug('Running command: %s' % ' '.join(self.cmd))
226
+ logger.debug('Running command: %s' % ' '.join(self.cmd))
227
227
  if self.memory_cacheable is not False:
228
228
  key = ' '.join(self.cmd)
229
229
  if key in self._memory_cache:
230
- cached_time, cached = Cmd._memory_cache[key]
230
+ cached_time, cached, code = Cmd._memory_cache[key]
231
231
  if cached_time + self.memory_cacheable >= time.time():
232
- logging.debug('Using memory cached result instead')
232
+ logger.debug('Using memory cached result instead')
233
233
  self.result = CmdFakeResponse(
234
234
  cached if self.uses == 'stdout' else '',
235
235
  cached if self.uses == 'stderr' else '',
@@ -240,7 +240,7 @@ class Cmd:
240
240
  if self.cacheable is not False:
241
241
  cached = self.try_cache()
242
242
  if cached is not None:
243
- logging.debug('Using cached result instead')
243
+ logger.debug('Using cached result instead')
244
244
  self.result = CmdFakeResponse(
245
245
  cached if self.uses == 'stdout' else '',
246
246
  cached if self.uses == 'stderr' else '',
@@ -263,22 +263,23 @@ class Cmd:
263
263
  self.result = CmdFakeResponse('', str(e), 1)
264
264
  finally:
265
265
  if self.result.stdout:
266
- logging.debug('STDOUT: %s' % self.result.stdout.strip())
266
+ logger.debug('STDOUT: %s' % self.result.stdout.strip())
267
267
  if self.result.stderr:
268
- logging.debug('STDERR: %s' % self.result.stderr.strip())
269
- logging.debug('Return code: %d' % self.result.returncode)
268
+ logger.debug('STDERR: %s' % self.result.stderr.strip())
269
+ logger.debug('Return code: %d' % self.result.returncode)
270
+
271
+ # Cache all responses to memory if requested, saves time on failed lookup checks.
272
+ if self.memory_cacheable is not False:
273
+ key = ' '.join(self.cmd)
274
+ if self.uses == 'stdout':
275
+ Cmd._memory_cache[key] = (time.time(), self.result.stdout, self.result.returncode)
276
+ elif self.uses == 'stderr':
277
+ Cmd._memory_cache[key] = (time.time(), self.result.stderr, self.result.returncode)
278
+ else:
279
+ logger.warning('Attempting to cache command output without capturing it. This is not supported!')
270
280
 
271
281
  if self.result.returncode == 0:
272
- # Check to see if this result should be cached on either the filesystem and/or memory
273
- if self.memory_cacheable is not False:
274
- key = ' '.join(self.cmd)
275
- if self.uses == 'stdout':
276
- Cmd._memory_cache[key] = (time.time(), self.result.stdout)
277
- elif self.uses == 'stderr':
278
- Cmd._memory_cache[key] = (time.time(), self.result.stderr)
279
- else:
280
- logging.warning('Attempting to cache command output without capturing it. This is not supported!')
281
-
282
+ # Successful executions can be cached to disk
282
283
  if self.cacheable is not False:
283
284
  # Do we save stdout or stderr?
284
285
  if self.uses == 'stdout':
@@ -286,7 +287,7 @@ class Cmd:
286
287
  elif self.uses == 'stderr':
287
288
  cache.save_cache(' '.join(self.cmd), self.result.stderr)
288
289
  else:
289
- logging.warning('Attempting to cache command output without capturing it. This is not supported!')
290
+ logger.warning('Attempting to cache command output without capturing it. This is not supported!')
290
291
 
291
292
  return self.result
292
293
 
@@ -323,10 +324,10 @@ class PipeCmd(Cmd):
323
324
  if self.result is None:
324
325
 
325
326
  if self.cacheable is not False:
326
- logging.warning('Piped commands cannot be cached!')
327
+ logger.warning('Piped commands cannot be cached!')
327
328
 
328
329
  try:
329
- logging.debug('Running piped command: %s' % ' '.join(self.cmd))
330
+ logger.debug('Running piped command: %s' % ' '.join(self.cmd))
330
331
  self.result = subprocess.Popen(
331
332
  self.cmd,
332
333
  cwd=self._cwd,
@@ -355,10 +356,10 @@ class BackgroundCmd(Cmd):
355
356
  if self.result is None:
356
357
 
357
358
  if self.cacheable is not False:
358
- logging.warning('Background commands cannot be cached!')
359
+ logger.warning('Background commands cannot be cached!')
359
360
 
360
361
  try:
361
- logging.debug('Running background command: %s' % ' '.join(self.cmd))
362
+ logger.debug('Running background command: %s' % ' '.join(self.cmd))
362
363
  self.result = subprocess.Popen(
363
364
  self.cmd,
364
365
  cwd=self._cwd,
@@ -1,9 +1,9 @@
1
- import logging
2
1
  import requests
3
2
  import json
4
3
  from warlock_manager.libs import utils
5
4
  from warlock_manager.libs import cache
6
5
  from warlock_manager.libs.meta import get_meta
6
+ from warlock_manager.libs.logger import logger
7
7
 
8
8
  # "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
9
9
  USER_AGENT = 'Warlock Manager/%s (warlock.nexus) <staff@bitsnbytes.dev>' % get_meta()['version']
@@ -18,7 +18,7 @@ def download_file(url: str, destination: str):
18
18
  :param destination: The local file path to save the downloaded file to
19
19
  :return:
20
20
  """
21
- logging.debug('Downloading file %s to %s' % (url, destination))
21
+ logger.debug('Downloading file %s to %s' % (url, destination))
22
22
  # Ensure the target directory exists
23
23
  utils.ensure_file_parent_exists(destination)
24
24
 
@@ -44,7 +44,7 @@ def download_json(url: str) -> dict:
44
44
  :param url: The URL to download from
45
45
  :return: The JSON data as a dictionary
46
46
  """
47
- logging.debug('Downloading JSON %s' % url)
47
+ logger.debug('Downloading JSON %s' % url)
48
48
 
49
49
  # Try the cache first
50
50
  cached = cache.get_cache(url)
@@ -1,5 +1,5 @@
1
1
  from warlock_manager.libs.cmd import Cmd
2
- import logging
2
+ from warlock_manager.libs.logger import logger
3
3
 
4
4
 
5
5
  class Firewall:
@@ -92,11 +92,11 @@ class Firewall:
92
92
  """
93
93
 
94
94
  if port <= 0 or port >= 65536:
95
- logging.error(f"Invalid port number: {port}")
95
+ logger.error(f"Invalid port number: {port}")
96
96
  return False
97
97
 
98
98
  if protocol.lower() not in ['tcp', 'udp']:
99
- logging.error(f"Invalid protocol: {protocol}")
99
+ logger.error(f"Invalid protocol: {protocol}")
100
100
  return False
101
101
 
102
102
  firewall = cls.get_available()
@@ -104,20 +104,20 @@ class Firewall:
104
104
  if firewall == 'ufw':
105
105
  # UFW requires the protocol to be all lowercase.
106
106
  protocol = protocol.lower()
107
- logging.info(f"Allowing {port}/{protocol} via UFW")
107
+ logger.info(f"Allowing {port}/{protocol} via UFW")
108
108
  cmd = Cmd(['ufw', 'allow', f'{port}/{protocol}'])
109
109
  if comment:
110
110
  cmd.extend(['comment', comment])
111
111
  return cmd.success
112
112
 
113
113
  elif firewall == 'firewalld':
114
- logging.info(f"Allowing {port}/{protocol} via Firewalld")
114
+ logger.info(f"Allowing {port}/{protocol} via Firewalld")
115
115
  if Cmd(['firewall-cmd', '--permanent', '--add-port', f'{port}/{protocol}']).success:
116
116
  Cmd(['firewall-cmd', '--reload']).run()
117
117
  return True
118
118
 
119
119
  elif firewall == 'iptables':
120
- logging.info(f"Allowing {port}/{protocol} via iptables")
120
+ logger.info(f"Allowing {port}/{protocol} via iptables")
121
121
  cmd = Cmd(['iptables', '-A', 'INPUT', '-p', protocol, '--dport', str(port), '-j', 'ACCEPT'])
122
122
  if comment:
123
123
  cmd.extend(['-m', 'comment', '--comment', comment])
@@ -126,7 +126,7 @@ class Firewall:
126
126
  return True
127
127
 
128
128
  else:
129
- logging.error('No supported firewall found on the system.')
129
+ logger.error('No supported firewall found on the system.')
130
130
 
131
131
  return False
132
132
 
@@ -142,11 +142,11 @@ class Firewall:
142
142
  """
143
143
 
144
144
  if port <= 0 or port >= 65536:
145
- logging.error(f"Invalid port number: {port}")
145
+ logger.error(f"Invalid port number: {port}")
146
146
  return False
147
147
 
148
148
  if protocol.lower() not in ['tcp', 'udp']:
149
- logging.error(f"Invalid protocol: {protocol}")
149
+ logger.error(f"Invalid protocol: {protocol}")
150
150
  return False
151
151
 
152
152
  firewall = cls.get_available()
@@ -165,7 +165,7 @@ class Firewall:
165
165
  return True
166
166
 
167
167
  else:
168
- logging.error('No supported firewall found on the system.')
168
+ logger.error('No supported firewall found on the system.')
169
169
 
170
170
  return False
171
171
 
@@ -219,5 +219,5 @@ class Firewall:
219
219
  return False
220
220
 
221
221
  else:
222
- logging.error('No supported firewall found on the system.')
222
+ logger.error('No supported firewall found on the system.')
223
223
  return True # No firewall means it's probably enabled by default, so we return true.
@@ -1,7 +1,6 @@
1
- import logging
2
-
3
1
  from warlock_manager.libs.version import extract_version_from_string, parse_version
4
2
  from warlock_manager.libs.cmd import Cmd
3
+ from warlock_manager.libs.logger import logger
5
4
 
6
5
 
7
6
  def get_java_paths() -> list[str]:
@@ -50,7 +49,7 @@ def _check_java_versions(java_paths: list[str], target_version: int) -> str | No
50
49
  :param target_version: The major Java version to find
51
50
  :return: The path to the matching Java executable, or None if not found
52
51
  """
53
- logging.debug('Searching for Java version %d' % target_version)
52
+ logger.debug('Searching for Java version %d' % target_version)
54
53
  for java_path in java_paths:
55
54
  result = Cmd([java_path, '-version'])
56
55
  # Java version information is typically printed to stderr, so we need to use that instead of stdout.
@@ -62,7 +61,7 @@ def _check_java_versions(java_paths: list[str], target_version: int) -> str | No
62
61
  # Use the version library to parse this version string.
63
62
  version_str = extract_version_from_string(version_str)
64
63
  version = parse_version(version_str)
65
- logging.debug('%s => %s' % (java_path, version))
64
+ logger.debug('%s => %s' % (java_path, version))
66
65
  if version.major == 1:
67
66
  # For Java 8 and earlier, the version string starts with "1.", so we need to check the minor version
68
67
  if version.minor == target_version: