atomicshop 2.12.17__py3-none-any.whl → 2.12.19__py3-none-any.whl

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.

Potentially problematic release.


This version of atomicshop might be problematic. Click here for more details.

atomicshop/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  """Atomic Basic functions and classes to make developer life easier"""
2
2
 
3
3
  __author__ = "Den Kras"
4
- __version__ = '2.12.17'
4
+ __version__ = '2.12.19'
atomicshop/diff_check.py CHANGED
@@ -207,7 +207,7 @@ class DiffChecker:
207
207
  self.new_objects_seconds_then_difference: Union[float, None] = None
208
208
  self.timer = None
209
209
 
210
- def _static_pre_process(self):
210
+ def initiate_before_action(self):
211
211
  """
212
212
  This function will be called before the actual checking of the object.
213
213
  If you change any attribute of the class, you will need to call this function again.
@@ -254,7 +254,8 @@ class DiffChecker:
254
254
  self.previous_day = None
255
255
 
256
256
  if self.new_objects_hours_then_difference and self.operation_type != 'new_objects':
257
- raise ValueError("The 'new_objects_hours_then_difference' variable must be set for 'new_objects' operation type.")
257
+ raise ValueError(
258
+ "The 'new_objects_hours_then_difference' variable must be set for 'new_objects' operation type.")
258
259
 
259
260
  if self.new_objects_hours_then_difference:
260
261
  self.new_objects_seconds_then_difference = self.new_objects_hours_then_difference * 60 * 60
@@ -266,8 +267,6 @@ class DiffChecker:
266
267
  The function will check file content for change by hashing it and comparing the hash.
267
268
  """
268
269
 
269
- self._static_pre_process()
270
-
271
270
  if not isinstance(self.check_object, str):
272
271
  raise TypeError(f"[check_object] must be string, not {type(self.check_object)}.")
273
272
 
@@ -287,8 +286,6 @@ class DiffChecker:
287
286
  :param print_kwargs: dict, of kwargs to pass to 'print_api' function.
288
287
  """
289
288
 
290
- self._static_pre_process()
291
-
292
289
  if not isinstance(self.check_object, list):
293
290
  raise TypeError(f'[check_object] must be list, not {type(self.check_object)}.')
294
291
 
@@ -102,8 +102,10 @@ def write_file(
102
102
  content = '\n'.join(content)
103
103
  else:
104
104
  file_object.writelines(content)
105
-
106
- if isinstance(content, str):
105
+ elif isinstance(content, str):
106
+ file_object.write(content)
107
+ # THis will happen if the content is bytes and the file mode is 'wb'.
108
+ elif isinstance(content, bytes) and 'b' in file_mode:
107
109
  file_object.write(content)
108
110
  else:
109
111
  raise TypeError(f"Content type is not supported: {type(content)}")
@@ -1,8 +1,6 @@
1
1
  from typing import Literal, Union
2
- from pathlib import Path
3
2
 
4
- from .checks import dns, network, hash, process_running
5
- from .. import filesystem, scheduling
3
+ from .checks import dns, network, file, url, process_running
6
4
 
7
5
 
8
6
  DNS__DEFAULT_SETTINGS = {
@@ -122,36 +120,31 @@ class ChangeMonitor:
122
120
 
123
121
  # === Additional variables ========================================
124
122
 
125
- # self.original_object_directory = None
126
- # self.original_object_file_path = None
127
-
128
- # # If 'store_original_object' is True, create directory for original object.
129
- # if self.store_original_object:
130
- # # Make path for original object.
131
- # self.original_object_directory = filesystem.add_object_to_path(
132
- # self.input_directory, 'Original')
133
- # # Create directory if it doesn't exist.
134
- # filesystem.create_directory(self.original_object_directory)
135
- #
136
- # Initialize objects for DNS and Network monitoring.
137
-
138
123
  self.checks_instance = None
139
124
  self._setup_object()
140
125
 
141
126
  def _setup_object(self):
142
- if self.object_type == 'file' or 'url_' in self.object_type:
143
- self.checks_instance = hash
144
- if self.object_type == 'dns':
145
- self.checks_instance = dns
127
+ if self.object_type == 'file':
128
+ if not self.object_type_settings:
129
+ self.object_type_settings = FILE__URL__DEFAULT_SETTINGS
146
130
 
131
+ self.checks_instance = file.FileCheck(self)
132
+ elif self.object_type.startswith('url_'):
133
+ if not self.object_type_settings:
134
+ self.object_type_settings = FILE__URL__DEFAULT_SETTINGS
135
+
136
+ self.checks_instance = url.UrlCheck(self)
137
+ elif self.object_type == 'dns':
147
138
  if not self.object_type_settings:
148
139
  self.object_type_settings = DNS__DEFAULT_SETTINGS
140
+
141
+ self.checks_instance = dns.DnsCheck(self)
149
142
  elif self.object_type == 'network':
150
- self.checks_instance = network
143
+ self.checks_instance = network.NetworkCheck(self)
151
144
  elif self.object_type == 'process_running':
152
- self.checks_instance = process_running
153
-
154
- self.checks_instance.setup_check(self)
145
+ self.checks_instance = process_running.ProcessRunningCheck(self)
146
+ else:
147
+ raise ValueError(f"ERROR: Unknown object type: {self.object_type}")
155
148
 
156
149
  def check_cycle(self, print_kwargs: dict = None):
157
150
  """
@@ -1,126 +1,137 @@
1
1
  from pathlib import Path
2
+ from typing import Union
2
3
 
3
4
  from ...etw.dns_trace import DnsTrace
4
5
  from ...print_api import print_api
5
- from ...diff_check import DiffChecker
6
+ from ...import diff_check
6
7
 
7
8
 
8
9
  INPUT_FILE_DEFAULT_NAME: str = 'known_domains.json'
9
10
  INPUT_STATISTICS_FILE_DEFAULT_NAME: str = 'dns_statistics.json'
10
- FETCH_ENGINE: DnsTrace = DnsTrace(enable_process_poller=True, attrs=['name', 'cmdline', 'domain', 'query_type'])
11
- SETTINGS = {}
12
- DIFF_CHECKER_AGGREGATION = DiffChecker(
13
- check_object=list(), # DNS events will be appended to this list.
14
- return_first_cycle=True,
15
- operation_type='new_objects'
16
- )
17
- DIFF_CHECKER_STATISTICS = DiffChecker(
18
- check_object=list(), # DNS events will be appended to this list.
19
- return_first_cycle=True,
20
- operation_type='hit_statistics',
21
- hit_statistics_enable_queue=True
22
- )
23
11
 
