Пример #1
0
def assure_citizen_alias(db, phone_number):
    ''' create citizen alias if does not exist yet '''

    from citizendesk.feeds.sms.citizen_alias.storage import get_one_by_phone_number as get_one_citizen_alias_by_phone_number
    from citizendesk.feeds.sms.citizen_alias.storage import get_one_by_id as get_one_citizen_alias_by_id
    alias_res = get_one_citizen_alias_by_phone_number(db, phone_number)
    if alias_res[0]:
        if (type(alias_res[1]) is not dict) or ('_id' not in alias_res[1]):
            return (False, 'wrong loaded citizen alias structure')
        return (True, alias_res[1])

    authority = get_conf('authority')
    phone_identifier_type = get_conf('phone_identifier_type')

    alias_new = {
        'authority': authority,
        'identifiers': [{'type':phone_identifier_type, 'value':phone_number}],
        'verified': False,
        'local': False
    }

    alias_id = citizen_holder.save_alias(alias_new)
    if not alias_id:
        return (False, 'can not save citizen alias info')

    alias_res = get_one_citizen_alias_by_id(db, alias_id)
    if (not alias_res[0]) or (type(alias_res[1]) is not dict) or ('_id' not in alias_res[1]):
        return (False, 'wrong reloaded citizen alias structure')

    return alias_res
Пример #2
0
def get_sms(phone_number):
    session_info = None

    phone_number_normalized = normalize_phone_number(phone_number)
    if not phone_number_normalized:
        return None

    feed_type = get_conf('feed_type')
    authority = get_conf('authority')
    channel_value_send = get_conf('channel_value_send')
    channel_value_receive = get_conf('channel_value_receive')

    sess_spec_sent = {
        'feed_type': feed_type,
        'channels': {
            '$elemMatch': {
                'value': channel_value_send
            }
        },
        'recipients': {
            '$elemMatch': {
                'authority': authority,
                'identifiers.user_id_search': phone_number_normalized
            }
        }
    }
    res = holder.find_last_session(sess_spec_sent)
    if (type(res) is not dict) or ('produced' not in res):
        res = None
    if res:
        session_info = res

    sess_spec_received = {
        'feed_type': feed_type,
        'channels': {
            '$elemMatch': {
                'value': channel_value_receive
            }
        },
        'authors': {
            '$elemMatch': {
                'authority': authority,
                'identifiers.user_id_search': phone_number_normalized
            }
        }
    }
    res = holder.find_last_session(sess_spec_received)
    if (type(res) is not dict) or ('produced' not in res):
        res = None
    if res:
        if not session_info:
            session_info = res
        else:
            if res['produced'] >= session_info['produced']:
                session_info = res

    return session_info
Пример #3
0
def prepare_sms_send_report(targets, recipients, message, user_id=None, language=None, sensitive=None, client_ip=None):
    ''' preparing an sms-based report when the sms is sent not as a reply, i.e. starting a new session for it '''

    channel_type = get_conf('channel_type')
    channel_value = get_conf('channel_value_send')
    feed_type = get_conf('feed_type')

    channel = {
        'type': channel_type,
        'value': channel_value,
        'filter': None,
        'reasons': None,
        'request': None
    }

    current_timestamp = datetime.datetime.now()

    doc = {
        'report_id': gen_id(feed_type, channel_type, channel_value, current_timestamp), # to generate the report_id
        'channels': [channel],
        'recipients': recipients,
        'authors': [], # no citizen here
        'endorsers': [], # no citizen here
        'publisher': get_conf('publisher'),
        'feed_type': feed_type,
        'parent_id': None, # not a reply here
        'session': None,
        'user_id': user_id, # who requested the sending, if not automatic
        'pinned_id': None,
        'coverage_id': None,
        'language': language,
        'produced': current_timestamp,
        'created': current_timestamp,
        'assignments': [],
        'original_id': None,
        'original': {'message': message},
        'texts': [{'original': message, 'transcript': None}],
        'tags': [], # we shall extract possible #tags, alike at sms receiving
        'is_published': False,
        'sensitive': None,
        'summary': False,
        'local': True,
        'targets': targets, # alias_ids and/or group_ids for replies, on sent reports
        'proto': False,
        'client_ip': client_ip # for logging
    }

    if sensitive is not None:
        doc['sensitive'] = _get_boolean(sensitive)

    doc['session'] = doc['report_id']

    doc['tags'] = _extract_tags(message)

    return doc
