<s> from StringIO import StringIO <EOL> import base64 <EOL> import logging <EOL> from datetime import datetime , timedelta , time <EOL> import re <EOL> import json <EOL> from couchdbkit import ResourceNotFound <EOL> import pytz <EOL> from django . contrib . auth import authenticate <EOL> from django . core . urlresolvers import reverse <EOL> from django . db import transaction <EOL> from django . http import HttpResponse , HttpResponseRedirect , HttpResponseBadRequest , Http404 <EOL> from django . shortcuts import render <EOL> from django . utils . decorators import method_decorator <EOL> from casexml . apps . case . models import CommCareCase <EOL> from corehq import privileges , toggles <EOL> from corehq . apps . hqadmin . views import BaseAdminSectionView <EOL> from corehq . apps . hqwebapp . doc_info import get_doc_info_by_id <EOL> from corehq . apps . hqwebapp . utils import get_bulk_upload_form , sign <EOL> from corehq . apps . reminders . util import can_use_survey_reminders <EOL> from corehq . apps . accounting . decorators import requires_privilege_with_fallback , requires_privilege_plaintext_response <EOL> from corehq . apps . api . models import require_api_user_permission , PERMISSION_POST_SMS , ApiUser <EOL> from corehq . apps . commtrack . models import AlertConfig <EOL> from corehq . apps . sms . api import ( <EOL> send_sms , <EOL> incoming , <EOL> send_sms_with_backend_name , <EOL> send_sms_to_verified_number , <EOL> DomainScopeValidationError , <EOL> MessageMetadata , <EOL> ) <EOL> from corehq . apps . domain . views import BaseDomainView , DomainViewMixin <EOL> from corehq . apps . hqwebapp . views import CRUDPaginatedViewMixin <EOL> from corehq . apps . sms . dbaccessors import get_forwarding_rules_for_domain <EOL> from corehq . apps . style . decorators import ( <EOL> use_bootstrap3 , <EOL> use_timepicker , <EOL> use_typeahead , <EOL> use_select2 , <EOL> use_jquery_ui , <EOL> upgrade_knockout_js , <EOL> use_datatables , <EOL> ) <EOL> from corehq . apps . users . decorators import require_permission <EOL> from corehq . apps . users . models import CouchUser , Permissions , CommCareUser <EOL> from corehq . apps . users import models as user_models <EOL> from corehq . apps . users . views . mobile . users import EditCommCareUserView <EOL> from corehq . apps . sms . models import ( <EOL> SMS , INCOMING , OUTGOING , ForwardingRule , <EOL> MessagingEvent , SelfRegistrationInvitation , <EOL> SQLMobileBackend , SQLMobileBackendMapping , PhoneLoadBalancingMixin , <EOL> SQLLastReadMessage <EOL> ) <EOL> from corehq . apps . sms . mixin import VerifiedNumber , BadSMSConfigException <EOL> from corehq . apps . sms . forms import ( ForwardingRuleForm , BackendMapForm , <EOL> InitiateAddSMSBackendForm , SubscribeSMSForm , <EOL> SettingsForm , SHOW_ALL , SHOW_INVALID , HIDE_ALL , ENABLED , DISABLED , <EOL> DEFAULT , CUSTOM , SendRegistrationInviationsForm , <EOL> WELCOME_RECIPIENT_NONE , WELCOME_RECIPIENT_CASE , <EOL> WELCOME_RECIPIENT_MOBILE_WORKER , WELCOME_RECIPIENT_ALL , ComposeMessageForm ) <EOL> from corehq . apps . sms . util import get_contact , get_sms_backend_classes <EOL> from corehq . apps . sms . messages import _MESSAGES <EOL> from corehq . apps . smsbillables . utils import country_name_from_isd_code_or_empty as country_name_from_code <EOL> from corehq . apps . groups . models import Group <EOL> from corehq . apps . domain . decorators import ( <EOL> login_and_domain_required , <EOL> login_or_digest_ex , <EOL> domain_admin_required , <EOL> require_superuser , <EOL> ) <EOL> from corehq . messaging . smsbackends . telerivet . models import SQLTelerivetBackend <EOL> from corehq . apps . translations . models import StandaloneTranslationDoc <EOL> from corehq . util . dates import iso_string_to_datetime <EOL> from corehq . util . spreadsheets . excel import WorkbookJSONReader <EOL> from corehq . util . timezones . conversions import ServerTime , UserTime <EOL> from corehq . util . quickcache import quickcache <EOL> from django . contrib import messages <EOL> from django . db . models import Q <EOL> from corehq . util . soft_assert import soft_assert <EOL> from corehq . util . timezones . utils import get_timezone_for_user <EOL> from django . views . decorators . csrf import csrf_exempt <EOL> from django . views . generic import View <EOL> from corehq . apps . domain . models import Domain <EOL> from corehq . const import SERVER_DATETIME_FORMAT , SERVER_DATE_FORMAT <EOL> from django . utils . translation import ugettext as _ , ugettext_noop , ugettext_lazy <EOL> from dimagi . utils . parsing import json_format_datetime , string_to_boolean <EOL> from dimagi . utils . decorators . memoized import memoized <EOL> from dimagi . utils . decorators . view import get_file <EOL> from dimagi . utils . logging import notify_exception <EOL> from dimagi . utils . web import json_response <EOL> from dimagi . utils . couch import CriticalSection <EOL> from dimagi . utils . couch . database import iter_docs <EOL> from dimagi . utils . couch . cache import cache_core <EOL> from django . conf import settings <EOL> from couchdbkit . resource import ResourceNotFound <EOL> from couchexport . models import Format <EOL> from couchexport . export import export_raw <EOL> from couchexport . shortcuts import export_response <EOL> SMS_CHAT_HISTORY_CHOICES = ( <EOL> ( ugettext_noop ( "<STR_LIT>" ) , <NUM_LIT:1> ) , <EOL> ( ugettext_noop ( "<STR_LIT>" ) , <NUM_LIT:7> ) , <EOL> ( ugettext_noop ( "<STR_LIT>" ) , <NUM_LIT:30> ) , <EOL> ) <EOL> @ login_and_domain_required <EOL> def default ( request , domain ) : <EOL> return HttpResponseRedirect ( reverse ( ComposeMessageView . urlname , args = [ domain ] ) ) <EOL> class BaseMessagingSectionView ( BaseDomainView ) : <EOL> section_name = ugettext_noop ( "<STR_LIT>" ) <EOL> @ method_decorator ( requires_privilege_with_fallback ( privileges . OUTBOUND_SMS ) ) <EOL> def dispatch ( self , * args , ** kwargs ) : <EOL> return super ( BaseMessagingSectionView , self ) . dispatch ( * args , ** kwargs ) <EOL> @ property <EOL> def section_url ( self ) : <EOL> return reverse ( "<STR_LIT>" , args = [ self . domain ] ) <EOL> class BaseAdvancedMessagingSectionView ( BaseMessagingSectionView ) : <EOL> """<STR_LIT>""" <EOL> @ method_decorator ( requires_privilege_with_fallback ( privileges . INBOUND_SMS ) ) <EOL> def dispatch ( self , * args , ** kwargs ) : <EOL> return super ( BaseAdvancedMessagingSectionView , self ) . dispatch ( * args , ** kwargs ) <EOL> class ComposeMessageView ( BaseMessagingSectionView ) : <EOL> template_name = '<STR_LIT>' <EOL> urlname = '<STR_LIT>' <EOL> page_title = _ ( '<STR_LIT>' ) <EOL> @ property <EOL> def page_context ( self ) : <EOL> page_context = super ( ComposeMessageView , self ) . page_context <EOL> tz = get_timezone_for_user ( self . request . couch_user , self . domain ) <EOL> page_context . update ( { <EOL> '<STR_LIT>' : datetime . utcnow ( ) , <EOL> '<STR_LIT>' : tz , <EOL> '<STR_LIT>' : datetime . now ( tz = tz ) , <EOL> '<STR_LIT>' : ComposeMessageForm ( domain = self . domain ) <EOL> } ) <EOL> page_context . update ( get_sms_autocomplete_context ( self . request , self . domain ) ) <EOL> return page_context <EOL> @ method_decorator ( require_permission ( Permissions . edit_data ) ) <EOL> @ method_decorator ( requires_privilege_with_fallback ( privileges . OUTBOUND_SMS ) ) <EOL> @ use_bootstrap3 <EOL> @ use_typeahead <EOL> def dispatch ( self , * args , ** kwargs ) : <EOL> return super ( BaseMessagingSectionView , self ) . dispatch ( * args , ** kwargs ) <EOL> @ csrf_exempt <EOL> def post ( request , domain ) : <EOL> """<STR_LIT>""" <EOL> _assert = soft_assert ( '<STR_LIT:@>' . join ( [ '<STR_LIT>' , '<STR_LIT>' ] ) , exponential_backoff = False ) <EOL> _assert ( False , "<STR_LIT>" ) <EOL> return HttpResponse ( '<STR_LIT:OK>' ) <EOL> @ require_api_user_permission ( PERMISSION_POST_SMS ) <EOL> def sms_in ( request ) : <EOL> """<STR_LIT>""" <EOL> backend_api = "<STR_LIT>" <EOL> phone_number = request . POST . get ( "<STR_LIT>" , None ) <EOL> message = request . POST . get ( "<STR_LIT:message>" , None ) <EOL> if phone_number is None or message is None : <EOL> return HttpResponse ( "<STR_LIT>" , status = <NUM_LIT> ) <EOL> else : <EOL> incoming ( phone_number , message , backend_api ) <EOL> return HttpResponse ( "<STR_LIT:OK>" ) <EOL> def get_sms_autocomplete_context ( request , domain ) : <EOL> """<STR_LIT>""" <EOL> phone_users = CouchUser . view ( "<STR_LIT>" , <EOL> startkey = [ domain ] , endkey = [ domain , { } ] , include_docs = True <EOL> ) <EOL> groups = Group . by_domain ( domain ) <EOL> contacts = [ "<STR_LIT>" ] <EOL> contacts . extend ( [ '<STR_LIT>' % group . name for group in groups ] ) <EOL> user_id = None <EOL> for user in phone_users : <EOL> if user . _id == user_id : <EOL> continue <EOL> contacts . append ( user . username ) <EOL> user_id = user . _id <EOL> return { "<STR_LIT>" : contacts } <EOL> @ login_and_domain_required <EOL> @ requires_privilege_with_fallback ( privileges . OUTBOUND_SMS ) <EOL> def send_to_recipients ( request , domain ) : <EOL> recipients = request . POST . get ( '<STR_LIT>' ) <EOL> message = request . POST . get ( '<STR_LIT:message>' ) <EOL> if not recipients : <EOL> messages . error ( request , _ ( "<STR_LIT>" ) ) <EOL> elif not message : <EOL> messages . error ( request , _ ( "<STR_LIT>" ) ) <EOL> else : <EOL> recipients = [ x . strip ( ) for x in recipients . split ( '<STR_LIT:U+002C>' ) if x . strip ( ) ] <EOL> phone_numbers = [ ] <EOL> group_names = [ ] <EOL> usernames = [ ] <EOL> phone_numbers = [ ] <EOL> unknown_usernames = [ ] <EOL> GROUP = "<STR_LIT>" <EOL> send_to_all_checked = False <EOL> for recipient in recipients : <EOL> if recipient == "<STR_LIT>" : <EOL> send_to_all_checked = True <EOL> phone_users = CouchUser . view ( "<STR_LIT>" , <EOL> startkey = [ domain ] , endkey = [ domain , { } ] , include_docs = True <EOL> ) <EOL> for user in phone_users : <EOL> usernames . append ( user . username ) <EOL> group_names = [ ] <EOL> break <EOL> elif ( not send_to_all_checked ) and recipient . endswith ( GROUP ) : <EOL> name = recipient [ : - len ( GROUP ) ] . strip ( ) <EOL> group_names . append ( name ) <EOL> elif re . match ( r'<STR_LIT>' , recipient ) : <EOL> def wrap_user_by_type ( u ) : <EOL> return getattr ( user_models , u [ '<STR_LIT>' ] [ '<STR_LIT>' ] ) . wrap ( u [ '<STR_LIT>' ] ) <EOL> phone_users = CouchUser . view ( "<STR_LIT>" , <EOL> keys = [ recipient , recipient [ <NUM_LIT:1> : ] ] , include_docs = True , <EOL> wrapper = wrap_user_by_type ) . all ( ) <EOL> phone_users = filter ( lambda u : u . is_member_of ( domain ) , phone_users ) <EOL> if len ( phone_users ) > <NUM_LIT:0> : <EOL> phone_numbers . append ( ( phone_users [ <NUM_LIT:0> ] , recipient ) ) <EOL> else : <EOL> phone_numbers . append ( ( None , recipient ) ) <EOL> elif ( not send_to_all_checked ) and re . match ( r'<STR_LIT>' , recipient ) : <EOL> usernames . append ( recipient ) <EOL> else : <EOL> unknown_usernames . append ( recipient ) <EOL> login_ids = { <EOL> r [ '<STR_LIT:key>' ] : r [ '<STR_LIT:id>' ] for r in CommCareUser . get_db ( ) . view ( <EOL> "<STR_LIT>" , keys = usernames , reduce = False ) . all ( ) } <EOL> for username in usernames : <EOL> if username not in login_ids : <EOL> unknown_usernames . append ( username ) <EOL> login_ids = login_ids . values ( ) <EOL> users = [ ] <EOL> empty_groups = [ ] <EOL> if len ( group_names ) > <NUM_LIT:0> : <EOL> users . extend ( CouchUser . view ( '<STR_LIT>' , keys = [ [ domain , gn ] for gn in group_names ] , <EOL> include_docs = True ) . all ( ) ) <EOL> if len ( users ) == <NUM_LIT:0> : <EOL> empty_groups = group_names <EOL> users . extend ( CouchUser . view ( '<STR_LIT>' , keys = login_ids , include_docs = True ) . all ( ) ) <EOL> users = [ user for user in users if user . is_active and not user . is_deleted ( ) ] <EOL> phone_numbers . extend ( [ ( user , user . phone_number ) for user in users ] ) <EOL> failed_numbers = [ ] <EOL> no_numbers = [ ] <EOL> sent = [ ] <EOL> if len ( phone_numbers ) == <NUM_LIT:1> : <EOL> recipient = phone_numbers [ <NUM_LIT:0> ] [ <NUM_LIT:0> ] <EOL> else : <EOL> recipient = None <EOL> logged_event = MessagingEvent . create_event_for_adhoc_sms ( domain , recipient = recipient ) <EOL> for user , number in phone_numbers : <EOL> if not number : <EOL> no_numbers . append ( user . raw_username ) <EOL> else : <EOL> args = [ user . doc_type , user . get_id ] if user else [ ] <EOL> logged_subevent = logged_event . create_subevent_for_single_sms ( * args ) <EOL> if send_sms ( <EOL> domain , user , number , message , <EOL> metadata = MessageMetadata ( messaging_subevent_id = logged_subevent . pk ) <EOL> ) : <EOL> sent . append ( "<STR_LIT:%s>" % ( user . raw_username if user else number ) ) <EOL> logged_subevent . completed ( ) <EOL> else : <EOL> failed_numbers . append ( "<STR_LIT>" % ( <EOL> number , <EOL> user . raw_username if user else "<STR_LIT>" <EOL> ) ) <EOL> logged_subevent . error ( MessagingEvent . ERROR_INTERNAL_SERVER_ERROR ) <EOL> logged_event . completed ( ) <EOL> def comma_reminder ( ) : <EOL> messages . error ( request , _ ( "<STR_LIT>" <EOL> "<STR_LIT>" ) ) <EOL> if empty_groups or failed_numbers or unknown_usernames or no_numbers : <EOL> if empty_groups : <EOL> messages . error ( request , _ ( "<STR_LIT>" ) + ( '<STR_LIT:U+002CU+0020>' . join ( empty_groups ) ) ) <EOL> comma_reminder ( ) <EOL> if no_numbers : <EOL> messages . error ( request , _ ( "<STR_LIT>" ) + ( '<STR_LIT:U+002CU+0020>' . join ( no_numbers ) ) ) <EOL> if failed_numbers : <EOL> messages . error ( request , _ ( "<STR_LIT>" ) + ( '<STR_LIT:U+002CU+0020>' . join ( failed_numbers ) ) ) <EOL> if unknown_usernames : <EOL> messages . error ( request , _ ( "<STR_LIT>" ) + ( '<STR_LIT:U+002CU+0020>' . join ( unknown_usernames ) ) ) <EOL> comma_reminder ( ) <EOL> if sent : <EOL> messages . success ( request , _ ( "<STR_LIT>" ) + ( '<STR_LIT:U+002CU+0020>' . join ( sent ) ) ) <EOL> else : <EOL> messages . info ( request , _ ( "<STR_LIT>" ) ) <EOL> else : <EOL> messages . success ( request , _ ( "<STR_LIT>" ) ) <EOL> return HttpResponseRedirect ( <EOL> request . META . get ( '<STR_LIT>' ) or <EOL> reverse ( ComposeMessageView . urlname , args = [ domain ] ) <EOL> ) <EOL> @ domain_admin_required <EOL> @ requires_privilege_with_fallback ( privileges . INBOUND_SMS ) <EOL> def message_test ( request , domain , phone_number ) : <EOL> if request . method == "<STR_LIT:POST>" : <EOL> message = request . POST . get ( "<STR_LIT:message>" , "<STR_LIT>" ) <EOL> domain_scope = None if request . couch_user . is_superuser else domain <EOL> try : <EOL> incoming ( phone_number , message , "<STR_LIT>" , domain_scope = domain_scope ) <EOL> except DomainScopeValidationError : <EOL> messages . error ( <EOL> request , <EOL> _ ( "<STR_LIT>" "<STR_LIT>" "<STR_LIT>" ) <EOL> ) <EOL> except Exception : <EOL> notify_exception ( request ) <EOL> messages . error ( <EOL> request , <EOL> _ ( "<STR_LIT>" "<STR_LIT>" "<STR_LIT>" ) <EOL> ) <EOL> context = get_sms_autocomplete_context ( request , domain ) <EOL> context [ '<STR_LIT>' ] = domain <EOL> context [ '<STR_LIT>' ] = True <EOL> context [ '<STR_LIT>' ] = phone_number <EOL> return render ( request , "<STR_LIT>" , context ) <EOL> @ csrf_exempt <EOL> @ login_or_digest_ex ( allow_cc_users = True ) <EOL> @ requires_privilege_plaintext_response ( privileges . OUTBOUND_SMS ) <EOL> def api_send_sms ( request , domain ) : <EOL> """<STR_LIT>""" <EOL> if request . method == "<STR_LIT:POST>" : <EOL> phone_number = request . POST . get ( "<STR_LIT>" , None ) <EOL> contact_id = request . POST . get ( "<STR_LIT>" , None ) <EOL> vn_id = request . POST . get ( "<STR_LIT>" , None ) <EOL> text = request . POST . get ( "<STR_LIT:text>" , None ) <EOL> backend_id = request . POST . get ( "<STR_LIT>" , None ) <EOL> chat = request . POST . get ( "<STR_LIT>" , None ) <EOL> contact = None <EOL> if ( phone_number is None and contact_id is None and not vn_id ) or ( text is None ) : <EOL> return HttpResponseBadRequest ( "<STR_LIT>" ) <EOL> vn = None <EOL> if vn_id : <EOL> try : <EOL> vn = VerifiedNumber . get ( vn_id ) <EOL> except ResourceNotFound : <EOL> return HttpResponseBadRequest ( "<STR_LIT>" ) <EOL> if vn . domain != domain : <EOL> return HttpResponseBadRequest ( "<STR_LIT>" ) <EOL> phone_number = vn . phone_number <EOL> contact = vn . owner <EOL> elif contact_id is not None : <EOL> try : <EOL> contact = get_contact ( contact_id ) <EOL> assert contact is not None <EOL> assert contact . domain == domain <EOL> except Exception : <EOL> return HttpResponseBadRequest ( "<STR_LIT>" ) <EOL> try : <EOL> vn = contact . get_verified_number ( ) <EOL> assert vn is not None <EOL> phone_number = vn . phone_number <EOL> except Exception : <EOL> return HttpResponseBadRequest ( "<STR_LIT>" ) <EOL> try : <EOL> chat_workflow = string_to_boolean ( chat ) <EOL> except Exception : <EOL> chat_workflow = False <EOL> if chat_workflow : <EOL> chat_user_id = request . couch_user . _id <EOL> else : <EOL> chat_user_id = None <EOL> logged_event = MessagingEvent . create_event_for_adhoc_sms ( <EOL> domain , recipient = contact , <EOL> content_type = ( MessagingEvent . CONTENT_CHAT_SMS if chat_workflow <EOL> else MessagingEvent . CONTENT_API_SMS ) ) <EOL> args = [ contact . doc_type , contact . get_id ] if contact else [ ] <EOL> logged_subevent = logged_event . create_subevent_for_single_sms ( * args ) <EOL> metadata = MessageMetadata ( <EOL> chat_user_id = chat_user_id , <EOL> messaging_subevent_id = logged_subevent . pk , <EOL> ) <EOL> if backend_id is not None : <EOL> success = send_sms_with_backend_name ( domain , phone_number , text , backend_id , metadata ) <EOL> elif vn is not None : <EOL> success = send_sms_to_verified_number ( vn , text , metadata ) <EOL> else : <EOL> success = send_sms ( domain , None , phone_number , text , metadata ) <EOL> if success : <EOL> logged_subevent . completed ( ) <EOL> logged_event . completed ( ) <EOL> return HttpResponse ( "<STR_LIT:OK>" ) <EOL> else : <EOL> logged_subevent . error ( MessagingEvent . ERROR_INTERNAL_SERVER_ERROR ) <EOL> return HttpResponse ( "<STR_LIT>" ) <EOL> else : <EOL> return HttpResponseBadRequest ( "<STR_LIT>" ) <EOL> @ login_and_domain_required <EOL> @ require_superuser <EOL> def list_forwarding_rules ( request , domain ) : <EOL> forwarding_rules = get_forwarding_rules_for_domain ( domain ) <EOL> context = { <EOL> "<STR_LIT>" : domain , <EOL> "<STR_LIT>" : forwarding_rules , <EOL> } <EOL> return render ( request , "<STR_LIT>" , context ) <EOL> @ login_and_domain_required <EOL> @ require_superuser <EOL> def add_forwarding_rule ( request , domain , forwarding_rule_id = None ) : <EOL> forwarding_rule = None <EOL> if forwarding_rule_id is not None : <EOL> forwarding_rule = ForwardingRule . get ( forwarding_rule_id ) <EOL> if forwarding_rule . domain != domain : <EOL> raise Http404 <EOL> if request . method == "<STR_LIT:POST>" : <EOL> form = ForwardingRuleForm ( request . POST ) <EOL> if form . is_valid ( ) : <EOL> if forwarding_rule is None : <EOL> forwarding_rule = ForwardingRule ( domain = domain ) <EOL> forwarding_rule . forward_type = form . cleaned_data . get ( "<STR_LIT>" ) <EOL> forwarding_rule . keyword = form . cleaned_data . get ( "<STR_LIT>" ) <EOL> forwarding_rule . backend_id = form . cleaned_data . get ( "<STR_LIT>" ) <EOL> forwarding_rule . save ( ) <EOL> return HttpResponseRedirect ( reverse ( '<STR_LIT>' , args = [ domain ] ) ) <EOL> else : <EOL> initial = { } <EOL> if forwarding_rule is not None : <EOL> initial [ "<STR_LIT>" ] = forwarding_rule . forward_type <EOL> initial [ "<STR_LIT>" ] = forwarding_rule . keyword <EOL> initial [ "<STR_LIT>" ] = forwarding_rule . backend_id <EOL> form = ForwardingRuleForm ( initial = initial ) <EOL> context = { <EOL> "<STR_LIT>" : domain , <EOL> "<STR_LIT>" : form , <EOL> "<STR_LIT>" : forwarding_rule_id , <EOL> } <EOL> return render ( request , "<STR_LIT>" , context ) <EOL> @ login_and_domain_required <EOL> @ require_superuser <EOL> def delete_forwarding_rule ( request , domain , forwarding_rule_id ) : <EOL> forwarding_rule = ForwardingRule . get ( forwarding_rule_id ) <EOL> if forwarding_rule . domain != domain or forwarding_rule . doc_type != "<STR_LIT>" : <EOL> raise Http404 <EOL> forwarding_rule . retire ( ) <EOL> return HttpResponseRedirect ( reverse ( "<STR_LIT>" , args = [ domain ] ) ) <EOL> class GlobalBackendMap ( BaseAdminSectionView ) : <EOL> urlname = '<STR_LIT>' <EOL> template_name = '<STR_LIT>' <EOL> page_title = ugettext_lazy ( "<STR_LIT>" ) <EOL> @ property <EOL> def page_url ( self ) : <EOL> return reverse ( self . urlname ) <EOL> @ property <EOL> @ memoized <EOL> def backends ( self ) : <EOL> return SQLMobileBackend . get_global_backends ( SQLMobileBackend . SMS ) <EOL> @ property <EOL> @ memoized <EOL> def backend_map_form ( self ) : <EOL> if self . request . method == '<STR_LIT:POST>' : <EOL> return BackendMapForm ( self . request . POST , backends = self . backends ) <EOL> backend_map = SQLMobileBackendMapping . get_prefix_to_backend_map ( SQLMobileBackend . SMS ) <EOL> initial = { <EOL> '<STR_LIT>' : backend_map . catchall_backend_id , <EOL> '<STR_LIT>' : json . dumps ( [ <EOL> { '<STR_LIT>' : prefix , '<STR_LIT>' : backend_id } <EOL> for prefix , backend_id in backend_map . backend_map_tuples <EOL> ] ) , <EOL> } <EOL> return BackendMapForm ( initial = initial , backends = self . backends ) <EOL> @ use_bootstrap3 <EOL> @ method_decorator ( require_superuser ) <EOL> def dispatch ( self , request , * args , ** kwargs ) : <EOL> return super ( GlobalBackendMap , self ) . dispatch ( request , * args , ** kwargs ) <EOL> @ property <EOL> def page_context ( self ) : <EOL> return { <EOL> '<STR_LIT>' : self . backend_map_form , <EOL> '<STR_LIT>' : self . backends , <EOL> } <EOL> def post ( self , request , * args , ** kwargs ) : <EOL> form = self . backend_map_form <EOL> if form . is_valid ( ) : <EOL> new_backend_map = form . cleaned_data . get ( '<STR_LIT>' ) <EOL> new_catchall_backend_id = form . cleaned_data . get ( '<STR_LIT>' ) <EOL> with transaction . atomic ( ) : <EOL> SQLMobileBackendMapping . get_prefix_to_backend_map . clear ( <EOL> SQLMobileBackendMapping , SQLMobileBackend . SMS <EOL> ) <EOL> SQLMobileBackendMapping . objects . filter ( <EOL> is_global = True , <EOL> backend_type = SQLMobileBackend . SMS , <EOL> ) . delete ( ) <EOL> for prefix , backend_id in new_backend_map . items ( ) : <EOL> SQLMobileBackendMapping . objects . create ( <EOL> is_global = True , <EOL> backend_type = SQLMobileBackend . SMS , <EOL> prefix = prefix , <EOL> backend_id = backend_id <EOL> ) <EOL> if new_catchall_backend_id : <EOL> SQLMobileBackendMapping . objects . create ( <EOL> is_global = True , <EOL> backend_type = SQLMobileBackend . SMS , <EOL> prefix = '<STR_LIT:*>' , <EOL> backend_id = new_catchall_backend_id <EOL> ) <EOL> messages . success ( request , _ ( "<STR_LIT>" ) ) <EOL> return HttpResponseRedirect ( reverse ( self . urlname ) ) <EOL> return self . get ( request , * args , ** kwargs ) <EOL> class ChatOverSMSView ( BaseMessagingSectionView ) : <EOL> urlname = '<STR_LIT>' <EOL> template_name = '<STR_LIT>' <EOL> page_title = _ ( "<STR_LIT>" ) <EOL> @ method_decorator ( require_permission ( Permissions . edit_data ) ) <EOL> @ use_bootstrap3 <EOL> @ use_datatables <EOL> def dispatch ( self , * args , ** kwargs ) : <EOL> return super ( ChatOverSMSView , self ) . dispatch ( * args , ** kwargs ) <EOL> def get_case_contact_info ( domain_obj , case_ids ) : <EOL> data = { } <EOL> for doc in iter_docs ( CommCareCase . get_db ( ) , case_ids ) : <EOL> if domain_obj . custom_case_username : <EOL> name = doc . get ( domain_obj . custom_case_username ) <EOL> else : <EOL> name = doc . get ( '<STR_LIT:name>' ) <EOL> data [ doc [ '<STR_LIT>' ] ] = [ name or _ ( '<STR_LIT>' ) ] <EOL> return data <EOL> def get_mobile_worker_contact_info ( domain_obj , user_ids ) : <EOL> data = { } <EOL> for doc in iter_docs ( CommCareUser . get_db ( ) , user_ids ) : <EOL> user = CommCareUser . wrap ( doc ) <EOL> data [ user . get_id ] = [ user . raw_username ] <EOL> return data <EOL> def get_contact_info ( domain ) : <EOL> cache_key = '<STR_LIT>' % domain <EOL> cache_expiration = <NUM_LIT:30> * <NUM_LIT> <EOL> try : <EOL> client = cache_core . get_redis_client ( ) <EOL> cached_data = client . get ( cache_key ) <EOL> if cached_data : <EOL> return json . loads ( cached_data ) <EOL> except : <EOL> pass <EOL> verified_number_ids = VerifiedNumber . by_domain ( domain , ids_only = True ) <EOL> domain_obj = Domain . get_by_name ( domain , strict = True ) <EOL> case_ids = [ ] <EOL> mobile_worker_ids = [ ] <EOL> data = [ ] <EOL> for doc in iter_docs ( VerifiedNumber . get_db ( ) , verified_number_ids ) : <EOL> owner_id = doc [ '<STR_LIT>' ] <EOL> if doc [ '<STR_LIT>' ] == '<STR_LIT>' : <EOL> case_ids . append ( owner_id ) <EOL> data . append ( [ <EOL> None , <EOL> '<STR_LIT>' , <EOL> doc [ '<STR_LIT>' ] , <EOL> owner_id , <EOL> doc [ '<STR_LIT>' ] , <EOL> ] ) <EOL> elif doc [ '<STR_LIT>' ] == '<STR_LIT>' : <EOL> mobile_worker_ids . append ( owner_id ) <EOL> data . append ( [ <EOL> None , <EOL> '<STR_LIT>' , <EOL> doc [ '<STR_LIT>' ] , <EOL> owner_id , <EOL> doc [ '<STR_LIT>' ] , <EOL> ] ) <EOL> contact_data = get_case_contact_info ( domain_obj , case_ids ) <EOL> contact_data . update ( get_mobile_worker_contact_info ( domain_obj , mobile_worker_ids ) ) <EOL> for row in data : <EOL> contact_info = contact_data . get ( row [ <NUM_LIT:3> ] ) <EOL> row [ <NUM_LIT:0> ] = contact_info [ <NUM_LIT:0> ] if contact_info else _ ( '<STR_LIT>' ) <EOL> try : <EOL> client . set ( cache_key , json . dumps ( data ) ) <EOL> client . expire ( cache_key , cache_expiration ) <EOL> except : <EOL> pass <EOL> return data <EOL> def format_contact_data ( domain , data ) : <EOL> for row in data : <EOL> contact_id = row [ <NUM_LIT:3> ] <EOL> vn_id = row [ <NUM_LIT:4> ] <EOL> if row [ <NUM_LIT:1> ] == '<STR_LIT>' : <EOL> row [ <NUM_LIT:1> ] = _ ( '<STR_LIT>' ) <EOL> row [ <NUM_LIT:4> ] = reverse ( '<STR_LIT>' , args = [ domain , contact_id ] ) <EOL> elif row [ <NUM_LIT:1> ] == '<STR_LIT>' : <EOL> row [ <NUM_LIT:1> ] = _ ( '<STR_LIT>' ) <EOL> row [ <NUM_LIT:4> ] = reverse ( EditCommCareUserView . urlname , args = [ domain , contact_id ] ) <EOL> else : <EOL> row [ <NUM_LIT:4> ] = '<STR_LIT:#>' <EOL> row . append ( reverse ( '<STR_LIT>' , args = [ domain , contact_id , vn_id ] ) ) <EOL> @ require_permission ( Permissions . edit_data ) <EOL> @ requires_privilege_with_fallback ( privileges . OUTBOUND_SMS ) <EOL> def chat_contact_list ( request , domain ) : <EOL> sEcho = request . GET . get ( '<STR_LIT>' ) <EOL> iDisplayStart = int ( request . GET . get ( '<STR_LIT>' ) ) <EOL> iDisplayLength = int ( request . GET . get ( '<STR_LIT>' ) ) <EOL> sSearch = request . GET . get ( '<STR_LIT>' , '<STR_LIT>' ) . strip ( ) <EOL> data = get_contact_info ( domain ) <EOL> total_records = len ( data ) <EOL> if sSearch : <EOL> regex = re . compile ( '<STR_LIT>' % sSearch ) <EOL> data = filter ( lambda row : regex . match ( row [ <NUM_LIT:0> ] ) or regex . match ( row [ <NUM_LIT:2> ] ) , data ) <EOL> filtered_records = len ( data ) <EOL> data . sort ( key = lambda row : row [ <NUM_LIT:0> ] ) <EOL> data = data [ iDisplayStart : iDisplayStart + iDisplayLength ] <EOL> format_contact_data ( domain , data ) <EOL> result = { <EOL> '<STR_LIT>' : sEcho , <EOL> '<STR_LIT>' : data , <EOL> '<STR_LIT>' : total_records , <EOL> '<STR_LIT>' : filtered_records , <EOL> } <EOL> return HttpResponse ( json . dumps ( result ) ) <EOL> @ require_permission ( Permissions . edit_data ) <EOL> @ requires_privilege_with_fallback ( privileges . OUTBOUND_SMS ) <EOL> def chat ( request , domain , contact_id , vn_id = None ) : <EOL> domain_obj = Domain . get_by_name ( domain , strict = True ) <EOL> timezone = get_timezone_for_user ( None , domain ) <EOL> local_date = datetime . now ( timezone ) . date ( ) <EOL> floored_utc_timestamp = UserTime ( <EOL> datetime . combine ( local_date , time ( <NUM_LIT:0> , <NUM_LIT:0> ) ) , <EOL> timezone <EOL> ) . server_time ( ) . done ( ) <EOL> def _fmt ( d ) : <EOL> return json_format_datetime ( floored_utc_timestamp - timedelta ( days = d ) ) <EOL> history_choices = [ ( _ ( x ) , _fmt ( y ) ) for ( x , y ) in SMS_CHAT_HISTORY_CHOICES ] <EOL> history_choices . append ( <EOL> ( _ ( "<STR_LIT>" ) , json_format_datetime ( datetime ( <NUM_LIT> , <NUM_LIT:1> , <NUM_LIT:1> ) ) ) <EOL> ) <EOL> context = { <EOL> "<STR_LIT>" : domain , <EOL> "<STR_LIT>" : contact_id , <EOL> "<STR_LIT>" : get_contact ( contact_id ) , <EOL> "<STR_LIT>" : domain_obj . chat_message_count_threshold is not None , <EOL> "<STR_LIT>" : domain_obj . chat_message_count_threshold or <NUM_LIT:0> , <EOL> "<STR_LIT>" : domain_obj . custom_case_username , <EOL> "<STR_LIT>" : history_choices , <EOL> "<STR_LIT>" : vn_id , <EOL> } <EOL> template = settings . CUSTOM_CHAT_TEMPLATES . get ( domain_obj . custom_chat_template ) or "<STR_LIT>" <EOL> return render ( request , template , context ) <EOL> class ChatMessageHistory ( View , DomainViewMixin ) : <EOL> urlname = '<STR_LIT>' <EOL> @ method_decorator ( require_permission ( Permissions . edit_data ) ) <EOL> @ method_decorator ( requires_privilege_with_fallback ( privileges . OUTBOUND_SMS ) ) <EOL> def dispatch ( self , request , * args , ** kwargs ) : <EOL> return super ( ChatMessageHistory , self ) . dispatch ( request , * args , ** kwargs ) <EOL> @ property <EOL> @ memoized <EOL> def contact_id ( self ) : <EOL> return self . request . GET . get ( '<STR_LIT>' ) <EOL> @ property <EOL> @ memoized <EOL> def contact ( self ) : <EOL> if not self . contact_id : <EOL> return None <EOL> contact = get_contact ( self . contact_id ) <EOL> if not contact or contact . domain != self . domain : <EOL> return None <EOL> return contact <EOL> @ property <EOL> @ memoized <EOL> def contact_name ( self ) : <EOL> if self . contact . doc_type == '<STR_LIT>' : <EOL> if self . domain_object . custom_case_username : <EOL> return self . contact . get_case_property ( self . domain_object . custom_case_username ) <EOL> else : <EOL> return self . contact . name <EOL> else : <EOL> return self . contact . first_name or self . contact . raw_username <EOL> @ quickcache ( [ '<STR_LIT>' ] , timeout = <NUM_LIT> * <NUM_LIT> , memoize_timeout = <NUM_LIT:5> * <NUM_LIT> ) <EOL> def get_chat_user_name ( self , user_id ) : <EOL> if not user_id : <EOL> return _ ( "<STR_LIT>" ) <EOL> try : <EOL> user = CouchUser . get_by_user_id ( user_id ) <EOL> return user . first_name or user . raw_username <EOL> except : <EOL> return _ ( "<STR_LIT>" ) <EOL> @ property <EOL> @ memoized <EOL> def start_date_str ( self ) : <EOL> return self . request . GET . get ( '<STR_LIT>' ) <EOL> @ property <EOL> @ memoized <EOL> def start_date ( self ) : <EOL> if not self . start_date_str : <EOL> return None <EOL> try : <EOL> return iso_string_to_datetime ( self . start_date_str ) <EOL> except ( TypeError , ValueError ) : <EOL> return None <EOL> def get_raw_data ( self ) : <EOL> result = SMS . objects . filter ( <EOL> domain = self . domain , <EOL> couch_recipient_doc_type = self . contact . doc_type , <EOL> couch_recipient = self . contact_id <EOL> ) . exclude ( <EOL> direction = OUTGOING , <EOL> processed = False <EOL> ) <EOL> if self . start_date : <EOL> result = result . filter ( date__gt = self . start_date ) <EOL> result = self . filter_survey_data ( result ) <EOL> return result . order_by ( '<STR_LIT:date>' ) <EOL> def filter_survey_data ( self , queryset ) : <EOL> if not self . domain_object . filter_surveys_from_chat : <EOL> return queryset <EOL> if self . domain_object . show_invalid_survey_responses_in_chat : <EOL> return queryset . exclude ( <EOL> Q ( xforms_session_couch_id__isnull = False ) & <EOL> ~ Q ( direction = INCOMING , invalid_survey_response = True ) <EOL> ) <EOL> else : <EOL> return queryset . exclude ( <EOL> xforms_session_couch_id__isnull = False <EOL> ) <EOL> def get_response_data ( self , requesting_user_id ) : <EOL> timezone = get_timezone_for_user ( None , self . domain ) <EOL> result = [ ] <EOL> last_sms = None <EOL> for sms in self . get_raw_data ( ) : <EOL> last_sms = sms <EOL> if sms . direction == INCOMING : <EOL> sender = self . contact_name <EOL> else : <EOL> sender = self . get_chat_user_name ( sms . chat_user_id ) <EOL> result . append ( { <EOL> '<STR_LIT>' : sender , <EOL> '<STR_LIT:text>' : sms . text , <EOL> '<STR_LIT>' : ( <EOL> ServerTime ( sms . date ) . user_time ( timezone ) <EOL> . ui_string ( "<STR_LIT>" ) . lower ( ) <EOL> ) , <EOL> '<STR_LIT>' : json_format_datetime ( sms . date ) , <EOL> '<STR_LIT>' : ( sms . chat_user_id == requesting_user_id ) , <EOL> } ) <EOL> return result , last_sms <EOL> def update_last_read_message ( self , requesting_user_id , sms ) : <EOL> domain = self . domain <EOL> contact_id = self . contact_id <EOL> key = '<STR_LIT>' % ( domain , requesting_user_id , contact_id ) <EOL> with CriticalSection ( [ key ] ) : <EOL> try : <EOL> entry = SQLLastReadMessage . objects . get ( <EOL> domain = domain , <EOL> read_by = requesting_user_id , <EOL> contact_id = contact_id <EOL> ) <EOL> except SQLLastReadMessage . DoesNotExist : <EOL> entry = SQLLastReadMessage ( <EOL> domain = domain , <EOL> read_by = requesting_user_id , <EOL> contact_id = contact_id <EOL> ) <EOL> if not entry . message_timestamp or entry . message_timestamp < sms . date : <EOL> entry . message_id = sms . couch_id <EOL> entry . message_timestamp = sms . date <EOL> entry . save ( ) <EOL> def get ( self , request , * args , ** kwargs ) : <EOL> if not self . contact : <EOL> return HttpResponse ( '<STR_LIT>' ) <EOL> data , last_sms = self . get_response_data ( request . couch_user . get_id ) <EOL> if last_sms : <EOL> try : <EOL> self . update_last_read_message ( request . couch_user . get_id , last_sms ) <EOL> except : <EOL> notify_exception ( request , "<STR_LIT>" % last_sms . pk ) <EOL> return HttpResponse ( json . dumps ( data ) ) <EOL> class ChatLastReadMessage ( View , DomainViewMixin ) : <EOL> urlname = '<STR_LIT>' <EOL> @ method_decorator ( require_permission ( Permissions . edit_data ) ) <EOL> @ method_decorator ( requires_privilege_with_fallback ( privileges . OUTBOUND_SMS ) ) <EOL> def dispatch ( self , request , * args , ** kwargs ) : <EOL> return super ( ChatLastReadMessage , self ) . dispatch ( request , * args , ** kwargs ) <EOL> @ property <EOL> @ memoized <EOL> def contact_id ( self ) : <EOL> return self . request . GET . get ( '<STR_LIT>' ) <EOL> def get ( self , request , * args , ** kwargs ) : <EOL> lrm_timestamp = None <EOL> if self . contact_id : <EOL> if self . domain_object . count_messages_as_read_by_anyone : <EOL> lrm = SQLLastReadMessage . by_anyone ( self . domain , self . contact_id ) <EOL> else : <EOL> lrm = SQLLastReadMessage . by_user ( self . domain , request . couch_user . get_id , self . contact_id ) <EOL> if lrm : <EOL> lrm_timestamp = json_format_datetime ( lrm . message_timestamp ) <EOL> return HttpResponse ( json . dumps ( { <EOL> '<STR_LIT>' : lrm_timestamp , <EOL> } ) ) <EOL> class DomainSmsGatewayListView ( CRUDPaginatedViewMixin , BaseMessagingSectionView ) : <EOL> template_name = "<STR_LIT>" <EOL> urlname = '<STR_LIT>' <EOL> page_title = ugettext_noop ( "<STR_LIT>" ) <EOL> strict_domain_fetching = True <EOL> @ use_bootstrap3 <EOL> @ method_decorator ( domain_admin_required ) <EOL> def dispatch ( self , request , * args , ** kwargs ) : <EOL> return super ( DomainSmsGatewayListView , self ) . dispatch ( request , * args , ** kwargs ) <EOL> @ property <EOL> def page_url ( self ) : <EOL> return reverse ( self . urlname , args = [ self . domain ] ) <EOL> @ property <EOL> def parameters ( self ) : <EOL> return self . request . POST if self . request . method == '<STR_LIT:POST>' else self . request . GET <EOL> @ property <EOL> @ memoized <EOL> def total ( self ) : <EOL> return SQLMobileBackend . get_domain_backends ( SQLMobileBackend . SMS , self . domain , count_only = True ) <EOL> @ property <EOL> def column_names ( self ) : <EOL> return [ <EOL> _ ( "<STR_LIT>" ) , <EOL> _ ( "<STR_LIT>" ) , <EOL> _ ( "<STR_LIT>" ) , <EOL> _ ( "<STR_LIT>" ) , <EOL> _ ( "<STR_LIT>" ) , <EOL> ] <EOL> @ property <EOL> def page_context ( self ) : <EOL> context = self . pagination_context <EOL> context . update ( { <EOL> '<STR_LIT>' : InitiateAddSMSBackendForm ( is_superuser = self . request . couch_user . is_superuser ) , <EOL> } ) <EOL> return context <EOL> @ property <EOL> def paginated_list ( self ) : <EOL> backends = SQLMobileBackend . get_domain_backends ( <EOL> SQLMobileBackend . SMS , <EOL> self . domain , <EOL> offset = self . skip , <EOL> limit = self . limit <EOL> ) <EOL> default_backend = SQLMobileBackend . get_domain_default_backend ( <EOL> SQLMobileBackend . SMS , <EOL> self . domain <EOL> ) <EOL> if len ( backends ) > <NUM_LIT:0> and not default_backend : <EOL> yield { <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT:id>' : '<STR_LIT>' , <EOL> '<STR_LIT:name>' : "<STR_LIT>" , <EOL> '<STR_LIT:status>' : '<STR_LIT>' , <EOL> } , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> } <EOL> elif default_backend : <EOL> yield { <EOL> '<STR_LIT>' : self . _fmt_backend_data ( default_backend ) , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> } <EOL> default_backend_id = default_backend . pk if default_backend else None <EOL> for backend in backends : <EOL> if backend . pk != default_backend_id : <EOL> yield { <EOL> '<STR_LIT>' : self . _fmt_backend_data ( backend ) , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> } <EOL> def _fmt_backend_data ( self , backend ) : <EOL> is_editable = not backend . is_global and backend . domain == self . domain <EOL> if len ( backend . supported_countries ) > <NUM_LIT:0> : <EOL> if backend . supported_countries [ <NUM_LIT:0> ] == '<STR_LIT:*>' : <EOL> supported_country_names = _ ( '<STR_LIT>' ) % '<STR_LIT:*>' <EOL> else : <EOL> supported_country_names = '<STR_LIT:U+002CU+0020>' . join ( <EOL> [ _ ( country_name_from_code ( int ( c ) ) ) for c in backend . supported_countries ] ) <EOL> else : <EOL> supported_country_names = '<STR_LIT>' <EOL> return { <EOL> '<STR_LIT:id>' : backend . pk , <EOL> '<STR_LIT:name>' : backend . name , <EOL> '<STR_LIT:description>' : backend . description , <EOL> '<STR_LIT>' : supported_country_names , <EOL> '<STR_LIT>' : reverse ( <EOL> EditDomainGatewayView . urlname , <EOL> args = [ self . domain , backend . hq_api_id , backend . pk ] <EOL> ) if is_editable else "<STR_LIT>" , <EOL> '<STR_LIT>' : is_editable , <EOL> '<STR_LIT>' : backend . is_global , <EOL> '<STR_LIT>' : not backend . is_global and backend . domain != self . domain , <EOL> '<STR_LIT>' : '<STR_LIT>' % backend . pk , <EOL> } <EOL> def _get_backend_from_item_id ( self , item_id ) : <EOL> try : <EOL> item_id = int ( item_id ) <EOL> backend = SQLMobileBackend . load ( item_id ) <EOL> return item_id , backend <EOL> except ( BadSMSConfigException , SQLMobileBackend . DoesNotExist , TypeError , ValueError ) : <EOL> raise Http404 ( ) <EOL> def get_deleted_item_data ( self , item_id ) : <EOL> item_id , backend = self . _get_backend_from_item_id ( item_id ) <EOL> if backend . is_global or backend . domain != self . domain : <EOL> raise Http404 ( ) <EOL> backend . soft_delete ( ) <EOL> return { <EOL> '<STR_LIT>' : self . _fmt_backend_data ( backend ) , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> } <EOL> def refresh_item ( self , item_id ) : <EOL> item_id , backend = self . _get_backend_from_item_id ( item_id ) <EOL> if not backend . domain_is_authorized ( self . domain ) : <EOL> raise Http404 ( ) <EOL> domain_default_backend_id = SQLMobileBackend . get_domain_default_backend ( <EOL> SQLMobileBackend . SMS , <EOL> self . domain , <EOL> id_only = True <EOL> ) <EOL> if domain_default_backend_id == item_id : <EOL> SQLMobileBackendMapping . unset_default_domain_backend ( self . domain ) <EOL> else : <EOL> SQLMobileBackendMapping . set_default_domain_backend ( self . domain , backend ) <EOL> @ property <EOL> def allowed_actions ( self ) : <EOL> actions = super ( DomainSmsGatewayListView , self ) . allowed_actions <EOL> return actions + [ '<STR_LIT>' ] <EOL> def post ( self , request , * args , ** kwargs ) : <EOL> if self . action == '<STR_LIT>' : <EOL> hq_api_id = request . POST [ '<STR_LIT>' ] <EOL> if ( <EOL> toggles . TELERIVET_SETUP_WALKTHROUGH . enabled ( self . domain ) and <EOL> hq_api_id == SQLTelerivetBackend . get_api_id ( ) <EOL> ) : <EOL> from corehq . messaging . smsbackends . telerivet . views import TelerivetSetupView <EOL> return HttpResponseRedirect ( reverse ( TelerivetSetupView . urlname , args = [ self . domain ] ) ) <EOL> return HttpResponseRedirect ( reverse ( AddDomainGatewayView . urlname , args = [ self . domain , hq_api_id ] ) ) <EOL> return self . paginate_crud_response <EOL> class AddGatewayViewMixin ( object ) : <EOL> """<STR_LIT>""" <EOL> @ property <EOL> def is_superuser ( self ) : <EOL> return self . request . couch_user . is_superuser <EOL> @ property <EOL> @ memoized <EOL> def hq_api_id ( self ) : <EOL> return self . kwargs . get ( '<STR_LIT>' ) <EOL> @ property <EOL> @ memoized <EOL> def backend_class ( self ) : <EOL> if not self . is_superuser and self . hq_api_id != SQLTelerivetBackend . get_api_id ( ) : <EOL> raise Http404 ( ) <EOL> backend_classes = get_sms_backend_classes ( ) <EOL> try : <EOL> return backend_classes [ self . hq_api_id ] <EOL> except KeyError : <EOL> raise Http404 ( ) <EOL> @ property <EOL> def use_load_balancing ( self ) : <EOL> return issubclass ( self . backend_class , PhoneLoadBalancingMixin ) <EOL> @ property <EOL> def page_name ( self ) : <EOL> return _ ( "<STR_LIT>" ) % self . backend_class . get_generic_name ( ) <EOL> @ property <EOL> def button_text ( self ) : <EOL> return _ ( "<STR_LIT>" ) % self . backend_class . get_generic_name ( ) <EOL> @ property <EOL> def page_context ( self ) : <EOL> return { <EOL> '<STR_LIT>' : self . backend_form , <EOL> '<STR_LIT>' : self . button_text , <EOL> '<STR_LIT>' : self . use_load_balancing , <EOL> } <EOL> def post ( self , request , * args , ** kwargs ) : <EOL> if self . backend_form . is_valid ( ) : <EOL> self . backend . name = self . backend_form . cleaned_data . get ( '<STR_LIT:name>' ) <EOL> self . backend . description = self . backend_form . cleaned_data . get ( '<STR_LIT:description>' ) <EOL> self . backend . reply_to_phone_number = self . backend_form . cleaned_data . get ( '<STR_LIT>' ) <EOL> extra_fields = { } <EOL> for key , value in self . backend_form . cleaned_data . items ( ) : <EOL> if key in self . backend . get_available_extra_fields ( ) : <EOL> extra_fields [ key ] = value <EOL> self . backend . set_extra_fields ( ** extra_fields ) <EOL> if self . use_load_balancing : <EOL> self . backend . load_balancing_numbers = self . backend_form . cleaned_data [ '<STR_LIT>' ] <EOL> self . backend . save ( ) <EOL> if not self . backend . is_global : <EOL> self . backend . set_shared_domains ( self . backend_form . cleaned_data . get ( '<STR_LIT>' ) ) <EOL> return self . redirect_to_gateway_list ( ) <EOL> return self . get ( request , * args , ** kwargs ) <EOL> @ property <EOL> def backend ( self ) : <EOL> raise NotImplementedError ( ) <EOL> @ property <EOL> def page_url ( self ) : <EOL> raise NotImplementedError ( ) <EOL> @ property <EOL> def backend_form ( self ) : <EOL> raise NotImplementedError ( ) <EOL> @ property <EOL> def parent_pages ( self ) : <EOL> raise NotImplementedError ( ) <EOL> def redirect_to_gateway_list ( self ) : <EOL> raise NotImplementedError ( ) <EOL> class AddDomainGatewayView ( AddGatewayViewMixin , BaseMessagingSectionView ) : <EOL> urlname = '<STR_LIT>' <EOL> template_name = '<STR_LIT>' <EOL> page_title = ugettext_lazy ( "<STR_LIT>" ) <EOL> @ property <EOL> @ memoized <EOL> def backend ( self ) : <EOL> return self . backend_class ( <EOL> domain = self . domain , <EOL> is_global = False , <EOL> backend_type = SQLMobileBackend . SMS , <EOL> hq_api_id = self . backend_class . get_api_id ( ) <EOL> ) <EOL> @ property <EOL> def page_url ( self ) : <EOL> return reverse ( self . urlname , args = [ self . domain , self . hq_api_id ] ) <EOL> @ property <EOL> @ memoized <EOL> def backend_form ( self ) : <EOL> form_class = self . backend_class . get_form_class ( ) <EOL> if self . request . method == '<STR_LIT:POST>' : <EOL> return form_class ( <EOL> self . request . POST , <EOL> button_text = self . button_text , <EOL> domain = self . domain , <EOL> backend_id = None <EOL> ) <EOL> return form_class ( <EOL> button_text = self . button_text , <EOL> domain = self . domain , <EOL> backend_id = None <EOL> ) <EOL> @ property <EOL> def parent_pages ( self ) : <EOL> return [ { <EOL> '<STR_LIT:title>' : DomainSmsGatewayListView . page_title , <EOL> '<STR_LIT:url>' : reverse ( DomainSmsGatewayListView . urlname , args = [ self . domain ] ) , <EOL> } ] <EOL> def redirect_to_gateway_list ( self ) : <EOL> return HttpResponseRedirect ( reverse ( DomainSmsGatewayListView . urlname , args = [ self . domain ] ) ) <EOL> @ use_bootstrap3 <EOL> @ use_select2 <EOL> @ method_decorator ( domain_admin_required ) <EOL> @ method_decorator ( requires_privilege_with_fallback ( privileges . OUTBOUND_SMS ) ) <EOL> def dispatch ( self , request , * args , ** kwargs ) : <EOL> return super ( AddDomainGatewayView , self ) . dispatch ( request , * args , ** kwargs ) <EOL> class EditDomainGatewayView ( AddDomainGatewayView ) : <EOL> urlname = '<STR_LIT>' <EOL> page_title = ugettext_lazy ( "<STR_LIT>" ) <EOL> @ property <EOL> def backend_id ( self ) : <EOL> return self . kwargs [ '<STR_LIT>' ] <EOL> @ property <EOL> @ memoized <EOL> def backend ( self ) : <EOL> try : <EOL> backend = self . backend_class . objects . get ( pk = self . backend_id ) <EOL> except ResourceNotFound : <EOL> raise Http404 ( ) <EOL> if ( <EOL> backend . is_global or <EOL> backend . domain != self . domain or <EOL> backend . hq_api_id != self . backend_class . get_api_id ( ) or <EOL> backend . deleted <EOL> ) : <EOL> raise Http404 ( ) <EOL> return backend <EOL> @ property <EOL> @ memoized <EOL> def backend_form ( self ) : <EOL> form_class = self . backend_class . get_form_class ( ) <EOL> authorized_domains = self . backend . get_authorized_domain_list ( ) <EOL> initial = { <EOL> '<STR_LIT:name>' : self . backend . name , <EOL> '<STR_LIT:description>' : self . backend . description , <EOL> '<STR_LIT>' : len ( authorized_domains ) > <NUM_LIT:0> , <EOL> '<STR_LIT>' : '<STR_LIT:U+002C>' . join ( authorized_domains ) , <EOL> '<STR_LIT>' : self . backend . reply_to_phone_number , <EOL> } <EOL> initial . update ( self . backend . get_extra_fields ( ) ) <EOL> if self . use_load_balancing : <EOL> initial [ '<STR_LIT>' ] = json . dumps ( <EOL> [ { '<STR_LIT>' : p } for p in self . backend . load_balancing_numbers ] <EOL> ) <EOL> if self . request . method == '<STR_LIT:POST>' : <EOL> return form_class ( <EOL> self . request . POST , <EOL> initial = initial , <EOL> button_text = self . button_text , <EOL> domain = self . domain , <EOL> backend_id = self . backend . pk <EOL> ) <EOL> return form_class ( <EOL> initial = initial , <EOL> button_text = self . button_text , <EOL> domain = self . domain , <EOL> backend_id = self . backend . pk <EOL> ) <EOL> @ property <EOL> def page_name ( self ) : <EOL> return _ ( "<STR_LIT>" ) % self . backend_class . get_generic_name ( ) <EOL> @ property <EOL> def button_text ( self ) : <EOL> return _ ( "<STR_LIT>" ) % self . backend_class . get_generic_name ( ) <EOL> @ property <EOL> def page_url ( self ) : <EOL> return reverse ( self . urlname , kwargs = self . kwargs ) <EOL> class GlobalSmsGatewayListView ( CRUDPaginatedViewMixin , BaseAdminSectionView ) : <EOL> template_name = "<STR_LIT>" <EOL> urlname = '<STR_LIT>' <EOL> page_title = ugettext_noop ( "<STR_LIT>" ) <EOL> @ use_bootstrap3 <EOL> @ method_decorator ( require_superuser ) <EOL> def dispatch ( self , request , * args , ** kwargs ) : <EOL> return super ( GlobalSmsGatewayListView , self ) . dispatch ( request , * args , ** kwargs ) <EOL> @ property <EOL> def page_url ( self ) : <EOL> return reverse ( self . urlname ) <EOL> @ property <EOL> def parameters ( self ) : <EOL> return self . request . POST if self . request . method == '<STR_LIT:POST>' else self . request . GET <EOL> @ property <EOL> @ memoized <EOL> def total ( self ) : <EOL> return SQLMobileBackend . get_global_backends ( SQLMobileBackend . SMS , count_only = True ) <EOL> @ property <EOL> def column_names ( self ) : <EOL> return [ <EOL> _ ( "<STR_LIT>" ) , <EOL> _ ( "<STR_LIT>" ) , <EOL> _ ( "<STR_LIT>" ) , <EOL> _ ( "<STR_LIT>" ) , <EOL> ] <EOL> @ property <EOL> def page_context ( self ) : <EOL> context = self . pagination_context <EOL> context . update ( { <EOL> '<STR_LIT>' : InitiateAddSMSBackendForm ( is_superuser = self . request . couch_user . is_superuser ) , <EOL> } ) <EOL> return context <EOL> @ property <EOL> def paginated_list ( self ) : <EOL> backends = SQLMobileBackend . get_global_backends ( <EOL> SQLMobileBackend . SMS , <EOL> offset = self . skip , <EOL> limit = self . limit <EOL> ) <EOL> for backend in backends : <EOL> yield { <EOL> '<STR_LIT>' : self . _fmt_backend_data ( backend ) , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> } <EOL> def _fmt_backend_data ( self , backend ) : <EOL> if len ( backend . supported_countries ) > <NUM_LIT:0> : <EOL> if backend . supported_countries [ <NUM_LIT:0> ] == '<STR_LIT:*>' : <EOL> supported_country_names = _ ( '<STR_LIT>' ) % '<STR_LIT:*>' <EOL> else : <EOL> supported_country_names = '<STR_LIT:U+002CU+0020>' . join ( <EOL> [ _ ( country_name_from_code ( int ( c ) ) ) for c in backend . supported_countries ] ) <EOL> else : <EOL> supported_country_names = '<STR_LIT>' <EOL> return { <EOL> '<STR_LIT:id>' : backend . pk , <EOL> '<STR_LIT:name>' : backend . name , <EOL> '<STR_LIT:description>' : backend . description , <EOL> '<STR_LIT>' : supported_country_names , <EOL> '<STR_LIT>' : reverse ( <EOL> EditGlobalGatewayView . urlname , <EOL> args = [ backend . hq_api_id , backend . pk ] <EOL> ) , <EOL> '<STR_LIT>' : '<STR_LIT>' % backend . pk , <EOL> } <EOL> def _get_backend_from_item_id ( self , item_id ) : <EOL> try : <EOL> item_id = int ( item_id ) <EOL> backend = SQLMobileBackend . load ( item_id ) <EOL> return item_id , backend <EOL> except ( BadSMSConfigException , SQLMobileBackend . DoesNotExist , TypeError , ValueError ) : <EOL> raise Http404 ( ) <EOL> def get_deleted_item_data ( self , item_id ) : <EOL> item_id , backend = self . _get_backend_from_item_id ( item_id ) <EOL> if not backend . is_global : <EOL> raise Http404 ( ) <EOL> backend . soft_delete ( ) <EOL> return { <EOL> '<STR_LIT>' : self . _fmt_backend_data ( backend ) , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> } <EOL> @ property <EOL> def allowed_actions ( self ) : <EOL> actions = super ( GlobalSmsGatewayListView , self ) . allowed_actions <EOL> return actions + [ '<STR_LIT>' ] <EOL> def post ( self , request , * args , ** kwargs ) : <EOL> if self . action == '<STR_LIT>' : <EOL> hq_api_id = request . POST [ '<STR_LIT>' ] <EOL> return HttpResponseRedirect ( reverse ( AddGlobalGatewayView . urlname , args = [ hq_api_id ] ) ) <EOL> return self . paginate_crud_response <EOL> class AddGlobalGatewayView ( AddGatewayViewMixin , BaseAdminSectionView ) : <EOL> urlname = '<STR_LIT>' <EOL> template_name = '<STR_LIT>' <EOL> page_title = ugettext_lazy ( "<STR_LIT>" ) <EOL> @ property <EOL> @ memoized <EOL> def backend ( self ) : <EOL> return self . backend_class ( <EOL> is_global = True , <EOL> backend_type = SQLMobileBackend . SMS , <EOL> hq_api_id = self . backend_class . get_api_id ( ) <EOL> ) <EOL> @ property <EOL> def page_url ( self ) : <EOL> return reverse ( self . urlname , args = [ self . hq_api_id ] ) <EOL> @ property <EOL> @ memoized <EOL> def backend_form ( self ) : <EOL> form_class = self . backend_class . get_form_class ( ) <EOL> if self . request . method == '<STR_LIT:POST>' : <EOL> return form_class ( <EOL> self . request . POST , <EOL> button_text = self . button_text , <EOL> domain = None , <EOL> backend_id = None <EOL> ) <EOL> return form_class ( <EOL> button_text = self . button_text , <EOL> domain = None , <EOL> backend_id = None <EOL> ) <EOL> @ property <EOL> def parent_pages ( self ) : <EOL> return [ { <EOL> '<STR_LIT:title>' : GlobalSmsGatewayListView . page_title , <EOL> '<STR_LIT:url>' : reverse ( GlobalSmsGatewayListView . urlname ) , <EOL> } ] <EOL> def redirect_to_gateway_list ( self ) : <EOL> return HttpResponseRedirect ( reverse ( GlobalSmsGatewayListView . urlname ) ) <EOL> @ use_bootstrap3 <EOL> @ use_select2 <EOL> @ method_decorator ( require_superuser ) <EOL> def dispatch ( self , request , * args , ** kwargs ) : <EOL> return super ( AddGlobalGatewayView , self ) . dispatch ( request , * args , ** kwargs ) <EOL> class EditGlobalGatewayView ( AddGlobalGatewayView ) : <EOL> urlname = '<STR_LIT>' <EOL> page_title = ugettext_lazy ( "<STR_LIT>" ) <EOL> @ property <EOL> def backend_id ( self ) : <EOL> return self . kwargs [ '<STR_LIT>' ] <EOL> @ property <EOL> @ memoized <EOL> def backend ( self ) : <EOL> try : <EOL> backend = self . backend_class . objects . get ( pk = self . backend_id ) <EOL> except ResourceNotFound : <EOL> raise Http404 ( ) <EOL> if ( <EOL> not backend . is_global or <EOL> backend . deleted or <EOL> backend . hq_api_id != self . backend_class . get_api_id ( ) <EOL> ) : <EOL> raise Http404 ( ) <EOL> return backend <EOL> @ property <EOL> @ memoized <EOL> def backend_form ( self ) : <EOL> form_class = self . backend_class . get_form_class ( ) <EOL> initial = { <EOL> '<STR_LIT:name>' : self . backend . name , <EOL> '<STR_LIT:description>' : self . backend . description , <EOL> '<STR_LIT>' : self . backend . reply_to_phone_number , <EOL> } <EOL> initial . update ( self . backend . get_extra_fields ( ) ) <EOL> if self . use_load_balancing : <EOL> initial [ '<STR_LIT>' ] = json . dumps ( <EOL> [ { '<STR_LIT>' : p } for p in self . backend . load_balancing_numbers ] <EOL> ) <EOL> if self . request . method == '<STR_LIT:POST>' : <EOL> return form_class ( <EOL> self . request . POST , <EOL> initial = initial , <EOL> button_text = self . button_text , <EOL> domain = None , <EOL> backend_id = self . backend . pk <EOL> ) <EOL> return form_class ( <EOL> initial = initial , <EOL> button_text = self . button_text , <EOL> domain = None , <EOL> backend_id = self . backend . pk <EOL> ) <EOL> @ property <EOL> def page_name ( self ) : <EOL> return _ ( "<STR_LIT>" ) % self . backend_class . get_generic_name ( ) <EOL> @ property <EOL> def button_text ( self ) : <EOL> return _ ( "<STR_LIT>" ) % self . backend_class . get_generic_name ( ) <EOL> @ property <EOL> def page_url ( self ) : <EOL> return reverse ( self . urlname , kwargs = self . kwargs ) <EOL> class SubscribeSMSView ( BaseMessagingSectionView ) : <EOL> template_name = "<STR_LIT>" <EOL> urlname = '<STR_LIT>' <EOL> page_title = ugettext_noop ( "<STR_LIT>" ) <EOL> @ method_decorator ( requires_privilege_with_fallback ( privileges . OUTBOUND_SMS ) ) <EOL> @ use_bootstrap3 <EOL> def dispatch ( self , * args , ** kwargs ) : <EOL> return super ( SubscribeSMSView , self ) . dispatch ( * args , ** kwargs ) <EOL> @ property <EOL> def commtrack_settings ( self ) : <EOL> return Domain . get_by_name ( self . domain ) . commtrack_settings <EOL> @ property <EOL> @ memoized <EOL> def form ( self ) : <EOL> if self . request . method == '<STR_LIT:POST>' : <EOL> return SubscribeSMSForm ( self . request . POST ) <EOL> if self . commtrack_settings and self . commtrack_settings . alert_config : <EOL> alert_config = self . commtrack_settings . alert_config <EOL> else : <EOL> alert_config = AlertConfig ( ) <EOL> initial = { <EOL> '<STR_LIT>' : alert_config . stock_out_facilities , <EOL> '<STR_LIT>' : alert_config . stock_out_commodities , <EOL> '<STR_LIT>' : alert_config . stock_out_rates , <EOL> '<STR_LIT>' : alert_config . non_report , <EOL> } <EOL> return SubscribeSMSForm ( initial = initial ) <EOL> @ property <EOL> def page_context ( self ) : <EOL> context = { <EOL> "<STR_LIT>" : self . form , <EOL> "<STR_LIT>" : self . domain , <EOL> } <EOL> return context <EOL> def post ( self , request , * args , ** kwargs ) : <EOL> if self . form . is_valid ( ) : <EOL> self . form . save ( self . commtrack_settings ) <EOL> messages . success ( request , _ ( "<STR_LIT>" ) ) <EOL> return HttpResponseRedirect ( reverse ( SubscribeSMSView . urlname , args = [ self . domain ] ) ) <EOL> return self . get ( request , * args , ** kwargs ) <EOL> class SMSLanguagesView ( BaseMessagingSectionView ) : <EOL> urlname = '<STR_LIT>' <EOL> template_name = "<STR_LIT>" <EOL> page_title = ugettext_noop ( "<STR_LIT>" ) <EOL> @ use_bootstrap3 <EOL> @ use_jquery_ui <EOL> @ method_decorator ( domain_admin_required ) <EOL> def dispatch ( self , * args , ** kwargs ) : <EOL> return super ( SMSLanguagesView , self ) . dispatch ( * args , ** kwargs ) <EOL> @ property <EOL> def page_context ( self ) : <EOL> with StandaloneTranslationDoc . get_locked_obj ( self . domain , "<STR_LIT>" , create = True ) as tdoc : <EOL> if len ( tdoc . langs ) == <NUM_LIT:0> : <EOL> tdoc . langs = [ "<STR_LIT>" ] <EOL> tdoc . translations [ "<STR_LIT>" ] = { } <EOL> tdoc . save ( ) <EOL> context = { <EOL> "<STR_LIT>" : self . domain , <EOL> "<STR_LIT>" : tdoc . langs , <EOL> "<STR_LIT>" : { <EOL> "<STR_LIT:action>" : reverse ( "<STR_LIT>" , args = ( self . domain , ) ) , <EOL> "<STR_LIT>" : reverse ( "<STR_LIT>" , args = ( self . domain , ) ) , <EOL> "<STR_LIT>" : _ ( "<STR_LIT>" ) , <EOL> "<STR_LIT>" : _ ( "<STR_LIT>" ) , <EOL> } , <EOL> } <EOL> context . update ( { <EOL> "<STR_LIT>" : get_bulk_upload_form ( context ) , <EOL> } ) <EOL> return context <EOL> @ domain_admin_required <EOL> @ requires_privilege_with_fallback ( privileges . OUTBOUND_SMS ) <EOL> def edit_sms_languages ( request , domain ) : <EOL> """<STR_LIT>""" <EOL> with StandaloneTranslationDoc . get_locked_obj ( domain , "<STR_LIT>" , <EOL> create = True ) as tdoc : <EOL> try : <EOL> from corehq . apps . app_manager . views . utils import validate_langs <EOL> langs , rename , build = validate_langs ( request , tdoc . langs , <EOL> validate_build = False ) <EOL> except AssertionError : <EOL> return HttpResponse ( status = <NUM_LIT> ) <EOL> for old , new in rename . items ( ) : <EOL> if old != new : <EOL> tdoc . translations [ new ] = tdoc . translations [ old ] <EOL> del tdoc . translations [ old ] <EOL> for lang in langs : <EOL> if lang not in tdoc . translations : <EOL> tdoc . translations [ lang ] = { } <EOL> for lang in tdoc . translations . keys ( ) : <EOL> if lang not in langs : <EOL> del tdoc . translations [ lang ] <EOL> tdoc . langs = langs <EOL> tdoc . save ( ) <EOL> return json_response ( langs ) <EOL> @ domain_admin_required <EOL> @ requires_privilege_with_fallback ( privileges . OUTBOUND_SMS ) <EOL> def download_sms_translations ( request , domain ) : <EOL> tdoc = StandaloneTranslationDoc . get_obj ( domain , "<STR_LIT>" ) <EOL> columns = [ "<STR_LIT>" ] + tdoc . langs + [ "<STR_LIT:default>" ] <EOL> msg_ids = sorted ( _MESSAGES . keys ( ) ) <EOL> rows = [ ] <EOL> for msg_id in msg_ids : <EOL> rows . append ( [ msg_id ] ) <EOL> for lang in tdoc . langs : <EOL> for row in rows : <EOL> row . append ( tdoc . translations [ lang ] . get ( row [ <NUM_LIT:0> ] , "<STR_LIT>" ) ) <EOL> for row in rows : <EOL> row . append ( _MESSAGES . get ( row [ <NUM_LIT:0> ] ) ) <EOL> temp = StringIO ( ) <EOL> headers = ( ( "<STR_LIT>" , tuple ( columns ) ) , ) <EOL> data = ( ( "<STR_LIT>" , tuple ( rows ) ) , ) <EOL> export_raw ( headers , data , temp ) <EOL> return export_response ( temp , Format . XLS_2007 , "<STR_LIT>" ) <EOL> @ domain_admin_required <EOL> @ requires_privilege_with_fallback ( privileges . OUTBOUND_SMS ) <EOL> @ get_file ( "<STR_LIT>" ) <EOL> def upload_sms_translations ( request , domain ) : <EOL> try : <EOL> workbook = WorkbookJSONReader ( request . file ) <EOL> translations = workbook . get_worksheet ( title = '<STR_LIT>' ) <EOL> with StandaloneTranslationDoc . get_locked_obj ( domain , "<STR_LIT>" ) as tdoc : <EOL> msg_ids = sorted ( _MESSAGES . keys ( ) ) <EOL> result = { } <EOL> for lang in tdoc . langs : <EOL> result [ lang ] = { } <EOL> for row in translations : <EOL> for lang in tdoc . langs : <EOL> if row . get ( lang ) : <EOL> msg_id = row [ "<STR_LIT>" ] <EOL> if msg_id in msg_ids : <EOL> val = row [ lang ] <EOL> if not isinstance ( val , basestring ) : <EOL> val = str ( val ) <EOL> val = val . strip ( ) <EOL> result [ lang ] [ msg_id ] = val <EOL> tdoc . translations = result <EOL> tdoc . save ( ) <EOL> messages . success ( request , _ ( "<STR_LIT>" ) ) <EOL> except Exception : <EOL> notify_exception ( request , '<STR_LIT>' ) <EOL> messages . error ( request , _ ( "<STR_LIT>" ) ) <EOL> return HttpResponseRedirect ( reverse ( '<STR_LIT>' , args = [ domain ] ) ) <EOL> class SMSSettingsView ( BaseMessagingSectionView ) : <EOL> urlname = "<STR_LIT>" <EOL> template_name = "<STR_LIT>" <EOL> page_title = ugettext_noop ( "<STR_LIT>" ) <EOL> @ property <EOL> def page_name ( self ) : <EOL> return _ ( "<STR_LIT>" ) <EOL> @ property <EOL> def page_url ( self ) : <EOL> return reverse ( self . urlname , args = [ self . domain ] ) <EOL> @ property <EOL> @ memoized <EOL> def previewer ( self ) : <EOL> return self . request . couch_user . is_previewer ( ) <EOL> def get_welcome_message_recipient ( self , domain_obj ) : <EOL> if ( <EOL> domain_obj . enable_registration_welcome_sms_for_case and <EOL> domain_obj . enable_registration_welcome_sms_for_mobile_worker <EOL> ) : <EOL> return WELCOME_RECIPIENT_ALL <EOL> elif domain_obj . enable_registration_welcome_sms_for_case : <EOL> return WELCOME_RECIPIENT_CASE <EOL> elif domain_obj . enable_registration_welcome_sms_for_mobile_worker : <EOL> return WELCOME_RECIPIENT_MOBILE_WORKER <EOL> else : <EOL> return WELCOME_RECIPIENT_NONE <EOL> @ property <EOL> @ memoized <EOL> def form ( self ) : <EOL> if self . request . method == "<STR_LIT:POST>" : <EOL> form = SettingsForm ( self . request . POST , cchq_domain = self . domain , <EOL> cchq_is_previewer = self . previewer ) <EOL> else : <EOL> domain_obj = Domain . get_by_name ( self . domain , strict = True ) <EOL> enabled_disabled = lambda b : ( ENABLED if b else DISABLED ) <EOL> default_custom = lambda b : ( CUSTOM if b else DEFAULT ) <EOL> initial = { <EOL> "<STR_LIT>" : <EOL> enabled_disabled ( domain_obj . use_default_sms_response ) , <EOL> "<STR_LIT>" : <EOL> domain_obj . default_sms_response , <EOL> "<STR_LIT>" : <EOL> enabled_disabled ( len ( domain_obj . restricted_sms_times ) > <NUM_LIT:0> ) , <EOL> "<STR_LIT>" : <EOL> [ w . to_json ( ) for w in domain_obj . restricted_sms_times ] , <EOL> "<STR_LIT>" : <EOL> enabled_disabled ( domain_obj . send_to_duplicated_case_numbers ) , <EOL> "<STR_LIT>" : <EOL> default_custom ( domain_obj . custom_case_username ) , <EOL> "<STR_LIT>" : <EOL> domain_obj . custom_case_username , <EOL> "<STR_LIT>" : <EOL> default_custom ( <EOL> domain_obj . chat_message_count_threshold is not None ) , <EOL> "<STR_LIT>" : <EOL> domain_obj . chat_message_count_threshold , <EOL> "<STR_LIT>" : <EOL> enabled_disabled ( len ( domain_obj . sms_conversation_times ) > <NUM_LIT:0> ) , <EOL> "<STR_LIT>" : <EOL> [ w . to_json ( ) for w in domain_obj . sms_conversation_times ] , <EOL> "<STR_LIT>" : <EOL> domain_obj . sms_conversation_length , <EOL> "<STR_LIT>" : <EOL> ( SHOW_ALL <EOL> if not domain_obj . filter_surveys_from_chat else <EOL> SHOW_INVALID <EOL> if domain_obj . show_invalid_survey_responses_in_chat else <EOL> HIDE_ALL ) , <EOL> "<STR_LIT>" : <EOL> enabled_disabled ( domain_obj . count_messages_as_read_by_anyone ) , <EOL> "<STR_LIT>" : <EOL> default_custom ( domain_obj . custom_chat_template ) , <EOL> "<STR_LIT>" : <EOL> domain_obj . custom_chat_template , <EOL> "<STR_LIT>" : <EOL> enabled_disabled ( domain_obj . sms_case_registration_enabled ) , <EOL> "<STR_LIT>" : <EOL> domain_obj . sms_case_registration_type , <EOL> "<STR_LIT>" : <EOL> domain_obj . sms_case_registration_owner_id , <EOL> "<STR_LIT>" : <EOL> domain_obj . sms_case_registration_user_id , <EOL> "<STR_LIT>" : <EOL> enabled_disabled ( domain_obj . sms_mobile_worker_registration_enabled ) , <EOL> "<STR_LIT>" : <EOL> self . get_welcome_message_recipient ( domain_obj ) , <EOL> } <EOL> form = SettingsForm ( initial = initial , cchq_domain = self . domain , <EOL> cchq_is_previewer = self . previewer ) <EOL> return form <EOL> @ property <EOL> def page_context ( self ) : <EOL> return { <EOL> "<STR_LIT>" : self . form , <EOL> } <EOL> def post ( self , request , * args , ** kwargs ) : <EOL> form = self . form <EOL> if form . is_valid ( ) : <EOL> domain_obj = Domain . get_by_name ( self . domain , strict = True ) <EOL> field_map = [ <EOL> ( "<STR_LIT>" , <EOL> "<STR_LIT>" ) , <EOL> ( "<STR_LIT>" , <EOL> "<STR_LIT>" ) , <EOL> ( "<STR_LIT>" , <EOL> "<STR_LIT>" ) , <EOL> ( "<STR_LIT>" , <EOL> "<STR_LIT>" ) , <EOL> ( "<STR_LIT>" , <EOL> "<STR_LIT>" ) , <EOL> ( "<STR_LIT>" , <EOL> "<STR_LIT>" ) , <EOL> ( "<STR_LIT>" , <EOL> "<STR_LIT>" ) , <EOL> ( "<STR_LIT>" , <EOL> "<STR_LIT>" ) , <EOL> ( "<STR_LIT>" , <EOL> "<STR_LIT>" ) , <EOL> ( "<STR_LIT>" , <EOL> "<STR_LIT>" ) , <EOL> ] <EOL> if self . previewer : <EOL> field_map . append ( <EOL> ( "<STR_LIT>" , <EOL> "<STR_LIT>" ) <EOL> ) <EOL> for ( model_field_name , form_field_name ) in field_map : <EOL> setattr ( domain_obj , model_field_name , <EOL> form . cleaned_data [ form_field_name ] ) <EOL> survey_traffic_option = form . cleaned_data [ "<STR_LIT>" ] <EOL> if survey_traffic_option == HIDE_ALL : <EOL> domain_obj . filter_surveys_from_chat = True <EOL> domain_obj . show_invalid_survey_responses_in_chat = False <EOL> elif survey_traffic_option == SHOW_INVALID : <EOL> domain_obj . filter_surveys_from_chat = True <EOL> domain_obj . show_invalid_survey_responses_in_chat = True <EOL> else : <EOL> domain_obj . filter_surveys_from_chat = False <EOL> domain_obj . show_invalid_survey_responses_in_chat = False <EOL> if form . cleaned_data [ "<STR_LIT>" ] : <EOL> domain_obj . sms_case_registration_enabled = True <EOL> domain_obj . sms_case_registration_type = form . cleaned_data [ <EOL> "<STR_LIT>" ] <EOL> domain_obj . sms_case_registration_owner_id = form . cleaned_data [ <EOL> "<STR_LIT>" ] <EOL> domain_obj . sms_case_registration_user_id = form . cleaned_data [ <EOL> "<STR_LIT>" ] <EOL> else : <EOL> domain_obj . sms_case_registration_enabled = False <EOL> domain_obj . enable_registration_welcome_sms_for_case = form . enable_registration_welcome_sms_for_case <EOL> domain_obj . enable_registration_welcome_sms_for_mobile_worker = form . enable_registration_welcome_sms_for_mobile_worker <EOL> domain_obj . save ( ) <EOL> messages . success ( request , _ ( "<STR_LIT>" ) ) <EOL> return self . get ( request , * args , ** kwargs ) <EOL> @ method_decorator ( domain_admin_required ) <EOL> @ method_decorator ( requires_privilege_with_fallback ( privileges . OUTBOUND_SMS ) ) <EOL> @ use_bootstrap3 <EOL> @ use_timepicker <EOL> def dispatch ( self , request , * args , ** kwargs ) : <EOL> return super ( SMSSettingsView , self ) . dispatch ( request , * args , ** kwargs ) <EOL> class ManageRegistrationInvitationsView ( BaseAdvancedMessagingSectionView , CRUDPaginatedViewMixin ) : <EOL> template_name = '<STR_LIT>' <EOL> urlname = '<STR_LIT>' <EOL> page_title = ugettext_lazy ( '<STR_LIT>' ) <EOL> limit_text = ugettext_noop ( "<STR_LIT>" ) <EOL> empty_notification = ugettext_noop ( "<STR_LIT>" ) <EOL> loading_message = ugettext_noop ( "<STR_LIT>" ) <EOL> strict_domain_fetching = True <EOL> @ property <EOL> @ memoized <EOL> def invitations_form ( self ) : <EOL> if self . request . method == '<STR_LIT:POST>' : <EOL> return SendRegistrationInviationsForm ( self . request . POST , domain = self . domain ) <EOL> else : <EOL> return SendRegistrationInviationsForm ( domain = self . domain ) <EOL> @ property <EOL> @ memoized <EOL> def project_timezone ( self ) : <EOL> return get_timezone_for_user ( None , self . domain ) <EOL> @ property <EOL> def parameters ( self ) : <EOL> return self . request . POST if self . request . method == '<STR_LIT:POST>' else self . request . GET <EOL> @ property <EOL> def page_context ( self ) : <EOL> context = self . pagination_context <EOL> context . update ( { <EOL> '<STR_LIT>' : self . invitations_form , <EOL> '<STR_LIT>' : <EOL> self . domain_object . sms_mobile_worker_registration_enabled , <EOL> } ) <EOL> return context <EOL> @ property <EOL> def total ( self ) : <EOL> return SelfRegistrationInvitation . objects . filter ( domain = self . domain ) . count ( ) <EOL> @ property <EOL> def column_names ( self ) : <EOL> return [ <EOL> _ ( '<STR_LIT>' ) , <EOL> _ ( '<STR_LIT>' ) , <EOL> _ ( '<STR_LIT>' ) , <EOL> _ ( '<STR_LIT>' ) , <EOL> _ ( '<STR_LIT>' ) , <EOL> _ ( '<STR_LIT>' ) , <EOL> ] <EOL> def format_status ( self , invitation ) : <EOL> if invitation . status == SelfRegistrationInvitation . STATUS_REGISTERED : <EOL> registered_date = ( ServerTime ( invitation . registered_date ) <EOL> . user_time ( self . project_timezone ) <EOL> . done ( ) <EOL> . strftime ( SERVER_DATETIME_FORMAT ) ) <EOL> return _ ( "<STR_LIT>" ) % { '<STR_LIT:date>' : registered_date } <EOL> else : <EOL> return { <EOL> SelfRegistrationInvitation . STATUS_PENDING : _ ( "<STR_LIT>" ) , <EOL> SelfRegistrationInvitation . STATUS_EXPIRED : _ ( "<STR_LIT>" ) , <EOL> } . get ( invitation . status ) <EOL> @ property <EOL> def paginated_list ( self ) : <EOL> invitations = SelfRegistrationInvitation . objects . filter ( <EOL> domain = self . domain <EOL> ) . order_by ( '<STR_LIT>' ) <EOL> doc_info_cache = { } <EOL> for invitation in invitations [ self . skip : self . skip + self . limit ] : <EOL> if invitation . app_id in doc_info_cache : <EOL> doc_info = doc_info_cache [ invitation . app_id ] <EOL> else : <EOL> doc_info = get_doc_info_by_id ( self . domain , invitation . app_id ) <EOL> doc_info_cache [ invitation . app_id ] = doc_info <EOL> yield { <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT:id>' : invitation . pk , <EOL> '<STR_LIT>' : ( ServerTime ( invitation . created_date ) <EOL> . user_time ( self . project_timezone ) <EOL> . done ( ) <EOL> . strftime ( SERVER_DATETIME_FORMAT ) ) , <EOL> '<STR_LIT>' : '<STR_LIT>' % invitation . phone_number , <EOL> '<STR_LIT:status>' : self . format_status ( invitation ) , <EOL> '<STR_LIT>' : invitation . expiration_date . strftime ( SERVER_DATE_FORMAT ) , <EOL> '<STR_LIT>' : doc_info . display , <EOL> '<STR_LIT>' : doc_info . link , <EOL> '<STR_LIT>' : dict ( SelfRegistrationInvitation . PHONE_TYPE_CHOICES ) . get ( invitation . phone_type ) , <EOL> } , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> } <EOL> def post ( self , * args , ** kwargs ) : <EOL> if self . request . POST . get ( '<STR_LIT:action>' ) == '<STR_LIT>' : <EOL> if not self . domain_object . sms_mobile_worker_registration_enabled : <EOL> return self . get ( * args , ** kwargs ) <EOL> if self . invitations_form . is_valid ( ) : <EOL> phone_numbers = self . invitations_form . cleaned_data . get ( '<STR_LIT>' ) <EOL> app_id = self . invitations_form . cleaned_data . get ( '<STR_LIT>' ) <EOL> result = SelfRegistrationInvitation . initiate_workflow ( <EOL> self . domain , <EOL> phone_numbers , <EOL> app_id = app_id <EOL> ) <EOL> success_numbers , invalid_format_numbers , numbers_in_use = result <EOL> if success_numbers : <EOL> messages . success ( <EOL> self . request , <EOL> _ ( "<STR_LIT>" ) % { <EOL> '<STR_LIT>' : '<STR_LIT:U+002C>' . join ( success_numbers ) , <EOL> } <EOL> ) <EOL> if invalid_format_numbers : <EOL> messages . error ( <EOL> self . request , <EOL> _ ( "<STR_LIT>" <EOL> "<STR_LIT>" ) % { <EOL> '<STR_LIT>' : '<STR_LIT:U+002C>' . join ( invalid_format_numbers ) <EOL> } <EOL> ) <EOL> if numbers_in_use : <EOL> messages . error ( <EOL> self . request , <EOL> _ ( "<STR_LIT>" <EOL> "<STR_LIT>" ) % { <EOL> '<STR_LIT>' : '<STR_LIT:U+002C>' . join ( numbers_in_use ) <EOL> } <EOL> ) <EOL> return self . get ( * args , ** kwargs ) <EOL> else : <EOL> if not self . domain_object . sms_mobile_worker_registration_enabled : <EOL> raise Http404 ( ) <EOL> return self . paginate_crud_response <EOL> class InvitationAppInfoView ( View , DomainViewMixin ) : <EOL> urlname = '<STR_LIT>' <EOL> @ property <EOL> @ memoized <EOL> def token ( self ) : <EOL> token = self . kwargs . get ( '<STR_LIT>' ) <EOL> if not token : <EOL> raise Http404 ( ) <EOL> return token <EOL> @ property <EOL> @ memoized <EOL> def invitation ( self ) : <EOL> invitation = SelfRegistrationInvitation . by_token ( self . token ) <EOL> if not invitation : <EOL> raise Http404 ( ) <EOL> return invitation <EOL> def get ( self , * args , ** kwargs ) : <EOL> if not self . invitation . odk_url : <EOL> raise Http404 ( ) <EOL> url = str ( self . invitation . odk_url ) . strip ( ) <EOL> response = '<STR_LIT>' % ( url , sign ( url ) ) <EOL> response = base64 . b64encode ( response ) <EOL> return HttpResponse ( response ) <EOL> def post ( self , * args , ** kwargs ) : <EOL> return self . get ( * args , ** kwargs ) <EOL> class IncomingBackendView ( View ) : <EOL> def dispatch ( self , request , api_key , * args , ** kwargs ) : <EOL> try : <EOL> api_user = ApiUser . get ( '<STR_LIT>' % api_key ) <EOL> except ResourceNotFound : <EOL> return HttpResponse ( status = <NUM_LIT> ) <EOL> if api_user . doc_type != '<STR_LIT>' or not api_user . has_permission ( PERMISSION_POST_SMS ) : <EOL> return HttpResponse ( status = <NUM_LIT> ) <EOL> return super ( IncomingBackendView , self ) . dispatch ( request , api_key , * args , ** kwargs ) <EOL> class NewIncomingBackendView ( View ) : <EOL> domain = None <EOL> backend_couch_id = None <EOL> @ property <EOL> def backend_class ( self ) : <EOL> """<STR_LIT>""" <EOL> raise NotImplementedError ( "<STR_LIT>" ) <EOL> @ method_decorator ( csrf_exempt ) <EOL> def dispatch ( self , request , api_key , * args , ** kwargs ) : <EOL> try : <EOL> self . domain , self . backend_couch_id = SQLMobileBackend . get_backend_info_by_api_key ( <EOL> self . backend_class . get_api_id ( ) , <EOL> api_key <EOL> ) <EOL> except SQLMobileBackend . DoesNotExist : <EOL> return HttpResponse ( status = <NUM_LIT> ) <EOL> return super ( NewIncomingBackendView , self ) . dispatch ( request , api_key , * args , ** kwargs ) </s>