24
12
 
25
- def setup_check(change_monitor_instance):
26
- global SETTINGS
27
- SETTINGS = change_monitor_instance.object_type_settings
28
-
29
- if SETTINGS['alert_always'] and SETTINGS['alert_about_missing_entries_after_learning']:
30
- raise ValueError(
31
- "ERROR: [alert_always] and [alert_about_missing_entries_after_learning] cannot be True at the same time.")
32
-
33
- if not change_monitor_instance.input_file_name:
34
- change_monitor_instance.input_file_name = INPUT_FILE_DEFAULT_NAME
35
- input_file_path = (
36
- str(Path(change_monitor_instance.input_directory, change_monitor_instance.input_file_name)))
37
-
38
- if not change_monitor_instance.input_statistics_file_name:
39
- change_monitor_instance.input_statistics_file_name = INPUT_STATISTICS_FILE_DEFAULT_NAME
40
- input_statistic_file_path = (
41
- str(Path(change_monitor_instance.input_directory, change_monitor_instance.input_statistics_file_name)))
42
-
43
- if SETTINGS['learning_mode_create_unique_entries_list']:
44
- DIFF_CHECKER_AGGREGATION.input_file_write_only = change_monitor_instance.input_file_write_only
45
- DIFF_CHECKER_AGGREGATION.check_object_display_name = \
46
- f'{change_monitor_instance.input_file_name}|{change_monitor_instance.object_type}'
47
- DIFF_CHECKER_AGGREGATION.input_file_path = input_file_path
48
- DIFF_CHECKER_AGGREGATION.new_objects_hours_then_difference = SETTINGS['learning_hours']
49
-
50
- if SETTINGS['create_alert_statistics']:
51
- DIFF_CHECKER_STATISTICS.input_file_write_only = change_monitor_instance.input_file_write_only
52
- DIFF_CHECKER_STATISTICS.check_object_display_name = \
53
- f'{change_monitor_instance.input_statistics_file_name}|{change_monitor_instance.object_type}'
54
- DIFF_CHECKER_STATISTICS.input_file_path = input_statistic_file_path
55
- DIFF_CHECKER_STATISTICS.hit_statistics_input_file_rotation_cycle_hours = SETTINGS['statistics_rotation_hours']
56
-
57
- # Start DNS monitoring.
58
- FETCH_ENGINE.start()
59
-
60
-
61
- def execute_cycle(print_kwargs: dict = None) -> list:
13
+ class DnsCheck:
62
14
  """
63
- This function executes the cycle of the change monitor: dns.
64
- The function is blocking so while using it, the script will wait for the next DNS event.
65
- No need to use 'time.sleep()'.
66
-
67
- :param print_kwargs: print_api kwargs.
68
- :return: List of dictionaries with the results of the cycle.
15
+ Class for DNS monitoring.
69
16
  """