Пример #4
0
def assure_citizen_alias(db, phone_number):
    ''' create citizen alias if does not exist yet '''

    from citizendesk.feeds.sms.citizen_alias.storage import get_one_by_phone_number as get_one_citizen_alias_by_phone_number
    from citizendesk.feeds.sms.citizen_alias.storage import get_one_by_id as get_one_citizen_alias_by_id
    alias_res = get_one_citizen_alias_by_phone_number(db, phone_number)
    if alias_res[0]:
        if (type(alias_res[1]) is not dict) or ('_id' not in alias_res[1]):
            return (False, 'wrong loaded citizen alias structure')
        return (True, alias_res[1])

    authority = get_conf('authority')

    alias_new = {
        'authority': authority,
        'identifiers': _create_phone_number_identities(phone_number),
        'verified': False,
        'local': False
    }

    alias_id = citizen_holder.save_alias(alias_new)
    if not alias_id:
        return (False, 'can not save citizen alias info')

    alias_res = get_one_citizen_alias_by_id(db, alias_id)
    if (not alias_res[0]) or (type(alias_res[1]) is not dict) or ('_id' not in alias_res[1]):
        return (False, 'wrong reloaded citizen alias structure')

    return alias_res
Пример #5
0
def get_sms(phone_number):
    session_info = None

    phone_number_normalized = normalize_phone_number(phone_number)
    if not phone_number_normalized:
        return None

    feed_type = get_conf('feed_type')
    authority = get_conf('authority')
    channel_value_send = get_conf('channel_value_send')
    channel_value_receive = get_conf('channel_value_receive')

    sess_spec_sent = {
        'feed_type': feed_type,
        'channels': {'$elemMatch': {'value': channel_value_send}},
        'recipients': {'$elemMatch': {'authority': authority, 'identifiers.user_id_search': phone_number_normalized}}
    }
    res = holder.find_last_session(sess_spec_sent)
    if (type(res) is not dict) or ('produced' not in res):
        res = None
    if res:
        session_info = res

    sess_spec_received = {
        'feed_type': feed_type,
        'channels': {'$elemMatch': {'value': channel_value_receive}},
        'authors': {'$elemMatch': {'authority': authority, 'identifiers.user_id_search': phone_number_normalized}}
    }
    res = holder.find_last_session(sess_spec_received)
    if (type(res) is not dict) or ('produced' not in res):
        res = None
    if res:
        if not session_info:
            session_info = res
        else:
            if res['produced'] >= session_info['produced']:
                session_info = res

    return session_info
Пример #6
0
def get_one_by_phone_number(db, phone_number, active=True):
    '''
    returns data of a single sms citizen alias with given phone number
    '''
    if not db:
        return (False, 'inner application error')

    coll = db[collection]

    phone_identifier_type = get_conf('phone_identifier_type')
    spec = {'active': active, 'authority': AUTHORITY, 'identifiers': {'type':phone_identifier_type, 'value':phone_number}}
    doc = coll.find_one(spec)

    if not doc:
        return (False, 'citizen alias info not found')

    return (True, doc)
Пример #7
0
def prepare_sms_send_report(targets,
                            recipients,
                            message,
                            user_id=None,
                            language=None,
                            sensitive=None,
                            client_ip=None):
    ''' preparing an sms-based report when the sms is sent not as a reply, i.e. starting a new session for it '''

    channel_type = get_conf('channel_type')
    channel_value = get_conf('channel_value_send')
    feed_type = get_conf('feed_type')

    if user_id:
        user_id = _get_id_value(user_id)

    channel = {
        'type': channel_type,
        'value': channel_value,
        'filter': None,
        'reasons': None,
        'request': None
    }

    current_timestamp = datetime.datetime.utcnow()

    doc = {
        'report_id':
        gen_id(feed_type, channel_type, channel_value,
               current_timestamp),  # to generate the report_id
        'channels': [channel],
        'recipients':
        recipients,
        'authors': [],  # no citizen here
        'endorsers': [],  # no citizen here
        'publisher':
        get_conf('publisher'),
        'feed_type':
        feed_type,
        'parent_id':
        None,  # not a reply here
        'session':
        None,
        'user_id':
        user_id,  # who requested the sending, if not automatic
        'pinned_id':
        None,
        'language':
        language,
        'produced':
        current_timestamp,
        '_created':
        current_timestamp,
        '_updated':
        current_timestamp,
        'assignments': [],
        'original_id':
        None,
        'original': {
            'message': message
        },
        'texts': [{
            'original': message,
            'transcript': None
        }],
        'tags': [],  # we shall extract possible #tags, alike at sms receiving
        'sensitive':
        None,
        'summary':
        False,
        'local':
        True,
        'targets':
        targets,  # alias_ids and/or group_ids for replies, on sent reports
        'proto':
        False,
        'client_ip':
        client_ip  # for logging
    }

    if sensitive is not None:
        doc['sensitive'] = _get_boolean(sensitive)

    doc['session'] = doc['report_id']

    doc['tags'] = _extract_tags(message)

    return doc
