<commit_before>from datetime import timedelta, datetime
from sets import Set

from apscheduler.scheduler import Scheduler

from rootio.radio.models import Person


class PhoneStatus:
    REJECTING = 1
    QUEUING = 2
    ANSWERING = 3
    CONFERENCING = 4
    IVR = 5
    RINGING = 6


class OutcallAction:

    def __init__(self, host_id, start_time, duration, program):
        self.__host_id = host_id
        self.start_time = start_time
        self.duration = duration
        self.program = program
        self.__scheduler = Scheduler()
        self.__available_calls = dict()
        self.__in_talkshow_setup = False
        self.__host = None
        self.__community_call_UUIDs = dict()
        self.__invitee_call_UUIDs = dict()
        self.__call_handler = self.program.radio_station.call_handler
        self.__phone_status = PhoneStatus.QUEUING
        self.__interested_participants = Set([])
        self.__collecting_digits_to_call = False
        self.__invitee_number = ""

    def start(self):
        try:
            self.__in_talkshow_setup = True
            self.__host = self.__get_host(self.__host_id)
            if self.__host is None or self.__host.phone is None:
                self.stop(False)
                return
            # self.program.set_running_action(self)
            self.__scheduler.start()
            self.__call_handler.register_for_incoming_calls(self)
            self.__call_handler.register_for_incoming_dtmf(self, str(self.__host.phone.raw_number))
            self.__call_handler.register_for_host_call(self, str(self.__host.phone.raw_number))
            self.request_host_call()
        except Exception as e:
            print e

    def stop(self, graceful=True, call_info=None):
        self.hangup_call()
        # Stop scheduler
        self.__scheduler.shutdown()
        # deregister from any triggers
        self.__call_handler.deregister_for_incoming_calls(self)
        self.__call_handler.deregister_for_incoming_dtmf(str(self.__host.phone.raw_number))
        self.program.notify_program_action_stopped(graceful, call_info)

    def __get_host(self, host_id):
        host = self.program.radio_station.db.query(Person).filter(Person.id == host_id).first()
        return host

    def request_host_call(self):
        self.__in_talkshow_setup = True
        result = self.__call_handler.call(self, self.__host.phone.raw_number, None, False,
                                          15)  # call ends in 15 mins max
        self.program.log_program_activity("result of host call is " + str(result))
        if not result[0]:
            self.stop(False)

    def __request_station_call(self):
        if self.program.radio_station.station.is_high_bandwidth:
            result = self.__call_station_via_sip()
            if result is None or not result[0]:  # Now try calling the SIM (ideally do primary, then secondary)
                result = self.__call_station_via_goip()
        else:
            result = self.__call_station_via_goip()
        if result is None or not result[0]:
            self.stop(False)

    def __call_station_via_sip(self):
        result = None
        # Try a high bandwidth call first
        if self.program.radio_station.station.sip_username is not None:
            result = self.__call_handler.call(self, self.program.radio_station.station.sip_username,
                                              self.__host.phone.raw_number, True,
                                              self.duration)
            self.program.log_program_activity("result of station call via SIP is " + str(result))
        return result

    def __call_station_via_goip(self):
        result = None
        if self.program.radio_station.station.primary_transmitter_phone is not None:
            result = self.__call_handler.call(self,
                                              self.program.radio_station.station.primary_transmitter_phone.raw_number,
                                              self.__host.phone.raw_number, False,
                                              self.duration)
            self.program.log_program_activity("result of station call (primary) via GoIP is " + str(result))
            if not result[
                    0] and self.program.radio_station.station.secondary_transmitter_phone is not None:  # Go for the secondary line of the station, if duo SIM phone
                result = self.__call_handler.call(self,
                                                  self.program.radio_station.station.secondary_transmitter_phone.raw_number,
                                                  self.__host.phone.raw_number, False,
                                                  self.duration)
                self.program.log_program_activity("result of station call (secondary) via GoIP is " + str(result))
        return result

    def notify_call_answered(self, answer_info):
        if self.__host.phone.raw_number not in self.__available_calls:
            self.__available_calls[answer_info['Caller-Destination-Number'][-12:]] = answer_info
            self.__inquire_host_readiness()
            self.program.log_program_activity("host call has been answered")
        elif 'Caller-Destination-Number' in answer_info and answer_info['Caller-Destination-Number'][-12:] == self.__invitee_number:
            self.__available_calls[answer_info['Caller-Destination-Number'][-12:]] = answer_info
            self.__invitee_number = "";
            self.__collecting_digits_to_call = False
        else:  # This notification is from answering the host call
            self.__available_calls[answer_info['Caller-Destination-Number'][-12:]] = answer_info
            # result1 = self.__schedule_warning()
            # result2 = self.__schedule_hangup()
        self.__call_handler.register_for_call_hangup(self, answer_info['Caller-Destination-Number'][-12:])

    def warn_number(self):
        seconds = self.duration - self.__warning_time
        if self.__host.phone.raw_number in self.__available_calls and 'Channel-Call-UUID' in self.__available_calls[
                self.__host.phone.raw_number]:
            result = self.__call_handler.speak(
                'Your call will end in ' + str(seconds) + 'seconds',
                self.__available_calls[self.__host.phone.raw_number]['Channel-Call-UUID'])
            self.program.log_program_activity("result of warning is " + result)

    def __pause_call(self):  # hangup and schedule to call later
        self.__schedule_host_callback()
        self.hangup_call()

    def notify_call_hangup(self, event_json):
        if 'Caller-Destination-Number' in event_json:
            if event_json[
                    'Caller-Destination-Number'] in self.__community_call_UUIDs:  # a community caller is hanging up
                del self.__community_call_UUIDs[event_json['Caller-Destination-Number']]
                self.__call_handler.deregister_for_call_hangup(event_json['Caller-Destination-Number'])
            elif event_json['Caller-Destination-Number'] in self.__invitee_call_UUIDs:
                del self.__invitee_call_UUIDs[event_json['Caller-Destination-Number']]
                self.__call_handler.deregister_for_call_hangup(event_json['Caller-Destination-Number'])
            else:  # It is a hangup by the station or the host
                self.program.log_program_activity(
                    "Program terminated because {0} hangup".format(event_json['Caller-Destination-Number']))
                self.stop(True)

    def __inquire_host_readiness(self):
        self.__call_handler.speak(
            'You are scheduled to host a talk show at this time. If you are ready, press one, if not ready, press two',
            self.__available_calls[self.__host.phone.raw_number]['Channel-Call-UUID'])
        self.program.log_program_activity("Asking if host is ready")

    def hangup_call(self):  # hangup the ongoing call
        for available_call in self.__available_calls:<commit_msg>Fix for invitee hangup terminating calls for everyone<commit_after>from datetime import timedelta, datetime