70
-
71
- # 'emit()' method is blocking (it uses 'get' of queue instance)
72
- # will return a dict with current DNS trace event.
73
- event_dict = FETCH_ENGINE.emit()
74
-
75
- return_list = list()
76
- if SETTINGS['learning_mode_create_unique_entries_list']:
77
- _aggregation_process(event_dict, return_list, print_kwargs)
78
-
79
- if SETTINGS['create_alert_statistics'] and SETTINGS['alert_always']:
80
- _statistics_process(event_dict, return_list, print_kwargs)
81
-
82
- return return_list
83
-
84
-
85
- def _aggregation_process(event_dict: dict, return_list: list, print_kwargs: dict = None):
86
- DIFF_CHECKER_AGGREGATION.check_object = [event_dict]
87
-
88
- # Check if 'known_domains' list was updated from previous cycle.
89
- result, message = DIFF_CHECKER_AGGREGATION.check_list_of_dicts(
90
- sort_by_keys=['cmdline', 'name'], print_kwargs=print_kwargs)
91
-
92
- if result:
93
- # Check if 'updated' key is in the result. This means that this is a regular cycle.
94
- if 'updated' in result:
95
- if not result['time_passed']:
96
- # Get list of new connections only.
97
- # new_connections_only: list = list_of_dicts.get_difference(result['old'], result['updated'])
98
-
99
- for connection in result['updated']:
100
- message = \
101
- f"[Learning] New Domain Added: {connection['name']} | " \
102
- f"{connection['domain']} | {connection['query_type']} | " \
103
- f"{connection['cmdline']}"
104
- print_api(message, color='yellow', **(print_kwargs or {}))
105
-
106
- return_list.append(message)
107
-
108
- # Check if learning time passed, so we can alert the new entries.
109
- if 'time_passed' in result:
110
- if result['time_passed']:
111
- _statistics_process(result['updated'], return_list, print_kwargs)
112
-
113
-
114
- def _statistics_process(event_dict: dict, return_list: list, print_kwargs: dict = None):
115
- DIFF_CHECKER_STATISTICS.check_object = [event_dict]
116
-
117
- # Check if 'known_domains' list was updated from previous cycle.
118
- result, message = DIFF_CHECKER_STATISTICS.check_list_of_dicts(
119
- sort_by_keys=['cmdline', 'name'], print_kwargs=print_kwargs)
120
-
121
- if result:
122
- if 'count' in result:
123
- message = f"[Alert] DNS Request: {result['entry']} | Times hit: {result['count']}"
124
- print_api(message, color='yellow', **(print_kwargs or {}))
125
-
126
- return_list.append(message)
17
+
18
+ def __init__(self, change_monitor_instance):
19
+ self.change_monitor_instance = change_monitor_instance
20
+ self.diff_checker_aggregation: Union[diff_check.DiffChecker, None] = None
21
+ self.diff_checker_statistics: Union[diff_check.DiffChecker, None] = None
22
+ self.settings: dict = change_monitor_instance.object_type_settings
23
+ self.fetch_engine: DnsTrace = (
24
+ DnsTrace(enable_process_poller=True, attrs=['name', 'cmdline', 'domain', 'query_type']))
25
+
26
+ if self.settings['alert_always'] and self.settings['alert_about_missing_entries_after_learning']:
27
+ raise ValueError(
28
+ "ERROR: [alert_always] and [alert_about_missing_entries_after_learning] "
29
+ "cannot be True at the same time.")
30
+
31
+ if not change_monitor_instance.input_file_name:
32
+ change_monitor_instance.input_file_name = INPUT_FILE_DEFAULT_NAME
33
+ input_file_path = (
34
+ str(Path(change_monitor_instance.input_directory, change_monitor_instance.input_file_name)))
35
+
36
+ if not change_monitor_instance.input_statistics_file_name:
37
+ change_monitor_instance.input_statistics_file_name = INPUT_STATISTICS_FILE_DEFAULT_NAME
38
+ input_statistic_file_path = (
39
+ str(Path(change_monitor_instance.input_directory, change_monitor_instance.input_statistics_file_name)))
40
+
41
+ if self.settings['learning_mode_create_unique_entries_list']:
42
+ aggregation_display_name = \
43
+ f'{change_monitor_instance.input_file_name}|{change_monitor_instance.object_type}'
44
+ self.diff_checker_aggregation = diff_check.DiffChecker(
45
+ check_object=list(), # DNS events will be appended to this list.
46
+ return_first_cycle=True,
47
+ operation_type='new_objects',
48
+ input_file_write_only=change_monitor_instance.input_file_write_only,
49
+ check_object_display_name=aggregation_display_name,
50
+ input_file_path=input_file_path,
51
+ new_objects_hours_then_difference=self.settings['learning_hours']
52
+ )
53
+ self.diff_checker_aggregation.initiate_before_action()
54
+
55
+ if self.settings['create_alert_statistics']:
56
+ statistics_display_name = \
57
+ f'{change_monitor_instance.input_statistics_file_name}|{change_monitor_instance.object_type}'
58
+
59
+ self.diff_checker_statistics = diff_check.DiffChecker(
60
+ check_object=list(), # DNS events will be appended to this list.
61
+ return_first_cycle=True,
62
+ operation_type='hit_statistics',
63
+ hit_statistics_enable_queue=True,
64
+ input_file_write_only=change_monitor_instance.input_file_write_only,
65
+ check_object_display_name=statistics_display_name,
66
+ input_file_path=input_statistic_file_path,
67
+ hit_statistics_input_file_rotation_cycle_hours=self.settings['statistics_rotation_hours']
68
+ )
69
+ self.diff_checker_statistics.initiate_before_action()
70
+
71
+ # Start DNS monitoring.
72
+ self.fetch_engine.start()
73
+
74
+ def execute_cycle(self, print_kwargs: dict = None) -> list:
75
+ """
76
+ This function executes the cycle of the change monitor: dns.
77
+ The function is blocking so while using it, the script will wait for the next DNS event.
78
+ No need to use 'time.sleep()'.
79
+
80
+ :param print_kwargs: print_api kwargs.
81
+ :return: List of dictionaries with the results of the cycle.
82
+ """
83
+
84
+ # 'emit()' method is blocking (it uses 'get' of queue instance)
85
+ # will return a dict with current DNS trace event.
86
+ event_dict = self.fetch_engine.emit()
87
+
88
+ return_list = list()
89
+ if self.settings['learning_mode_create_unique_entries_list']:
90
+ self._aggregation_process(event_dict, return_list, print_kwargs)
91
+
92
+ if self.settings['create_alert_statistics'] and self.settings['alert_always']:
93
+ self._statistics_process(event_dict, return_list, print_kwargs)
94
+
95
+ return return_list
96
+
97
+ def _aggregation_process(self, event_dict: dict, return_list: list, print_kwargs: dict = None):
98
+ self.diff_checker_aggregation.check_object = [event_dict]
99
+
100
+ # Check if 'known_domains' list was updated from previous cycle.
101
+ result, message = self.diff_checker_aggregation.check_list_of_dicts(
102
+ sort_by_keys=['cmdline', 'name'], print_kwargs=print_kwargs)
103
+
104
+ if result:
105
+ # Check if 'updated' key is in the result. This means that this is a regular cycle.
106
+ if 'updated' in result:
107
+ if not result['time_passed']:
108
+ # Get list of new connections only.
109
+ # new_connections_only: list = list_of_dicts.get_difference(result['old'], result['updated'])
110
+
111
+ for connection in result['updated']:
112
+ message = \
113
+ f"[Learning] New Domain Added: {connection['name']} | " \
114
+ f"{connection['domain']} | {connection['query_type']} | " \
115
+ f"{connection['cmdline']}"
116
+ print_api(message, color='yellow', **(print_kwargs or {}))
117
+
118
+ return_list.append(message)
119
+
120
+ # Check if learning time passed, so we can alert the new entries.
121
+ if 'time_passed' in result:
122
+ if result['time_passed']:
123
+ self._statistics_process(result['updated'], return_list, print_kwargs)
124
+
125
+ def _statistics_process(self, event_dict: dict, return_list: list, print_kwargs: dict = None):
126
+ self.diff_checker_statistics.check_object = [event_dict]
127
+
128
+ # Check if 'known_domains' list was updated from previous cycle.
129
+ result, message = self.diff_checker_statistics.check_list_of_dicts(
130
+ sort_by_keys=['cmdline', 'name'], print_kwargs=print_kwargs)
131
+
132
+ if result:
133
+ if 'count' in result:
134
+ message = f"[Alert] DNS Request: {result['entry']} | Times hit: {result['count']}"
135
+ print_api(message, color='yellow', **(print_kwargs or {}))
136
+
137
+ return_list.append(message)
@@ -0,0 +1,77 @@
1
+ from pathlib import Path
2
+
3
+ from ... import filesystem, hashing
4
+ from ... import diff_check
5
+ from ...print_api import print_api
6
+
7
+
8
+ class FileCheck:
9
+ """
10
+ Class for file monitoring.
11
+ """
12
+ def __init__(self, change_monitor_instance):
13
+ self.diff_checker = None
14
+ self.change_monitor_instance = None
15
+ self.store_original_file_path = None
16
+
17
+ if not change_monitor_instance.input_file_name:
18
+ change_monitor_instance.input_file_name = Path(change_monitor_instance.check_object).name
19
+ change_monitor_instance.input_file_name = change_monitor_instance.input_file_name.lower()
20
+ change_monitor_instance.input_file_name = (
21
+ change_monitor_instance.input_file_name.replace(' ', '_').replace('.', '_'))
22
+ change_monitor_instance.input_file_name = f'{change_monitor_instance.input_file_name}.txt'
23
+
24
+ input_file_path = (
25
+ str(Path(change_monitor_instance.input_directory, change_monitor_instance.input_file_name)))
26
+
27
+ # If 'store_original_object' is True, create filename for the store original object.
28
+ if change_monitor_instance.object_type_settings['store_original_object']:
29
+ store_original_file_name: str = f'ORIGINAL_{Path(change_monitor_instance.check_object).name}'
30
+ self.store_original_file_path = str(Path(change_monitor_instance.input_directory, store_original_file_name))
31
+
32
+ self.diff_checker = diff_check.DiffChecker(
33
+ return_first_cycle=False,
34
+ operation_type='single_object',
35
+ input_file_path=input_file_path,
36
+ check_object_display_name=f'{change_monitor_instance.input_file_name}|{change_monitor_instance.object_type}'
37
+ )
38
+ self.diff_checker.initiate_before_action()
39
+ self.change_monitor_instance = change_monitor_instance
40
+
41
+ def execute_cycle(self, print_kwargs: dict = None):
42
+ """
43
+ This function executes the cycle of the change monitor: hash.
44
+
45
+ :param print_kwargs: print_api kwargs.
46
+ :return: List of dictionaries with the results of the cycle.
47
+ """
48
+
49
+ return_list = list()
50
+
51
+ self._get_hash()
52
+
53
+ # Check if the object was updated.
54
+ result, message = self.diff_checker.check_string(
55
+ print_kwargs=print_kwargs)
56
+
57
+ # If the object was updated, print the message in yellow color, otherwise print in green color.
58
+ if result:
59
+ print_api(message, color='yellow', **print_kwargs)
60
+ # create_message_file(message, self.__class__.__name__, logger=self.logger)
61
+
62
+ return_list.append(message)
63
+ else:
64
+ print_api(message, color='green', **print_kwargs)
65
+
66
+ return return_list
67
+
68
+ def _get_hash(self):
69
+ # Copy the file to the original object directory.
70
+ if self.store_original_file_path:
71
+ filesystem.copy_file(self.change_monitor_instance.check_object, self.store_original_file_path)
72
+
73
+ # Get hash of the file.
74
+ hash_string = hashing.hash_file(self.change_monitor_instance.check_object)
75
+
76
+ # Set the hash string to the 'check_object' variable.
77
+ self.diff_checker.check_object = hash_string
@@ -1,18 +1,17 @@
1
+ from ... import diff_check
1
2
  from ...print_api import print_api