Пример #8
0
def ask_sender(db, session_start, orig_report, alias_info, phone_number, common_config):
    # for now, general config in a config file, or 'cd_config' collection in 'sms' document
    # by phone_number: in citizen_alias structure

    use_config = {
        'sms_reply_send': None,
        'sms_reply_message': None,
        'sms_confirm_send': None,
        'sms_confirm_message': None,
    }

    for key in use_config:
        if key in common_config:
            use_config[key] = common_config[key]

    alias_config = {}
    if ('config' in alias_info) and (type(alias_info['config']) is dict):
        alias_config = alias_info['config']
    for key in use_config:
        if (key in alias_config) and (alias_config[key] is not None):
            use_config[key] = alias_config[key]

    message = None
    if session_start:
        to_send = use_config['sms_reply_send']
        if to_send:
            message = use_config['sms_reply_message']
    else:
        to_send = use_config['sms_confirm_send']
        if to_send:
            message = use_config['sms_confirm_message']

    if not message:
        return (True, None)

    if not controller:
        return (False, 'no sms gateway controller available')

    conf_alias_doctype = get_conf('alias_doctype')
    conf_authority = get_conf('authority')
    conf_phone_identifier_type = get_conf('phone_identifier_type')

    use_targets = [{'type':conf_alias_doctype, 'value':alias_info['_id']}]
    use_recipients = [{'authority':conf_authority, 'identifiers':[{'type':conf_phone_identifier_type, 'value':phone_number}]}]
    use_phone_numbers = [phone_number]

    doc = _prepare_sms_reply_report(orig_report, use_targets, use_recipients, message)
    if not doc:
        return (False, 'automatic report could not be prepared')
    doc['automatic'] = True

    doc_id = report_holder.save_report(doc)
    if not doc_id:
        return (False, 'automatic report could not be saved')

    sms_gateway_url = common_config['sms_gateway_url']
    sms_gateway_key = common_config['sms_gateway_key']

    connector = controller.SMSConnector(sms_gateway_url, sms_gateway_key)
    res = connector.send_sms(message, {'phone_numbers': use_phone_numbers})
    if not res[0]:
        report_holder.delete_report(doc_id)
        return (False, 'automatic message could not be sent', res[1])

    return (True, {'_id': doc_id})