from sets import Set

from apscheduler.scheduler import Scheduler

from rootio.radio.models import Person


class PhoneStatus:
    REJECTING = 1
    QUEUING = 2
    ANSWERING = 3
    CONFERENCING = 4
    IVR = 5
    RINGING = 6


class OutcallAction:

    def __init__(self, host_id, start_time, duration, program):
        self.__host_id = host_id
        self.start_time = start_time
        self.duration = duration
        self.program = program
        self.__scheduler = Scheduler()
        self.__available_calls = dict()
        self.__in_talkshow_setup = False
        self.__host = None
        self.__community_call_UUIDs = dict()
        self.__invitee_call_UUIDs = dict()
        self.__call_handler = self.program.radio_station.call_handler
        self.__phone_status = PhoneStatus.QUEUING
        self.__interested_participants = Set([])
        self.__collecting_digits_to_call = False
        self.__invitee_number = ""

    def start(self):
        try:
            self.__in_talkshow_setup = True
            self.__host = self.__get_host(self.__host_id)
            if self.__host is None or self.__host.phone is None:
                self.stop(False)
                return
            # self.program.set_running_action(self)
            self.__scheduler.start()
            self.__call_handler.register_for_incoming_calls(self)
            self.__call_handler.register_for_incoming_dtmf(self, str(self.__host.phone.raw_number))
            self.__call_handler.register_for_host_call(self, str(self.__host.phone.raw_number))
            self.request_host_call()
        except Exception as e:
            print e

    def stop(self, graceful=True, call_info=None):
        self.hangup_call()
        # Stop scheduler
        self.__scheduler.shutdown()
        # deregister from any triggers
        self.__call_handler.deregister_for_incoming_calls(self)
        self.__call_handler.deregister_for_incoming_dtmf(str(self.__host.phone.raw_number))
        self.program.notify_program_action_stopped(graceful, call_info)

    def __get_host(self, host_id):
        host = self.program.radio_station.db.query(Person).filter(Person.id == host_id).first()
        return host

    def request_host_call(self):
        self.__in_talkshow_setup = True
        result = self.__call_handler.call(self, self.__host.phone.raw_number, None, False,
                                          15)  # call ends in 15 mins max
        self.program.log_program_activity("result of host call is " + str(result))
        if not result[0]:
            self.stop(False)

    def __request_station_call(self):
        if self.program.radio_station.station.is_high_bandwidth:
            result = self.__call_station_via_sip()
            if result is None or not result[0]:  # Now try calling the SIM (ideally do primary, then secondary)
                result = self.__call_station_via_goip()
        else:
            result = self.__call_station_via_goip()
        if result is None or not result[0]:
            self.stop(False)

    def __call_station_via_sip(self):
        result = None
        # Try a high bandwidth call first
        if self.program.radio_station.station.sip_username is not None:
            result = self.__call_handler.call(self, self.program.radio_station.station.sip_username,
                                              self.__host.phone.raw_number, True,
                                              self.duration)
            self.program.log_program_activity("result of station call via SIP is " + str(result))
        return result

    def __call_station_via_goip(self):
        result = None
        if self.program.radio_station.station.primary_transmitter_phone is not None:
            result = self.__call_handler.call(self,
                                              self.program.radio_station.station.primary_transmitter_phone.raw_number,
                                              self.__host.phone.raw_number, False,
                                              self.duration)
            self.program.log_program_activity("result of station call (primary) via GoIP is " + str(result))
            if not result[
                    0] and self.program.radio_station.station.secondary_transmitter_phone is not None:  # Go for the secondary line of the station, if duo SIM phone
                result = self.__call_handler.call(self,
                                                  self.program.radio_station.station.secondary_transmitter_phone.raw_number,
                                                  self.__host.phone.raw_number, False,
                                                  self.duration)
                self.program.log_program_activity("result of station call (secondary) via GoIP is " + str(result))
        return result

    def notify_call_answered(self, answer_info):
        if self.__host.phone.raw_number not in self.__available_calls:
            self.__available_calls[answer_info['Caller-Destination-Number'][-12:]] = answer_info
            self.__inquire_host_readiness()
            self.program.log_program_activity("host call has been answered")
        elif 'Caller-Destination-Number' in answer_info and answer_info['Caller-Destination-Number'][-12:] == self.__invitee_number:
            self.__available_calls[answer_info['Caller-Destination-Number'][-12:]] = answer_info
            self.__invitee_number = "";
            self.__collecting_digits_to_call = False
        else:  # This notification is from answering the host call
            self.__available_calls[answer_info['Caller-Destination-Number'][-12:]] = answer_info
            # result1 = self.__schedule_warning()
            # result2 = self.__schedule_hangup()
        self.__call_handler.register_for_call_hangup(self, answer_info['Caller-Destination-Number'][-12:])

    def warn_number(self):
        seconds = self.duration - self.__warning_time
        if self.__host.phone.raw_number in self.__available_calls and 'Channel-Call-UUID' in self.__available_calls[
                self.__host.phone.raw_number]:
            result = self.__call_handler.speak(
                'Your call will end in ' + str(seconds) + 'seconds',
                self.__available_calls[self.__host.phone.raw_number]['Channel-Call-UUID'])
            self.program.log_program_activity("result of warning is " + result)

    def __pause_call(self):  # hangup and schedule to call later
        self.__schedule_host_callback()
        self.hangup_call()

    def notify_call_hangup(self, event_json):
        if 'Caller-Destination-Number' in event_json:
            if event_json[
                    'Caller-Destination-Number'] in self.__community_call_UUIDs:  # a community caller is hanging up
                del self.__community_call_UUIDs[event_json['Caller-Destination-Number']]
                self.__call_handler.deregister_for_call_hangup(event_json['Caller-Destination-Number'])
            elif event_json['Caller-Destination-Number'] in self.__invitee_call_UUIDs:
                del self.__invitee_call_UUIDs[event_json['Caller-Destination-Number']]
                self.__call_handler.deregister_for_call_hangup(event_json['Caller-Destination-Number'])
            elif event_json['Caller-Destination-Number'] == self.__host.phone.raw_number or \
                    event_json['Caller-Destination-Number'] in \
                    [self.program.radio_station.station.sip_username,
                     self.program.radio_station.station.primary_transmitter_phone.raw_number,
                     self.program.radio_station.station.secondary_transmitter_phone.raw_number]:  # It is a hangup by
                #  the station or the host
                self.program.log_program_activity(
                    "Program terminated because {0} hangup".format(event_json['Caller-Destination-Number']))
                self.stop(True)

    def __inquire_host_readiness(self):
        self.__call_handler.speak(
            'You are scheduled to host a talk show at this time. If you are ready, press one, if not ready, press two',
            self.__available_calls[self.__host.phone.raw_number]['Channel-Call-UUID'])
        self.program.log_program_activity("Asking if host is ready")

    def hangup_call(self):  # hangup the ongoing call
        for available_call in self.__available_calls:
{'fraction_non_alphanumeric': 0.0824679662355013, 'fraction_numerical': 0.003279285844416105, 'mean_word_length': 2.309485530546624, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 36, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3800723', 'n_tokens_mistral': 4537, 'n_tokens_neox': 4456, 'n_words': 912}