2
3
  from .hash_checks import file, url
3
4
 
4
5
 
5
- def setup_check(change_monitor_instance):
6
- # if store_original_object and not (input_directory or input_file_path):
7
- # raise ValueError(
8
- # 'ERROR: if [store_original_object] is True, either '
9
- # '[input_directory] or [input_file_path] must be specified .')
6
+ DIFF_CHECKER = diff_check.DiffChecker(
7
+ return_first_cycle=False,
8
+ operation_type='single_object'
9
+ )
10
10
 
11
11
 
12
+ def setup_check(change_monitor_instance):
12
13
  change_monitor_instance.set_input_file_path()
13
14
 
14
- change_monitor_instance.diff_checker.operation_type = 'single_object'
15
-
16
15
  if change_monitor_instance.object_type == 'file':
17
16
  file.setup_check(change_monitor_instance, change_monitor_instance.check_object)
18
17
  elif 'url_' in change_monitor_instance.object_type:
@@ -1,91 +1,91 @@
1
+ from pathlib import Path
2
+ from typing import Union
3
+
1
4
  from ...wrappers.psutilw import psutilw
2
5
  from ...basics import list_of_dicts
3
6
  from ...print_api import print_api
7
+ from ... import diff_check
4
8
 
5
9
 
6
- def setup_check(change_monitor_instance):
7
- original_name: str = str()
8
-
9
- # Initialize objects for network monitoring.
10
- change_monitor_instance.fetch_engine = psutilw.PsutilConnections()
11
-
12
- # Change settings for the DiffChecker object.
13
- change_monitor_instance.diff_checker.return_first_cycle = True
14
-
15
- if change_monitor_instance.generate_input_file_name:
16
- original_name = 'known_connections'
17
- # Make path for 'input_file_name'.
18
- change_monitor_instance.input_file_name = f'{original_name}.txt'
19
-
20
- change_monitor_instance.diff_checker.check_object_display_name = \
21
- f'{original_name}|{change_monitor_instance.object_type}'
22
-
23
- # Set the 'check_object' to empty list, since we will append the list of DNS events.
24
- change_monitor_instance.diff_checker.check_object = list()
25
-
26
- change_monitor_instance.diff_checker.operation_type = 'single_object'
27
-
28
-
29
- def execute_cycle(change_monitor_instance, print_kwargs: dict = None):
30
- """
31
- This function executes the cycle of the change monitor: network.
32
-
33
- :param change_monitor_instance: Instance of the ChangeMonitor class.
34
- :param print_kwargs: print_api kwargs.
35
-
36
- :return: List of dictionaries with the results of the cycle.
37
- """
38
-
39
- if print_kwargs is None:
40
- print_kwargs = dict()
41
-
42
- return_list = list()
43
-
44
- _get_list(change_monitor_instance)
45
-
46
- change_monitor_instance._set_input_file_path()
47
-
48
- # Check if 'known_domains' list was updated from previous cycle.
49
- result, message = change_monitor_instance.diff_checker.check_list_of_dicts(print_kwargs=print_kwargs)
10
+ INPUT_FILE_DEFAULT_NAME: str = 'known_connections.txt'
50
11
 
51
- if result:
52
- # Get list of new connections only.
53
- new_connections_only: list = list_of_dicts.get_difference(result['old'], result['updated'])
54
12
 
55
- for connection in new_connections_only:
56
- message = \
57
- f"New connection: {connection['name']} | " \
58
- f"{connection['dst_ip']}:{connection['dst_port']} | " \
59
- f"{connection['family']} | {connection['type']} | {connection['cmdline']}"
60
- # f"{connection['src_ip']}:{connection['src_port']} -> " \
61
- print_api(message, color='yellow', **print_kwargs)
62
-
63
- return_list.append(message)
64
-
65
- return return_list
66
-
67
-
68
- def _get_list(change_monitor_instance):
13
+ class NetworkCheck:
69
14
  """
70
- The function will get the list of opened network sockets and return only the new ones.
71
-
72
- :param change_monitor_instance: Instance of the ChangeMonitor class.
73
-
74
- :return: list of dicts, of new network sockets.
15
+ Class for network monitoring.
75
16
  """
76
17
 