Пример #9
0
def do_post(db, params, main_config, client_ip):
    '''
    * assure citizen_alias exists (i.e. create/save if does not yet)
    * find if following a previous report (incl. taking its session)
    * create and save the report
    * if starting a new session and with auto-replies:
        * create a reply-report
        * send a reply message (via gateway)
    '''
    logger = get_logger()

    # taking given params
    feed_type = get_conf('feed_type')
    publisher = get_conf('publisher')

    feed_name = params['feed']
    phone_number = params['phone']
    message = params['text']
    received = params['time']

    timestamp = datetime.datetime.now()

    # assuring the citizen
    alias_id = None
    alias_info = None
    alias_res = assure_citizen_alias(db, phone_number)
    if alias_res[0]:
        alias_info = alias_res[1]
        alias_id = alias_info['_id']

    # finding the followed report
    last_report = get_sms(phone_number)
    if last_report:
        for key in ['produced', 'session', 'report_id']:
            if key not in last_report:
                last_report = None

    # creating the report
    authority = get_conf('authority')
    phone_identifier_type = get_conf('phone_identifier_type')
    channel_type = get_conf('channel_type')
    channel_value_receive = get_conf('channel_value_receive')

    sms_filter = None
    if feed_name:
        sms_filter = {'feed_name': feed_name}

    channels = [{'type': channel_type, 'value': channel_value_receive, 'filter': sms_filter, 'request': None, 'reasons': None}]
    authors = [{'authority': authority, 'identifiers': [{'type': phone_identifier_type, 'value': phone_number}]}]
    endorsers = []

    original = {'message': message}
    texts = [{'original': message, 'transcript': None}]
    tags = []
    if message:
        tags = _extract_tags(message)

    report_id = gen_id(feed_type, channel_type, channel_value_receive, timestamp)
    session = report_id
    parent_id = None
    new_session = True

    pinned_id = None
    assignments = []

    if last_report:
        if is_within_session(last_report['produced'], received, main_config):
            session = last_report['session']
            parent_id = last_report['report_id']
            if 'pinned_id' in last_report:
                pinned_id = last_report['pinned_id']
            if 'assignments' in last_report:
                assignments = last_report['assignments']
            new_session = False

    report = {}
    report['report_id'] = report_id
    report['parent_id'] = parent_id
    report['client_ip'] = client_ip
    report['feed_type'] = feed_type
    report['produced'] = received
    report['session'] = session
    report['publisher'] = publisher
    report['channels'] = channels
    report['authors'] = authors
    report['original'] = original
    report['texts'] = texts
    report['tags'] = tags

    report['pinned_id'] = pinned_id
    report['assignments'] = assignments

    report['proto'] = False

    report_doc_id = report_holder.save_report(report)
    if not report_doc_id:
        return (False, 'can not save SMS report')

    report = report_holder.provide_report(feed_type, report_id)

    reply_res = ask_sender(db, new_session, report, alias_info, phone_number, main_config)
    if not reply_res[0]:
        reason = str(reply_res[1])
        if 2 < len(reply_res):
            reason += ', ' + str(reply_res[2])
        logger.warning('Issue during auto-reply SMS: ' + reason)

    return (True, str(report_doc_id))
Пример #10
0
def do_post_send(db, sms_gateway_api, sms_gateway_url, sms_gateway_key, message, targets, user_id, language, sensitive, client_ip):
    try:
        controller = importlib.import_module('citizendesk.feeds.sms.external.' + sms_gateway_api)
    except:
        controller = None

    if not controller:
        return (False, 'no sms gateway controller available')
    if not db:
        return (False, 'no database available')

    if not sms_gateway_url:
        return (False, 'no sms gateway url configured')
    if not sms_gateway_key:
        return (False, 'no sms gateway key configured')

    if not message:
        return (False, 'no message provided')
    if not targets:
        return (False, 'no targets provided')

    from citizendesk.feeds.sms.citizen_alias.storage import get_one_by_id as get_one_citizen_alias_by_id

    use_targets = []
    use_recipients = []
    use_phone_numbers = []

    authority = get_conf('authority')
    alias_doctype = get_conf('alias_doctype')

    if type(targets) not in [list, tuple]:
        return (False, '')
    for one_target in targets:
        if type(one_target) is not dict:
            continue
        if 'type' not in one_target:
            continue
        if one_target['type'] != alias_doctype:
            continue
        if 'value' not in one_target:
            continue

        one_target_id = _get_id_value(one_target['value'])
        alias_res = get_one_citizen_alias_by_id(db, one_target_id)
        if (not alias_res) or (not alias_res[0]):
            continue
        alias = alias_res[1]
        if (type(alias) is not dict) or (not alias):
            continue
        if ('identifiers' not in alias) or (not alias['identifiers']):
            continue

        one_phone_number = _get_phone_number(alias)
        if not one_phone_number:
            continue

        one_recipient = {'authority': authority, 'identifiers': alias['identifiers']}

        use_phone_numbers.append(one_phone_number)
        use_recipients.append(one_recipient)
        use_targets.append(one_target)

    if not use_targets:
        return (False, 'no valid recipient found')

    # putting all the recipients into a single report; and thus using its session for next communication with all the recipients
    try:
        report = _prepare_sms_send_report(use_targets, use_recipients, message, user_id, language, sensitive, client_ip)
    except:
        report = None
    if not report:
        return (False, 'report could not be prepared')

    # we either save the report before sms sending, and deleting it if sending fails,
    # or we first send sms, and if success on it, we save the report then;
    # thus either transiently having a false report, or a possibility of not having the report
    # on sent sms if the report saving fails at the end (should not hopefully though)

    doc_id = report_holder.save_report(report)
    if not doc_id:
        return (False, 'report could not be saved')

    connector = controller.SMSConnector(sms_gateway_url, sms_gateway_key)
    res = connector.send_sms(message, {'phone_numbers': use_phone_numbers})
    if not res[0]:
        report_holder.delete_report(doc_id)
        return (False, 'message could not be sent', res[1])

    return (True, {'_id': doc_id})
