<commit_before>#!/usr/bin/env python3

# written by sqall
# twitter: https://twitter.com/sqall01
# blog: https://h4des.org
# github: https://github.com/sqall01
#
# Licensed under the GNU Affero General Public License, version 3.

import logging
import os
import threading
from typing import List, Any
from ..client import EventHandler
from ..alert.core import _Alert
from ..globalData import SensorDataType
from ..globalData import ManagerObjManager, ManagerObjNode, ManagerObjOption, ManagerObjSensorAlert, \
    ManagerObjAlertLevel, ManagerObjAlert, ManagerObjSensor, ManagerObjProfile
from ..globalData import AlertObjProfileChange
from ..globalData import GlobalData


class AlertEventHandler(EventHandler):

    def __init__(self,
                 global_data: GlobalData):
        super().__init__()

        # file name of this file (used for logging)
        self._log_tag = os.path.basename(__file__)

        # Get global configured data
        self._global_data = global_data
        self._local_alerts = self._global_data.alerts

    def _thread_profile_change(self, alert: _Alert, profile_change: AlertObjProfileChange):
        alert.alert_profile_change(profile_change)

    def _thread_sensor_alert(self, alert: _Alert, sensor_alert: ManagerObjSensorAlert):
        if sensor_alert.state == 1:
            alert.alert_triggered(sensor_alert)

        elif sensor_alert.state == 0:
            alert.alert_normal(sensor_alert)

    # noinspection PyTypeChecker
    def status_update(self,
                      msg_time: int,
                      options: List[ManagerObjOption],
                      profiles: List[ManagerObjProfile],
                      nodes: List[ManagerObjNode],
                      sensors: List[ManagerObjSensor],
                      managers: List[ManagerObjManager],
                      alerts: List[ManagerObjAlert],
                      alert_levels: List[ManagerObjAlertLevel]) -> bool:
        logging.critical("[%s]: status_update() not supported by node of type 'alert'." % self._log_tag)
        raise NotImplementedError("Not supported by node of type 'alert'.")

    def sensor_alert(self,
                     msg_time: int,
                     sensor_alert: ManagerObjSensorAlert) -> bool:

        at_least_once_triggered = False
        alert_level_str = ", ".join(map(str, sensor_alert.alertLevels))
        for alert in self._local_alerts:
            for alert_level in sensor_alert.alertLevels:
                if alert_level in alert.alertLevels:
                    at_least_once_triggered = True

                    logging.debug("[%s]: Trigger Alert '%d' with state '%s' for Alert Levels '%s'."
                                  % (self._log_tag, alert.id, str(sensor_alert.state), alert_level_str))

                    thread = threading.Thread(target=self._thread_sensor_alert,
                                              args=(alert, sensor_alert))
                    thread.daemon = True
                    thread.start()

        if not at_least_once_triggered:
            logging.info("[%s]: No Alert triggered for Alert Levels '%s'."
                         % (self._log_tag, alert_level_str))

        return True

    def profile_change(self,
                       msg_time: int,
                       profile_change: AlertObjProfileChange) -> bool:

        # Tell system profile change to all alerts.
        for alert in self._local_alerts:
            logging.debug("[%s]: Notifying Alert '%d' about system profile change to '%d'."
                          % (self._log_tag, alert.id, profile_change.profileId))

            thread = threading.Thread(target=self._thread_profile_change,
                                      args=(alert, profile_change))
            thread.daemon = True
            thread.start()

        return True

    # noinspection PyTypeChecker
    def state_change(self,
                     msg_time: int,
                     sensor_id: int,<commit_msg>remove Alert only once if Alert Levels of Sensor Alert and Alert intersect multiple times<commit_after>#!/usr/bin/env python3

# written by sqall
# twitter: https://twitter.com/sqall01
# blog: https://h4des.org
# github: https://github.com/sqall01
#
# Licensed under the GNU Affero General Public License, version 3.

import logging
import os
import threading
from typing import List, Any
from ..client import EventHandler
from ..alert.core import _Alert
from ..globalData import SensorDataType
from ..globalData import ManagerObjManager, ManagerObjNode, ManagerObjOption, ManagerObjSensorAlert, \
    ManagerObjAlertLevel, ManagerObjAlert, ManagerObjSensor, ManagerObjProfile
from ..globalData import AlertObjProfileChange
from ..globalData import GlobalData


class AlertEventHandler(EventHandler):

    def __init__(self,
                 global_data: GlobalData):
        super().__init__()

        # file name of this file (used for logging)
        self._log_tag = os.path.basename(__file__)

        # Get global configured data
        self._global_data = global_data
        self._local_alerts = self._global_data.alerts

    def _thread_profile_change(self, alert: _Alert, profile_change: AlertObjProfileChange):
        alert.alert_profile_change(profile_change)

    def _thread_sensor_alert(self, alert: _Alert, sensor_alert: ManagerObjSensorAlert):
        if sensor_alert.state == 1:
            alert.alert_triggered(sensor_alert)

        elif sensor_alert.state == 0:
            alert.alert_normal(sensor_alert)

    # noinspection PyTypeChecker
    def status_update(self,
                      msg_time: int,
                      options: List[ManagerObjOption],
                      profiles: List[ManagerObjProfile],
                      nodes: List[ManagerObjNode],
                      sensors: List[ManagerObjSensor],
                      managers: List[ManagerObjManager],
                      alerts: List[ManagerObjAlert],
                      alert_levels: List[ManagerObjAlertLevel]) -> bool:
        logging.critical("[%s]: status_update() not supported by node of type 'alert'." % self._log_tag)
        raise NotImplementedError("Not supported by node of type 'alert'.")

    def sensor_alert(self,
                     msg_time: int,
                     sensor_alert: ManagerObjSensorAlert) -> bool:

        at_least_once_triggered = False
        alert_level_str = ", ".join(map(str, sensor_alert.alertLevels))
        for alert in self._local_alerts:

            # Check Alert Levels of Sensor Alert and Alert have common levels.
            intersect_alert_levels = set(sensor_alert.alertLevels).intersection(alert.alertLevels)
            if intersect_alert_levels:
                at_least_once_triggered = True

                logging.debug("[%s]: Trigger Alert '%d' with state '%s' for Alert Levels '%s'."
                              % (self._log_tag, alert.id, str(sensor_alert.state), alert_level_str))

                thread = threading.Thread(target=self._thread_sensor_alert,
                                          args=(alert, sensor_alert))
                thread.daemon = True
                thread.start()

        if not at_least_once_triggered:
            logging.info("[%s]: No Alert triggered for Alert Levels '%s'."
                         % (self._log_tag, alert_level_str))

        return True

    def profile_change(self,
                       msg_time: int,
                       profile_change: AlertObjProfileChange) -> bool:

        # Tell system profile change to all alerts.
        for alert in self._local_alerts:
            logging.debug("[%s]: Notifying Alert '%d' about system profile change to '%d'."
                          % (self._log_tag, alert.id, profile_change.profileId))

            thread = threading.Thread(target=self._thread_profile_change,
                                      args=(alert, profile_change))
            thread.daemon = True
            thread.start()

        return True

    # noinspection PyTypeChecker
    def state_change(self,
                     msg_time: int,
                     sensor_id: int,
{'fraction_non_alphanumeric': 0.0814239960581424, 'fraction_numerical': 0.0022172949002217295, 'mean_word_length': 2.150562669771052, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 7, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7552805', 'n_tokens_mistral': 2181, 'n_tokens_neox': 2052, 'n_words': 538}