77
- # Get all connections (list of dicts), including process name and cmdline.
78
- connections_list_of_dicts: list = \
79
- change_monitor_instance.fetch_engine.get_connections_with_process_as_list_of_dicts(
80
- attrs=['name', 'cmdline', 'family', 'type', 'dst_ip', 'dst_port'], skip_empty_dst=True,
81
- cmdline_to_string=True, remove_duplicates=True)
82
-
83
- # Get list of connections that are not in 'known_connections' list.
84
- missing_connections_from_cycle: list = list_of_dicts.get_difference(
85
- change_monitor_instance.diff_checker.check_object, connections_list_of_dicts)
86
- # Add missing new connections to 'known_connections' list.
87
- change_monitor_instance.diff_checker.check_object.extend(missing_connections_from_cycle)
88
-
89
- # Sort list of dicts by process name and then by process cmdline.
90
- change_monitor_instance.diff_checker.check_object = list_of_dicts.sort_by_keys(
91
- change_monitor_instance.diff_checker.check_object, key_list=['cmdline', 'name'], case_insensitive=True)
18
+ def __init__(self, change_monitor_instance):
19
+ self.change_monitor_instance = change_monitor_instance
20
+ self.diff_checker: Union[diff_check.DiffChecker, None] = None
21
+ self.fetch_engine = psutilw.PsutilConnections()
22
+
23
+ if not change_monitor_instance.input_file_name:
24
+ change_monitor_instance.input_file_name = INPUT_FILE_DEFAULT_NAME
25
+ input_file_path = (
26
+ str(Path(change_monitor_instance.input_directory, change_monitor_instance.input_file_name)))
27
+
28
+ diff_checker_display_name = \
29
+ f'{change_monitor_instance.input_file_name}|{change_monitor_instance.object_type}'
30
+ self.diff_checker = diff_check.DiffChecker(
31
+ check_object=list(), # we will append the list of connection events.
32
+ return_first_cycle=True,
33
+ operation_type='single_object',
34
+ check_object_display_name=diff_checker_display_name,
35
+ input_file_path=input_file_path
36
+ )
37
+ self.diff_checker.initiate_before_action()
38
+
39
+ def execute_cycle(self, print_kwargs: dict = None):
40
+ """
41
+ This function executes the cycle of the change monitor: network.
42
+
43
+ :param print_kwargs: print_api kwargs.
44
+ :return: List of dictionaries with the results of the cycle.
45
+ """
46
+
47
+ return_list = list()
48
+
49
+ self._get_list()
50
+
51
+ # Check if 'known_domains' list was updated from previous cycle.
52
+ result, message = self.diff_checker.check_list_of_dicts(print_kwargs=print_kwargs)
53
+
54
+ if result:
55
+ # Get list of new connections only.
56
+ new_connections_only: list = list_of_dicts.get_difference(result['old'], result['updated'])
57
+
58
+ for connection in new_connections_only:
59
+ message = \
60
+ f"New connection: {connection['name']} | " \
61
+ f"{connection['dst_ip']}:{connection['dst_port']} | " \
62
+ f"{connection['family']} | {connection['type']} | {connection['cmdline']}"
63
+ # f"{connection['src_ip']}:{connection['src_port']} -> " \
64
+ print_api(message, color='yellow', **(print_kwargs or {}))
65
+
66
+ return_list.append(message)
67
+
68
+ return return_list
69
+
70
+ def _get_list(self):
71
+ """
72
+ The function will get the list of opened network sockets and return only the new ones.
73
+
74
+ :return: list of dicts, of new network sockets.
75
+ """
76
+
77
+ # Get all connections (list of dicts), including process name and cmdline.
78
+ connections_list_of_dicts: list = \
79
+ self.fetch_engine.get_connections_with_process_as_list_of_dicts(
80
+ attrs=['name', 'cmdline', 'family', 'type', 'dst_ip', 'dst_port'], skip_empty_dst=True,
81
+ cmdline_to_string=True, remove_duplicates=True)
82
+
83
+ # Get list of connections that are not in 'known_connections' list.
84
+ missing_connections_from_cycle: list = list_of_dicts.get_difference(
85
+ self.diff_checker.check_object, connections_list_of_dicts)
86
+ # Add missing new connections to 'known_connections' list.
87
+ self.diff_checker.check_object.extend(missing_connections_from_cycle)
88
+
89
+ # Sort list of dicts by process name and then by process cmdline.
90
+ self.diff_checker.check_object = list_of_dicts.sort_by_keys(
91
+ self.diff_checker.check_object, key_list=['cmdline', 'name'], case_insensitive=True)
@@ -3,51 +3,50 @@ from ...basics import list_of_dicts
3
3
  from ...print_api import print_api
4
4
 
5
5
 
6
- def setup_check(change_monitor_instance):
7
- change_monitor_instance.fetch_engine = psutilw.PsutilProcesses()
8
-
9
-
10
- def execute_cycle(change_monitor_instance, print_kwargs: dict = None):
6
+ class ProcessRunningCheck:
11
7
  """
12
- This function executes the cycle of the change monitor: process_running.
13
-
14
- :param change_monitor_instance: Instance of the ChangeMonitor class.
15
- :param print_kwargs: Dictionary with the print arguments.
16
- :return: List of dictionaries with the results of the cycle.
8
+ Class for process running monitoring.
17
9
  """
18
10
 
19
- if print_kwargs is None:
20
- print_kwargs = dict()
11
+ def __init__(self, change_monitor_instance):
12
+ self.change_monitor_instance = change_monitor_instance
13
+ self.fetch_engine = psutilw.PsutilProcesses()
21
14
 
22
- return_list = list()
15
+ def execute_cycle(self, print_kwargs: dict = None):
16
+ """
17
+ This function executes the cycle of the change monitor: process_running.
23
18
 
24
- processes = _get_list(change_monitor_instance)
19
+ :param print_kwargs: Dictionary with the print arguments.
20
+ :return: List of dictionaries with the results of the cycle.
21
+ """
25
22
 
26
- for process_name in change_monitor_instance.check_object:
27
- result = list_of_dicts.is_value_exist_in_key(processes, 'cmdline', process_name, value_case_insensitive=True)
23
+ return_list = list()
28
24
 
29
- # If the process name was found in the list of currently running processes.
30
- if result:
31
- message = f"Process [{process_name}] is Running."
32
- print_api(message, color='green', **print_kwargs)
33
- # If the process name was not found in the list of currently running processes.
34
- else:
35
- message = f"Process [{process_name}] not Running!"
36
- print_api(message, color='red', **print_kwargs)
25
+ processes = self._get_list()
37
26
 
38
- return_list.append(message)
27
+ for process_name in self.change_monitor_instance.check_object:
28
+ result = list_of_dicts.is_value_exist_in_key(
29
+ processes, 'cmdline', process_name, value_case_insensitive=True)
39
30
 