Пример #11
0
def ask_sender(db, session_start, orig_report, alias_info, phone_number, common_config):
    # for now, general config in a config file, or 'core_config' collection in 'sms' document
    # by phone_number: in citizen_alias structure

    try:
        gateway_api = common_config['gateway_api']
    except:
        gateway_api = 'frontlinesms'

    try:
        controller = importlib.import_module('citizendesk.feeds.sms.external.' + gateway_api)
    except:
        controller = None

    use_config = {
        'sms_reply_send': None,
        'sms_reply_message': None,
        'sms_confirm_send': None,
        'sms_confirm_message': None,
    }

    for key in use_config:
        if key in common_config:
            use_config[key] = common_config[key]

    alias_config = {}
    if ('config' in alias_info) and (type(alias_info['config']) is dict):
        alias_config = alias_info['config']
    for key in use_config:
        if (key in alias_config) and (alias_config[key] is not None):
            use_config[key] = alias_config[key]

    message = None
    if session_start:
        to_send = use_config['sms_reply_send']
        if to_send:
            message = use_config['sms_reply_message']
    else:
        to_send = use_config['sms_confirm_send']
        if to_send:
            message = use_config['sms_confirm_message']

    if not message:
        return (True, None)

    if not controller:
        return (False, 'no sms gateway controller available')

    conf_alias_doctype = get_conf('alias_doctype')
    conf_authority = get_conf('authority')

    use_targets = [{'type':conf_alias_doctype, 'value':alias_info['_id']}]
    use_identifiers = _create_phone_number_identities(phone_number)
    use_recipients = [{'authority':conf_authority, 'identifiers':use_identifiers}]
    use_phone_numbers = [phone_number]

    doc = _prepare_sms_reply_report(orig_report, use_targets, use_recipients, message)
    if not doc:
        return (False, 'automatic report could not be prepared')
    doc['automatic'] = True

    doc_id = report_holder.save_report(doc)
    if not doc_id:
        return (False, 'automatic report could not be saved')

    sms_gateway_url = common_config['sms_gateway_url']
    sms_gateway_key = common_config['sms_gateway_key']

    connector = controller.SMSConnector(sms_gateway_url, sms_gateway_key)
    res = connector.send_sms(message, {'phone_numbers': use_phone_numbers})
    if not res[0]:
        report_holder.delete_report(doc_id)
        return (False, 'automatic message could not be sent', res[1])

    return (True, {'_id': doc_id})
Пример #12
0
def do_post(db, params, main_config, client_ip):
    '''
    * assure citizen_alias exists (i.e. create/save if does not yet)
    * find if following a previous report (incl. taking its session)
    * create and save the report
    * if starting a new session and with auto-replies:
        * create a reply-report
        * send a reply message (via gateway)
    '''
    logger = get_logger()

    # taking given params
    feed_type = get_conf('feed_type')
    publisher = get_conf('publisher')

    feed_name = params['feed']
    phone_number = params['phone']
    message = params['text']
    received = params['time']

    timestamp = datetime.datetime.utcnow()

    # assuring the citizen
    alias_id = None
    alias_info = None
    alias_res = assure_citizen_alias(db, phone_number)
    if alias_res[0]:
        alias_info = alias_res[1]
        alias_id = alias_info['_id']

    # finding the followed report
    last_report = get_sms(phone_number)
    if last_report:
        for key in ['produced', 'session', 'report_id']:
            if key not in last_report:
                last_report = None

    # creating the report
    authority = get_conf('authority')
    channel_type = get_conf('channel_type')
    channel_value_receive = get_conf('channel_value_receive')

    sms_filter = None
    if feed_name:
        sms_filter = {'feed_name': feed_name}

    use_identifiers = _create_phone_number_identities(phone_number)

    channels = [{'type': channel_type, 'value': channel_value_receive, 'filter': sms_filter, 'request': None, 'reasons': None}]
    authors = [{'authority': authority, 'identifiers': use_identifiers}]
    endorsers = []

    original = {'message': message}
    texts = [{'original': message, 'transcript': None}]
    tags = []
    if message:
        tags = _extract_tags(message)

    report_id = gen_id(feed_type, channel_type, channel_value_receive, timestamp)
    session = report_id
    parent_id = None
    new_session = True

    pinned_id = None
    assignments = []

    if last_report:
        if is_within_session(last_report['produced'], received, main_config):
            session = last_report['session']
            parent_id = last_report['report_id']
            if 'pinned_id' in last_report:
                pinned_id = last_report['pinned_id']
            if 'assignments' in last_report:
                assignments = last_report['assignments']
            new_session = False

    report = {}
    report['report_id'] = report_id
    report['parent_id'] = parent_id
    report['client_ip'] = client_ip
    report['feed_type'] = feed_type
    report['produced'] = received
    report['session'] = session
    report['publisher'] = publisher
    report['channels'] = channels
    report['authors'] = authors
    report['original'] = original
    report['texts'] = texts
    report['tags'] = tags

    report['pinned_id'] = pinned_id
    report['assignments'] = assignments

    report['proto'] = False

    report_doc_id = report_holder.save_report(report)
    if not report_doc_id:
        return (False, 'can not save SMS report')

    report = report_holder.provide_report(feed_type, report_id)

    reply_res = ask_sender(db, new_session, report, alias_info, phone_number, main_config)
    if not reply_res[0]:
        reason = str(reply_res[1])
        if 2 < len(reply_res):
            reason += ', ' + str(reply_res[2])
        logger.warning('Issue during auto-reply SMS: ' + reason)

    return (True, str(report_doc_id))
