def track_by_id(request, id): event = request.GET.get('event', None) if event is None: event = request.GET.get('stage', None) callback_id = request.GET.get('id', None) print 'track_by_id', id, event, callback_id if None in (event, callback_id): random_delay(finishing_with=0.6) # to prevent time attacks return HttpResponse('') try: callback = PendingCallback.objects.get(id=int(id)) except: callback = None if not callback: print ' PendingCallback %s is not found' % id random_delay(finishing_with=0.6) # to prevent time attacks return HttpResponse('') # if callback.mtt_callback_call_id != callback_id: # print (' WARNING: %s != %s' % (callback_id, callback.mtt_callback_call_id)) dt = 0.0 try: dt = (datetime.datetime.now() - callback.when).total_seconds() except: import traceback traceback.print_exc() callback.mtt_callback_call_id = callback_id callback.tracking_history += "%s(%s);" % (event, dt) callback.callback_status = tracking_history_to_callback_status(callback.tracking_history, 'tracking') callback.save() print ' OK! [%s], callback_status = %s' % (callback.tracking_history, callback.callback_status) # if TRACKING_EVENT_END_SIDE_A in callback.tracking_history: refresh_pending_callbacks([callback,]) random_delay() # to prevent time attacks return HttpResponse('')
def get(self, request): try: if 'callback' not in request.GET: return HttpResponse(json.dumps({ 'response': 'error', 'message': 'callback argument not specified'}, ensure_ascii=False), 'application/json') if 'token' not in request.GET: return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps({ 'response': 'error', 'message': 'token argument not specified'}, ensure_ascii=False)), 'text/javascript') #--- read from DB by token ID token = request.GET.get('token', None) widget = None try: widget = Widget.objects.get(id=int(token)) except: import traceback return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps({ 'response': 'error', 'message': 'no widget found, token=%s, error=%s' % ( token, traceback.format_exc())}, ensure_ascii=False)), 'text/javascript') client_ip_addr = request.META.get('REMOTE_ADDR', '') jdata = { 'callback': request.GET['callback'].replace('CallbackRegistry.', ''), 'ip': client_ip_addr, 'token': request.GET['token'], 'referrer': urllib2.unquote(request.GET.get('referrer', '')), 'search_request': urllib2.unquote(request.GET.get('search_request', '')), 'hostname': urllib2.unquote(request.GET.get('hostname', '')), } widget.last_executed = timezone.now() widget.save() #--- check ip in black list if self.is_ip_in_blacklist(jdata['ip'], widget.blacklist_ip.split(',')): jdata.update({'response': 'refused', 'message': '%s were found in the black list' % jdata['ip'], }) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') try: operators = widget.client.operator_set.all() if widget.related_operators.count() < 1 \ else widget.related_operators.all() except: import traceback return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps({ 'response': 'error', 'message': 'no operators found, token=%s, error=%s' % ( token, traceback.format_exc())}, ensure_ascii=False)), 'text/javascript') #--- is_active try: is_on = widget.is_active is_active = widget.client.balance_minutes > 1 except: return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps({ 'response': 'error', 'message': 'unable to read the data from DB'}, ensure_ascii=False)), 'text/javascript') #--- check paid status # if MTT balance is too low or widget is not active - set to false jdata['mode'] = 'paid' if is_active else 'free' if not is_on: jdata['mode'] = 'off' #--- managers manager = {} managers_wo_phones = [] for i, operator in enumerate(operators, 1): if operator == widget.default_operator: managers_wo_phones.insert(0, { # 'name': operator.name.encode('utf8').decode('utf8'), # 'role': operator.position.encode('utf8').decode('utf8'), 'name': unicode(operator.name).encode('unicode-escape'), 'role': unicode(operator.position).encode('unicode-escape'), 'photo_url': operator.photo_url, }) manager = { # 'name': operator.name.encode('utf8').decode('utf8'), # 'role': operator.position.encode('utf8').decode('utf8'), 'name': unicode(operator.name).encode('unicode-escape'), 'role': unicode(operator.position).encode('unicode-escape'), 'photo_url': operator.photo_url, } else: managers_wo_phones.append({ # 'name': operator.name.encode('utf8').decode('utf8'), # 'role': operator.position.encode('utf8').decode('utf8'), 'name': unicode(operator.name).encode('unicode-escape'), 'role': unicode(operator.position).encode('unicode-escape'), 'photo_url': operator.photo_url, }) if not len(managers_wo_phones): jdata.update({ 'response': 'error', 'message': 'no managers found for this widget'}) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') if len(manager) == 0: manager = managers_wo_phones[0] # return managers to the widget - to show pictures and names # but without phone number jdata['managers'] = managers_wo_phones # provide client schedule jdata['schedule'] = widget.schedule.asList() #--- REQUEST OPTIONS # retrieve widget settings from DB when widget loads if 'request_options' in request.GET: hostname = request.GET.get('hostname', None) valid_host = False print 'request_options', unicode(widget.site_url).encode(locale.getpreferredencoding()) if hostname: # print 'hostname', type(hostname) hostname = unicode(hostname) hostname = hostname.replace('www.', '') try: print hostname.encode(locale.getpreferredencoding()) except: print 'FAIL: hostname.encode(locale.getpreferredencoding())' if widget.site_url.count(hostname): valid_host = True if not valid_host: try: hostname_uq = urllib2.unquote(hostname) if widget.site_url.count(hostname_uq): valid_host = True # print 'hostname_uq', type(hostname_uq) print hostname_uq.encode(locale.getpreferredencoding()) except: print 'FAIL: hostname_uq = urllib2.unquote(hostname)' if not valid_host: try: hostname_idna = hostname.decode('idna') if widget.site_url.count(hostname_idna): valid_host = True # print 'hostname_idna', type(hostname_idna) print hostname_idna.encode(locale.getpreferredencoding()) except: print 'FAIL: hostname_idna = hostname.decode("idna")' if not valid_host: try: hostname_utf8 = hostname_uq.decode('utf8') if widget.site_url.count(hostname_utf8): valid_host = True # print 'hostname_utf8', type(hostname_utf8) print hostname_utf8.encode(locale.getpreferredencoding()) except: print 'FAIL: hostname_utf8 = hostname_uq.decode("utf8")' if not valid_host: try: hostname_win1251 = hostname_uq.decode('windows-1251') if widget.site_url.count(hostname_win1251): valid_host = True # print 'hostname_win1251', type(hostname_win1251) print hostname_win1251.encode(locale.getpreferredencoding()) except: print 'FAIL: hostname_win1251 = hostname_uq.decode("windows-1251")' print 'valid_host:', valid_host if not valid_host: jdata.update({'response': 'refused', 'message': 'incorrect host name', }) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') s = widget.settings s = json.loads(s) try: for k in s.keys(): if isinstance(s[k], unicode): s[k] = (s[k].encode('unicode-escape')) elif isinstance(s[k], str): s[k] = (unicode(s[k]).encode('unicode-escape')) except: import traceback traceback.print_exc() # BE SURE TO CHECK FOR DEFAULT VALUES FOR ALL NEW OPTIONS !!! if 'cookie_ttl_seconds' not in s: s['cookie_ttl_seconds'] = 1 * 60 * 60 if 'submit_button_line_height' not in s: s['submit_button_line_height'] = 42 if 'encoding' not in s: s['encoding'] = 'utf-8' # TODO s['position'] = 'fixed' s['flag_is_operator_shown_in_widget'] = widget.is_operator_shown_in_widget s['flag_disable_on_mobiles'] = widget.disable_on_mobiles jdata['options'] = s jdata.update({ 'response': 'ok', 'message': 'connected'}) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') #--- REQUEST STATUS if 'request_status' in request.GET: hostname = request.GET.get('hostname', None) call_id = request.GET.get('callback_id', None) valid_host = False # print 'request_options', widget.site_url, hostname, unicode(hostname).decode('idna'), type(unicode(hostname).decode('idna')) if hostname: if widget.site_url.count(hostname): valid_host = True if widget.site_url.count(unicode(hostname).decode('idna')): valid_host = True if not valid_host: jdata.update({'response': 'refused', 'message': 'incorrect host name', }) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') try: callback = PendingCallback.objects.get(id=call_id) except ObjectDoesNotExist: random_delay(finishing_with=0.6) # to prevent time attacks jdata.update({'response': 'failed', 'message': 'call id %s not found' % call_id, }) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') jdata['status'] = { 'tracking_history': callback.tracking_history, 'callback_status': callback.callback_status, } jdata.update({ 'response': 'ok', 'message': 'connected'}) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') #--- ORDER CALL if 'order_time' in request.GET and 'order_day' in request.GET and 'order_delta_day' in request.GET and 'order_phone' in request.GET: jdata['notify_by_email'] = widget.callback_notifications_email jdata['order_time'] = request.GET['order_time'] jdata['order_day'] = request.GET['order_day'] jdata['order_delta_day'] = request.GET['order_delta_day'] jdata['order_phone'] = request.GET['order_phone'] if self.is_number_in_blacklist(jdata['order_phone'], widget.blacklist_phones.split(',')): jdata.update({'response': 'refused', 'message': '%s were found in the black list' % jdata['order_phone'], }) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') try: if widget.is_email_notification_on: # notify manager via email mail.send_email_order_call( widget.callback_notifications_email, jdata['order_phone'], jdata['order_day'], jdata['order_time'], widget.site_url) if widget.is_sms_notification_on: # notify manager via SMS sms.send(widget.sms_notification_number, u"CallFeed.NET: обратный звонок на %s, телефон: %s, время для связи: %s в %s" % ( widget.site_url, jdata['order_phone'], widget.callback_notifications_email, jdata['order_time'])) response = 'ok' except: traceback.print_exc() response = 'exception: ' + traceback.format_exc() jdata.update({'response': response, 'message': 'sending email to manager on %s' % widget.callback_notifications_email, }) try: order_time = jdata['order_time'].split(':') order_date = datetime.datetime.combine( datetime.datetime.now() + datetime.timedelta(days=int(jdata['order_delta_day'])), datetime.time(hour=int(order_time[0]), minute=int(order_time[1]))) self.order_deferred_callback(widget, jdata['ip'], jdata['referrer'], jdata['search_request'], order_date, jdata['order_phone']) except: import traceback print traceback.format_exc() print ' ORDER call on %s' % (widget.site_url,) # temporary save data to the local file filename = '/home/callfeed/incomings/%s_%s.txt' % ( jdata['ip'].replace('.', '_'), jdata['callback']) open(filename, 'wb').write(pprint.pformat(jdata)) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') #--- TIME OFF if 'timeoff_time' in request.GET and 'timeoff_day' in request.GET and 'timeoff_phone' in request.GET: jdata['notify_by_email'] = widget.callback_notifications_email jdata['timeoff_time'] = request.GET['timeoff_time'] jdata['timeoff_day'] = request.GET['timeoff_day'] jdata['timeoff_phone'] = request.GET['timeoff_phone'] if self.is_number_in_blacklist(jdata['timeoff_phone'], widget.blacklist_phones.split(',')): jdata.update({'response': 'refused', 'message': '%s were found in the black list' % jdata['timeoff_phone'], }) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') try: if widget.is_email_notification_on: # notify manager via email mail.send_email_timeoff_order_call( widget.callback_notifications_email, jdata['timeoff_phone'], jdata['timeoff_day'], jdata['timeoff_time'], widget.site_url) if widget.is_sms_notification_on: # notify manager via SMS sms.send(widget.sms_notification_number, u"CallFeed.NET: заказ звонка с %s в нерабочее время, телефон: %s, время для связи: %s в %s" % ( widget.site_url, jdata['timeoff_phone'], jdata['timeoff_day'], jdata['timeoff_time'])) response = 'ok' except: traceback.print_exc() response = 'exception: ' + traceback.format_exc() jdata.update({'response': response, 'message': 'sending email to manager, email=%s' % widget.callback_notifications_email, }) print ' visitor made a TIME OFF call on %s' % widget.site_url # temporary save data to the local file filename = '/home/callfeed/incomings/%s_%s.txt' % ( jdata['ip'].replace('.', '_'), jdata['callback']) open(filename, 'wb').write(pprint.pformat(jdata)) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') #--- SEND MESSAGE if 'message_text' in request.GET and 'message_email' in request.GET and 'message_phone' in request.GET: jdata['notify_by_email'] = widget.callback_notifications_email jdata['message_text'] = request.GET['message_text'] jdata['message_email'] = request.GET['message_email'] jdata['message_phone'] = request.GET['message_phone'] if self.is_number_in_blacklist(jdata['message_phone'], widget.blacklist_phones.split(',')): jdata.update({'response': 'refused', 'message': '%s were found in the black list' % jdata['message_phone'], }) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') try: # notify manager via email mail.send_email_message( str(widget.offline_message_notifications_email), jdata['message_phone'], str(jdata['message_email']), jdata['message_text'], widget.site_url) if widget.is_sms_notification_on: # notify manager via SMS sms.send(widget.sms_notification_number, u"CallFeed.NET: новое входящее сообщение на %s, проверьте почту" % (widget.site_url)) response = 'ok' except: traceback.print_exc() response = 'exception: ' + traceback.format_exc() jdata.update({'response': response, 'message': 'sending email to manager', }) print " incomming MESSAGE on %s" % widget.site_url # temporary save data to the local file filename = '/home/callfeed/incomings/%s_%s.txt' % ( jdata['ip'].replace('.', '_'), jdata['callback']) open(filename, 'wb').write(pprint.pformat(jdata)) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') #--- FREE VERSION if 'free_time' in request.GET and 'free_day' in request.GET and 'free_phone' in request.GET: jdata['notify_by_email'] = widget.callback_notifications_email jdata['free_time'] = request.GET['free_time'] jdata['free_day'] = request.GET['free_day'] jdata['free_phone'] = request.GET['free_phone'] if self.is_number_in_blacklist(jdata['free_phone'], widget.blacklist_phones.split(',')): jdata.update({'response': 'refused', 'message': '%s were found in the black list' % jdata['free_phone'], }) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') try: mail.send_email_free_version_notification( widget.callback_notifications_email, jdata['free_phone'], jdata['free_day'], jdata['free_time'], widget.site_url) # notify manager via email response = 'ok' except: traceback.print_exc() response = 'exception: ' + traceback.format_exc() jdata.update({'response': response, 'message': 'sending email to manager, email=%s' % widget.callback_notifications_email, }) print ' FREE call from visitor on %s' % (widget.site_url,) # temporary save data to the local file filename = '/home/callfeed/incomings/%s_%s.txt' % ( jdata['ip'].replace('.', '_'), jdata['callback']) open(filename, 'wb').write(pprint.pformat(jdata)) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') #--- PAID VERSION CHECK if 'phone' not in request.GET: jdata.update({ 'response': 'ok', 'message': 'connected'}) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') jdata['phone'] = request.GET['phone'] if self.is_number_in_blacklist(jdata['phone'], widget.blacklist_phones.split(',')): jdata.update({'response': 'refused', 'message': '%s were found in the black list' % jdata['phone'], }) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') #--- INITIATE CALLBACK callback_result = JSONPEntryPoint.initiate_callback(jdata['phone'], widget, '', '', jdata['ip']) if callback_result[0] == 'exception': jdata.update({'response': 'error', 'message': callback_result[1], }) # temporary save data to the local file filename = '/home/callfeed/incomings/%s_%s.txt' % ( jdata['ip'].replace('.', '_'), jdata['callback']) open(filename, 'wb').write(pprint.pformat(jdata)) return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascript') jdata['mtt_response'] = callback_result[0] jdata['callback_id'] = callback_result[0]['callback_id'] jdata.update({'response': 'ok', 'message': callback_result[1], }) mtt_response = jdata.get('mtt_response', {}) mtt_response_result = mtt_response.get('result', None) # temporary save data to the local file filename = '/home/callfeed/incomings/%s_%s.txt' % ( jdata['ip'].replace('.', '_'), jdata['callback']) open(filename, 'wb').write(pprint.pformat(jdata)) print ('MTT CALL!!!', jdata['token'], jdata['hostname'], jdata['phone'], client_ip_addr, jdata['callback_id'], mtt_response_result) except Exception as e: import traceback traceback.print_exc() return HttpResponse('%s(%s);' % ( request.GET['callback'], json.dumps(jdata, ensure_ascii=False)), 'text/javascrit') # new_pending_info.mtt_callback_call_id = mtt_response_result_callback_id # new_pending_info.save() # if new_pending_info.mtt_callback_call_id != mtt_response_result_callback_id: # print (' WARNING: %s != %s' % (mtt_response_result_callback_id, new_pending_info.mtt_callback_call_id)) # return ('error', '%s != %s' % (mtt_response_result_callback_id, new_pending_info.mtt_callback_call_id)) # mtt_response_check = mttproxy.getCallBackFollowmeCallInfo(mtt.CUSTOMER_NAME, mtt_response_result_callback_id) # mtt_response_check_result = mtt_response_check.get('result', None) # # if mtt_response_check_result is None: # print (' ERROR: getCallBackFollowmeCallInfo returned None') # return ('error', 'getCallBackFollowmeCallInfo returned None',) # # call_info_struct = mtt_response_check_result.get('callBackFollowmeCallInfoStruct', None) # # if call_info_struct is None: # print (' ERROR: callBackFollowmeCallInfoStruct is None') # return ('error', 'callBackFollowmeCallInfoStruct is None',) # # record_url_a = call_info_struct.get('call_back_record_URL_A', '') # record_url_a = call_info_struct.get('downloadURL', '') # record_url_b = call_info_struct.get('call_back_record_URL_B', '') # record_url_b = call_info_struct.get('downloadURL', '') # # new_pending_info.call_description = call_info_struct.get('callDescription', '') # new_pending_info.phone_number_side_a = call_info_struct.get('destination_A', '') # new_pending_info.phone_number_side_b = call_info_struct.get('destination_B', '') # new_pending_info.charged_length_a_sec=int(call_info_struct.get('call_back_charged_length_A', '0')) # new_pending_info.charged_length_b_sec=int(call_info_struct.get('call_back_charged_length_B', '0')) # new_pending_info.real_length_a_sec=int(call_info_struct.get('call_back_real_length_A', '0')) # new_pending_info.real_length_b_sec=int(call_info_struct.get('call_back_real_length_B', '0')) # new_pending_info.record_url_a = record_url_a # new_pending_info.record_url_b = record_url_b # new_pending_info.waiting_period_a_sec = call_info_struct.get('waiting_period_A', '0') # new_pending_info.waiting_period_b_sec = call_info_struct.get('waiting_period_B', '0') # new_pending_info.callback_status = CallbackInfo.CALLBACK_STATUS_SUCCEED # new_pending_info.cost = call_info_struct.get('call_back_cost', 0.0) # new_pending_info.currency = call_info_struct.get('call_back_currency', 'RUB') # # new_pending_info.ip_side_b = callback.ip_side_b # # new_pending_info.geodata_side_b='-' # # mtt_callback_call_id=callback.mtt_callback_call_id, # # new_pending_info.referer = callback.referer, search_request=callback.search_request, # # new_pending_info.when = callback.when, # # new_pending_info.tracking_history=callback.tracking_history # new_pending_info.save() # # try: # charged_a = int(call_info_struct.get('call_back_charged_length_A', '0')) # charged_b = int(call_info_struct.get('call_back_charged_length_B', '0')) # widget.client.balance_minutes -= int((float(charged_a) + float(charged_b)) / 60.0) # widget.client.save() # print (' BALANCE:', widget.client.name, widget.client.email, widget.client.balance_minutes) # except: # traceback.print_exc() # if mtt_response_result_callback_id is not None: # new_pending_callback = PendingCallback(widget=widget, # mtt_callback_call_id=mtt_response_result_callback_id, # ip_side_b=ip_address, # geodata_side_b=ip_to_location(ip_address), # referer=rferrer_str, # search_request=search_str, # when=datetime.datetime.now(), # tracking_history='') # new_pending_callback.save()