40
- return return_list
31
+ # If the process name was found in the list of currently running processes.
32
+ if result:
33
+ message = f"Process [{process_name}] is Running."
34
+ print_api(message, color='green', **(print_kwargs or {}))
35
+ # If the process name was not found in the list of currently running processes.
36
+ else:
37
+ message = f"Process [{process_name}] not Running!"
38
+ print_api(message, color='red', **(print_kwargs or {}))
41
39
 
40
+ return_list.append(message)
42
41
 
43
- def _get_list(change_monitor_instance):
44
- """
45
- The function will get the list of opened network sockets and return only the new ones.
42
+ return return_list
46
43
 
47
- :param change_monitor_instance: Instance of the ChangeMonitor class.
44
+ def _get_list(self):
45
+ """
46
+ The function will get the list of opened network sockets and return only the new ones.
48
47
 
49
- :return: list of dicts, of new network sockets.
50
- """
48
+ :return: list of dicts, of new network sockets.
49
+ """
51
50
 
52
- return change_monitor_instance.fetch_engine.get_processes_as_list_of_dicts(
53
- default_keys=True, cmdline_to_string=True)
51
+ return self.fetch_engine.get_processes_as_list_of_dicts(
52
+ default_keys=True, cmdline_to_string=True)
@@ -0,0 +1,94 @@
1
+ from pathlib import Path
2
+
3
+ from ... import hashing, urls
4
+ from ... import diff_check
5
+ from ...print_api import print_api
6
+
7
+
8
+ class UrlCheck:
9
+ """
10
+ Class for file monitoring.
11
+ """
12
+ def __init__(self, change_monitor_instance):
13
+ self.diff_checker = None
14
+ self.change_monitor_instance = None
15
+ self.store_original_file_path = None
16
+ self.get_method = None
17
+
18
+ # Extract the method name from the object type.
19
+ self.get_method = change_monitor_instance.object_type.split('_', 1)[1]
20
+
21
+ if not change_monitor_instance.input_file_name:
22
+ change_monitor_instance.input_file_name = (
23
+ urls.url_parser(change_monitor_instance.check_object))['directories'][-1]
24
+ change_monitor_instance.input_file_name = change_monitor_instance.input_file_name.lower()
25
+ change_monitor_instance.input_file_name = f'{change_monitor_instance.input_file_name}.txt'
26
+
27
+ input_file_path = (
28
+ str(Path(change_monitor_instance.input_directory, change_monitor_instance.input_file_name)))
29
+
30
+ # If 'store_original_object' is True, create filename for the store original object.
31
+ if change_monitor_instance.object_type_settings['store_original_object']:
32
+ # Add extension to the file name.
33
+ extension: str = str()
34
+ if 'playwright' in self.get_method:
35
+ extension = self.get_method.split('_')[1]
36
+ elif self.get_method == 'urllib':
37
+ extension = 'html'
38
+
39
+ store_original_file_name: str = Path(change_monitor_instance.input_file_name).stem
40
+ store_original_file_name = f'{store_original_file_name}.{extension}'
41
+ self.store_original_file_path = str(Path(change_monitor_instance.input_directory, store_original_file_name))
42
+
43
+ self.diff_checker = diff_check.DiffChecker(
44
+ return_first_cycle=False,
45
+ operation_type='single_object',
46
+ input_file_path=input_file_path,
47
+ check_object_display_name=f'{change_monitor_instance.input_file_name}|{change_monitor_instance.object_type}'
48
+ )
49
+ self.diff_checker.initiate_before_action()
50
+ self.change_monitor_instance = change_monitor_instance
51
+
52
+ def execute_cycle(self, print_kwargs: dict = None):
53
+ """
54
+ This function executes the cycle of the change monitor: hash.
55
+
56
+ :param print_kwargs: print_api kwargs.
57
+ :return: List of dictionaries with the results of the cycle.
58
+ """
59
+
60
+ return_list = list()
61
+
62
+ self._get_hash(print_kwargs=print_kwargs)
63
+
64
+ # Check if the object was updated.
65
+ result, message = self.diff_checker.check_string(
66
+ print_kwargs=print_kwargs)
67
+
68
+ # If the object was updated, print the message in yellow color, otherwise print in green color.
69
+ if result:
70
+ print_api(message, color='yellow', **print_kwargs)
71
+ # create_message_file(message, self.__class__.__name__, logger=self.logger)
72
+
73
+ return_list.append(message)
74
+ else:
75
+ print_api(message, color='green', **print_kwargs)
76
+
77
+ return return_list
78
+
79
+ def _get_hash(self, print_kwargs: dict = None):
80
+ """
81
+ The function will get the hash of the URL content.
82
+
83
+ :param print_kwargs: print_api kwargs.
84
+ """
85
+ # Get hash of the url. The hash will be different between direct hash of the URL content and the
86
+ # hash of the file that was downloaded from the URL. Since the file has headers and other information
87
+ # that is not part of the URL content. The Original downloaded file is for reference only to see
88
+ # what was the content of the URL at the time of the download.
89
+ hash_string = hashing.hash_url(
90
+ self.change_monitor_instance.check_object, get_method=self.get_method,
91
+ path=self.store_original_file_path, print_kwargs=print_kwargs)
92
+
93
+ # Set the hash string to the 'check_object' variable.
94
+ self.diff_checker.check_object = hash_string
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: atomicshop
3
- Version: 2.12.17
3
+ Version: 2.12.19
4
4
  Summary: Atomic functions and classes to make developer life easier
5
5
  Author: Denis Kras
6
6
  License: MIT License
@@ -1,4 +1,4 @@
1
- atomicshop/__init__.py,sha256=Y0i9YbX4w6RHv1MhMq0Dp3xhWzkgeDIA2V8gJkAoNbw,124
1
+ atomicshop/__init__.py,sha256=CBepG0XgfpgafeV__swI0Jz0kUF1uJvK3WLlJWWcQwk,124
2
2
  atomicshop/_basics_temp.py,sha256=6cu2dd6r2dLrd1BRNcVDKTHlsHs_26Gpw8QS6v32lQ0,3699
3
3
  atomicshop/_create_pdf_demo.py,sha256=Yi-PGZuMg0RKvQmLqVeLIZYadqEZwUm-4A9JxBl_vYA,3713
4
4
  atomicshop/_patch_import.py,sha256=ENp55sKVJ0e6-4lBvZnpz9PQCt3Otbur7F6aXDlyje4,6334
@@ -9,7 +9,7 @@ atomicshop/config_init.py,sha256=z2RXD_mw9nQlAOpuGry1h9QT-2LhNscXgGAktN3dCVQ,249
9
9
  atomicshop/console_output.py,sha256=AOSJjrRryE97PAGtgDL03IBtWSi02aNol8noDnW3k6M,4667