Пример #13
0
def do_post_reply(db, sms_gateway_api, sms_gateway_url, sms_gateway_key, message, report_id, user_id, language, sensitive, client_ip):
    try:
        controller = importlib.import_module('citizendesk.feeds.sms.external.' + sms_gateway_api)
    except:
        controller = None

    if not controller:
        return (False, 'no sms gateway controller available')
    if not db:
        return (False, 'no database available')

    if not sms_gateway_url:
        return (False, 'no sms gateway url configured')
    if not sms_gateway_key:
        return (False, 'no sms gateway key configured')

    if not message:
        return (False, 'no message provided')
    if not report_id:
        return (False, 'report_id not provided')

    from citizendesk.feeds.sms.report.storage import do_get_one_by_id as get_one_report_by_id
    from citizendesk.feeds.sms.citizen_alias.storage import get_one_by_id as get_one_citizen_alias_by_id
    from citizendesk.feeds.sms.citizen_alias.storage import get_one_by_phone_number as get_one_citizen_alias_by_phone_number

    report_id = _get_id_value(report_id)
    report_res = get_one_report_by_id(db, report_id)
    if not report_res[0]:
        return (False, 'report of given id not found')
    report_source = report_res[1]

    was_sent = False
    was_received = False

    channel_type = get_conf('channel_type')
    channel_value_send = get_conf('channel_value_send')
    channel_value_receive = get_conf('channel_value_receive')
    alias_doctype = get_conf('alias_doctype')
    authority = get_conf('authority')

    if type(report_source) is not dict:
        return (False, 'wrong structure of report')
    if ('channels' in report_source) and (type(report_source['channels']) in (list, tuple)):
        for one_channel in report_source['channels']:
            if (type(one_channel) is dict) and ('type' in one_channel) and ('value' in one_channel):
                if one_channel['type'] != channel_type:
                    continue
                if one_channel['value'] == channel_value_send:
                    was_sent = True
                if one_channel['value'] == channel_value_receive:
                    was_received = True

    if (not was_sent) and (not was_received):
        return (False, 'unknown form of report')

    citizen_aliases = []

    if was_sent and ('targets' in report_source) and (type(report_source['targets']) in (list, tuple)):
        for one_target in report_source['targets']:
            if (type(one_target) is dict) and ('type' in one_target) and ('value' in one_target):
                if one_target['type'] == alias_doctype:
                    one_target_value = _get_id_value(one_target['value'])
                    one_citizen_alias_res = get_one_citizen_alias_by_id(db, one_target_value)
                    if one_citizen_alias_res[0]:
                        citizen_aliases.append(one_citizen_alias_res[1])

    if was_received and ('authors' in report_source) and (type(report_source['authors']) in (list, tuple)):
        for one_author in report_source['authors']:
            one_phone_number = _get_phone_number(one_author)
            if not one_phone_number:
                continue
            one_citizen_alias_res = get_one_citizen_alias_by_phone_number(db, one_phone_number)
            if one_citizen_alias_res[0]:
                citizen_aliases.append(one_citizen_alias_res[1])

    if not citizen_aliases:
        return (False, 'not target suitable citizen alias found')

    use_targets = []
    use_recipients = []
    use_phone_numbers = []

    for one_citizen_alias in citizen_aliases:
        if (type(one_citizen_alias) is not dict):
            continue
        if ('_id' not in one_citizen_alias) or (not one_citizen_alias['_id']):
            continue
        one_target = {'type': alias_doctype, 'value': one_citizen_alias['_id']}

        if ('identifiers' not in one_citizen_alias) or (not one_citizen_alias['identifiers']):
            continue
        one_recipient = {'authority': authority, 'identifiers': one_citizen_alias['identifiers']}

        one_phone_number = _get_phone_number(one_citizen_alias)
        if not one_phone_number:
            continue

        use_phone_numbers.append(one_phone_number)
        use_recipients.append(one_recipient)
        use_targets.append(one_target)

    if not use_targets:
        return (False, 'no valid recipient found')

    # putting all the recipients into a single report; and thus using its session for next communication with all the recipients
    try:
        report = _prepare_sms_reply_report(report_source, use_targets, use_recipients, message, user_id, language, sensitive, client_ip)
    except:
        report = None
    if not report:
        return (False, 'report could not be prepared')

    # we either save the report before sms sending, and deleting it if sending fails,
    # or we first send sms, and if success on it, we save the report then;
    # thus either transiently having a false report, or a possibility of not having the report
    # on sent sms if the report saving fails at the end (should not hopefully though)

    doc_id = report_holder.save_report(report)
    if not doc_id:
        return (False, 'report could not be saved')

    connector = controller.SMSConnector(sms_gateway_url, sms_gateway_key)
    res = connector.send_sms(message, {'phone_numbers': use_phone_numbers})
    if not res[0]:
        report_holder.delete_report(doc_id)
        return (False, 'message could not be sent', res[1])

    return (True, {'_id': doc_id})