10
10
  atomicshop/console_user_response.py,sha256=31HIy9QGXa7f-GVR8MzJauQ79E_ZqAeagF3Ks4GGdDU,3234
11
11
  atomicshop/datetimes.py,sha256=olsL01S5tkXk4WPzucxujqgLOh198BLgJntDnGYukRU,15533
12
- atomicshop/diff_check.py,sha256=BJIhnAgTyJ-nyw3UBKwobvF0lJuhXQ2rPu12NiYETkI,27088
12
+ atomicshop/diff_check.py,sha256=0H4OeRxJodFIubpAoy2dFY9hixzLbkJ8NNlH6K3Xdus,27033
13
13
  atomicshop/dns.py,sha256=bNZOo5jVPzq7OT2qCPukXoK3zb1oOsyaelUwQEyK1SA,2500
14
14
  atomicshop/domains.py,sha256=Rxu6JhhMqFZRcoFs69IoEd1PtYca0lMCG6F1AomP7z4,3197
15
15
  atomicshop/emails.py,sha256=I0KyODQpIMEsNRi9YWSOL8EUPBiWyon3HRdIuSj3AEU,1410
@@ -106,7 +106,7 @@ atomicshop/etw/etw.py,sha256=xVJNbfCq4KgRfsDnul6CrIdAMl9xRBixZ-hUyqiB2g4,2403
106
106
  atomicshop/file_io/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
107
107
  atomicshop/file_io/csvs.py,sha256=WOtDyVFhhA1RD3yrU9P33kDY1EKFEz8UmVCUkqYKuog,5503
108
108
  atomicshop/file_io/docxs.py,sha256=6tcYFGp0vRsHR47VwcRqwhdt2DQOwrAUYhrwN996n9U,5117
109
- atomicshop/file_io/file_io.py,sha256=FR84ihjGlr7Eqejo-_js4nBICVst31axD0bwX19S2eM,6385
109
+ atomicshop/file_io/file_io.py,sha256=FOZ6_PjOASxSDHESe4fwDv5miXYR10OHTxkxtEHoZYQ,6555
110
110
  atomicshop/file_io/jsons.py,sha256=q9ZU8slBKnHLrtn3TnbK1qxrRpj5ZvCm6AlsFzoANjo,5303
111
111
  atomicshop/file_io/tomls.py,sha256=oa0Wm8yMkPRXKN9jgBuTnKbioSOee4mABW5IMUFCYyU,3041
112
112
  atomicshop/file_io/xlsxs.py,sha256=v_dyg9GD4LqgWi6wA1QuWRZ8zG4ZwB6Dz52ytdcmmmI,2184
@@ -132,15 +132,14 @@ atomicshop/mitm/engines/__reference_general/parser___reference_general.py,sha256
132
132
  atomicshop/mitm/engines/__reference_general/recorder___reference_general.py,sha256=KENDVf9OwXD9gwSh4B1XxACCe7iHYjrvnW1t6F64wdE,695
133
133
  atomicshop/mitm/engines/__reference_general/responder___reference_general.py,sha256=1AM49UaFTKA0AHw-k3SV3uH3QbG-o6ux0c-GoWkKNU0,6993
134
134
  atomicshop/monitor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
135
- atomicshop/monitor/change_monitor.py,sha256=ySfFCtsCFG3irV6gKr43DbbyQgmTwzG5m3FkCWDa8UI,9246
135
+ atomicshop/monitor/change_monitor.py,sha256=mrLedkgXWxKzQLqjYd3bmD8-or6HlX9sejdXbSvhNMI,9016
136
136
  atomicshop/monitor/checks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
137
- atomicshop/monitor/checks/dns.py,sha256=XOMVhf2A2A8zEvQxBszL5z_DItJC0pomg_mkiMKMrug,5741
138
- atomicshop/monitor/checks/hash.py,sha256=f719jU1A_rJi1ixGEHzWIZEoqpHJq4znabZnq4in9IM,2202
139
- atomicshop/monitor/checks/network.py,sha256=i2jc5LRKeQJRNtOrSbkZQQCMy33No_X-SjMcXDmIh1E,3753
140
- atomicshop/monitor/checks/process_running.py,sha256=pvSTa3nHDy1YH-35QkFxBUsqnCnfU5PBA_NNjp9iUNg,1889
141
- atomicshop/monitor/checks/hash_checks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
142
- atomicshop/monitor/checks/hash_checks/file.py,sha256=o80UpjPNx9-AF5fYkZaP-ASHcBCE2zwGKUVRtDYKQyI,2402
143
- atomicshop/monitor/checks/hash_checks/url.py,sha256=XxBNjhQZO_JlicgadqBblvt6sIRizerwM-LVCOgMCQU,3020
137
+ atomicshop/monitor/checks/dns.py,sha256=bPqQACt8IgQ08U-x9G7pAN-iSfxbdOAubJTHZd-lJ84,6792
138
+ atomicshop/monitor/checks/file.py,sha256=2tIDSlX2KZNc_9i9ji1tcOqupbFTIOj7cKXLyBEDWMk,3263
139
+ atomicshop/monitor/checks/hash.py,sha256=r4mDOdjItN3eyaJk8TVz03f4bQ_uKZ4MDTXagjseazs,2011
140
+ atomicshop/monitor/checks/network.py,sha256=CGZWl4WlQrxayZeVF9JspJXwYA-zWx8ECWTVGSlXc98,3825
141
+ atomicshop/monitor/checks/process_running.py,sha256=x66wd6-l466r8sbRQaIli0yswyGt1dH2DVXkGDL6O0Q,1891
142
+ atomicshop/monitor/checks/url.py,sha256=1PvKt_d7wFg7rDMFpUejAQhj0mqWsmlmrNfjNAV2G4g,4123
144
143
  atomicshop/ssh_scripts/process_from_ipv4.py,sha256=uDBKZ2Ds20614JW1xMLr4IPB-z1LzIwy6QH5-SJ4j0s,1681
145
144
  atomicshop/ssh_scripts/process_from_port.py,sha256=uDTkVh4zc3HOTTGv1Et3IxM3PonDJCPuFRL6rnZDQZ4,1389
146
145
  atomicshop/wrappers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -251,8 +250,8 @@ atomicshop/wrappers/socketw/socket_server_tester.py,sha256=AhpurHJmP2kgzHaUbq5ey
251
250
  atomicshop/wrappers/socketw/socket_wrapper.py,sha256=aXBwlEIJhFT0-c4i8iNlFx2It9VpCEpsv--5Oqcpxao,11624
252
251
  atomicshop/wrappers/socketw/ssl_base.py,sha256=k4V3gwkbq10MvOH4btU4onLX2GNOsSfUAdcHmL1rpVE,2274
253
252
  atomicshop/wrappers/socketw/statistics_csv.py,sha256=t3dtDEfN47CfYVi0CW6Kc2QHTEeZVyYhc57IYYh5nmA,826
254
- atomicshop-2.12.17.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
255
- atomicshop-2.12.17.dist-info/METADATA,sha256=eRzyeiQbRlaJQ62ckcewFJ7JdMmcSNBZKaVuhM4-GS8,10479
256
- atomicshop-2.12.17.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
257
- atomicshop-2.12.17.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
258
- atomicshop-2.12.17.dist-info/RECORD,,
253
+ atomicshop-2.12.19.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
254
+ atomicshop-2.12.19.dist-info/METADATA,sha256=XjMOMxBIk9wbHMRy4KgeBeYKoy8sD8FJjt-CGllbCsw,10479
255
+ atomicshop-2.12.19.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
256
+ atomicshop-2.12.19.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
257
+ atomicshop-2.12.19.dist-info/RECORD,,
File without changes
@@ -1,54 +0,0 @@
1
- from .... import filesystem, hashing
2
-
3
-
4
- def setup_check(change_monitor_instance, check_object: str):
5
- original_name: str = str()
6
-
7
- # If 'generate_input_file_name' is True, or 'store_original_object' is True, we need to create a
8
- # filename without extension.
9
- if change_monitor_instance.store_original_object or change_monitor_instance.generate_input_file_name:
10
- # Get the last directory from the url.
11
- original_name = filesystem.get_file_name(check_object)
12
- # Make characters lower case.
13
- original_name = original_name.lower()
14
-
15
- # If 'store_original_object' is True, then we need to create a filepath to store.
16
- if change_monitor_instance.original_object_directory:
17
- # Add extension to the file name.
18
- original_file_name = original_name
19
-
20
- # Make path for original object.
21
- change_monitor_instance.original_object_file_path = filesystem.add_object_to_path(
22
- change_monitor_instance.original_object_directory, original_file_name)
23
-
24
- if change_monitor_instance.generate_input_file_name:
25
- # Remove dots from the file name.
26
- original_name_no_dots = original_name.replace('.', '-')
27
- # Make path for 'input_file_name'.
28
- change_monitor_instance.input_file_name = f'{original_name_no_dots}.txt'
29
-
30
- # Change settings for the DiffChecker object.
31
- change_monitor_instance.diff_checker.return_first_cycle = False
32
-
33
- change_monitor_instance.diff_checker.check_object_display_name = \
34
- f'{original_name}|{change_monitor_instance.object_type}'
35
-
36
-
37
- def get_hash(change_monitor_instance, check_object: str, print_kwargs: dict = None):
38
- """
39
- The function will get the hash of the URL content.
40
-
41
- :param change_monitor_instance: Instance of the ChangeMonitor class.
42
- :param check_object: string, full URL to a web page.
43
- :param print_kwargs: dict, that contains all the arguments for 'print_api' function.
44
- """
45
-
46
- # Copy the file to the original object directory.
47
- if change_monitor_instance.original_object_file_path:
48
- filesystem.copy_file(check_object, change_monitor_instance.original_object_file_path)
49
-
50
- # Get hash of the file.
51
- hash_string = hashing.hash_file(check_object)
52
-
53
- # Set the hash string to the 'check_object' variable.
54
- change_monitor_instance.diff_checker.check_object = hash_string
@@ -1,64 +0,0 @@
1
- from .... import filesystem, hashing, urls
2
-
3
-
4
- def setup_check(change_monitor_instance, check_object: str):
5
- # Extract the method name from the object type.
6
- get_method = change_monitor_instance.object_type.split('_', 1)[1]
7
-
8
- original_name: str = str()
9
-
10
- # If 'generate_input_file_name' is True, or 'store_original_object' is True, we need to create a
11
- # filename without extension.
12
- if change_monitor_instance.store_original_object or change_monitor_instance.generate_input_file_name:
13
- # Get the last directory from the url.
14
- original_name = urls.url_parser(check_object)['directories'][-1]
15
- # Make characters lower case.
16
- original_name = original_name.lower()
17
-
18
- # If 'store_original_object' is True, then we need to create a filepath to store.
19
- extension = None
20
- if change_monitor_instance.original_object_directory:
21
- # Add extension to the file name.
22
- if 'playwright' in get_method:
23
- extension = get_method.split('_')[1]
24
- elif get_method == 'urllib':
25
- extension = 'html'
26
- original_file_name = f'{original_name}.{extension}'
27
-
28
- # Make path for original object.
29
- change_monitor_instance.original_object_file_path = filesystem.add_object_to_path(
30
- change_monitor_instance.original_object_directory, original_file_name)
31
-
32
- if change_monitor_instance.generate_input_file_name:
33
- # Make path for 'input_file_name'.
34
- change_monitor_instance.input_file_name = f'{original_name}.txt'
35
-
36
- # Change settings for the DiffChecker object.
37
- change_monitor_instance.diff_checker.return_first_cycle = False
38
-
39
- change_monitor_instance.diff_checker.check_object_display_name = \
40
- f'{original_name}|{change_monitor_instance.object_type}'
41
-
42
-
43
- def get_hash(change_monitor_instance, check_object: str, print_kwargs: dict = None):
44
- """
45
- The function will get the hash of the URL content.
46
-
47
- :param change_monitor_instance: Instance of the ChangeMonitor class.
48
- :param check_object: string, full URL to a web page.
49
- :param print_kwargs: dict, that contains all the arguments for 'print_api' function.
50
- """
51
- # Extract the method name from the object type.
52
- get_method = change_monitor_instance.object_type.split('_', 1)[1]
53
-
54
- # Get hash of the url. The hash will be different between direct hash of the URL content and the
55
- # hash of the file that was downloaded from the URL. Since the file has headers and other information
56
- # that is not part of the URL content. The Original downloaded file is for reference only to see
57
- # what was the content of the URL at the time of the download.
58
- hash_string = hashing.hash_url(
59
- check_object, get_method=get_method, path=change_monitor_instance.original_object_file_path,
60
- print_kwargs=print_kwargs
61
- )
62
-
63
- # Set the hash string to the 'check_object' variable.
64
- change_monitor_instance.diff_checker.check_object = hash_string