Пример #14
0
def do_post_one(db, alias_id, alias_spec, user_id):
    '''
    sets a basic info on phone_number-based citizen alias
    '''
    if not db:
        return (False, 'inner application error')

    if type(alias_spec) is not dict:
        return (False, 'citizen specification should be a dict')
    if 'phone_number' not in alias_spec:
        return (False, 'phone number specification not provided')
    use_phone_number = alias_spec['phone_number']
    try:
        use_phone_number = str(use_phone_number)
    except:
        return (False, 'wrong specification of phone number')
    if not use_phone_number:
        return (False, 'empty phone number specification')

    user_id = _get_id_value(user_id)

    if not alias_id:
        search_res = get_one_by_phone_number(db, use_phone_number)
        if search_res[0]:
            return (False, 'active citizen alias with given phone number already exists', search_res[1]['_id'])

    alias_doc = None
    if alias_id:
        alias_id = _get_id_value(alias_id)
        alias_doc = get_one_by_id(db, alias_id)
        if not alias_doc:
            return (False, 'citizen alias of provided id not found')

    spec_keys = {
        'description': [str, unicode],
        'name_first': [str, unicode],
        'name_last': [str, unicode],
        'name_full': [str, unicode],
        'languages': [list, tuple],
        'places': [list, tuple],
        'home_pages': [list, tuple],
        'verified': [bool]
    }

    phone_identifier_type = get_conf('phone_identifier_type')
    if not alias_doc:
        alias_use = {
            'authority': AUTHORITY,
            'identifiers': [{'type':phone_identifier_type, 'value':use_phone_number}],
            'verified': False,
            'local': True,
            'created_by': user_id
        }

        for key in spec_keys:
            if (key in alias_spec) and (type(alias_spec[key]) in spec_keys[key]):
                alias_use[key] = alias_spec[key]

        alias_id = citizen_holder.save_alias(alias_use)

        if not alias_id:
            return (False, 'can not save the citizen alias')

    else:
        alias_use = alias_doc
        alias_use['identifiers'] = [{'type':phone_identifier_type, 'value':use_phone_number}]
        alias_use['updated_by'] = user_id
        alias_use['local'] = True

        for key in spec_keys:
            if (key in alias_spec) and (type(alias_spec[key]) in spec_keys[key]):
                alias_use[key] = alias_spec[key]

        coll = db[collection]
        alias_id = coll.save(alias_use)

        if not alias_id:
            return (False, 'can not update the citizen alias')

    return (True, {'_id': alias_id})