def handle(self, *args, **options): """Загрузка cdr_csv информации о звонках в базу""" is_running = search_process(q=('load_cdr_csv', 'manage.py')) if is_running: logger.error('Already running %s' % (is_running, )) exit() # Разовая операция, нужна, чтобы привязать # звонки на наши номера, например, 73952546133, # а в белом списке этот телефон стоит как 83952546133 if options.get('link_redirects2clients'): # Достаем и подготавливаем редиректы redirects = Redirects.objects.all().values_list('phone', flat=True) redirects = [ kill_quotes(redirect, 'int') for redirect in redirects ] redirects = ['7%s' % redirect[1:] for redirect in redirects] rows = CdrCsv.objects.filter(dest__in=redirects, client_id__isnull=True).values( 'id', 'dest') for row in rows: dest = '8%s' % row['dest'][1:] client = PhonesWhiteList.objects.filter(phone=dest).first() if client: CdrCsv.objects.filter(pk=row['id']).update( client_id=client.tag, client_name=client.name) print(row['id'], row['dest'], client.name, client.tag) return # Разовая операция, нужна, чтобы задать правильный путь # для звонков через переадресацию, т/к они встают как uuid # без пути к файлу и расширения if options.get('fix_redirects2clients'): # Достаем и подготавливаем редиректы redirects = Redirects.objects.all().values_list('phone', flat=True) redirects = [ kill_quotes(redirect, 'int') for redirect in redirects ] print(redirects) rows = CdrCsv.objects.filter(dest__in=redirects, context='redirects_context') for row in rows: new_dest = '7%s' % row.dest[1:] CdrCsv.objects.filter(pk=row.id).update(dest=new_dest) print(row.id, new_dest) return analyze_logs()
def prepare_session(request, phone: str = None): """Подготовить сессию для регистрации/обновления профиля с подтверждением по обратному звонку :param request: HttpRequest :param phone: Телефон (если нет пользователя) """ result = {} shopper = get_shopper(request) if request.method == 'GET' and (shopper or phone): if shopper: phone = shopper.phone phone = kill_quotes(phone, 'int') request.session['confirm_phone'] = GenPasswd(4, '1234567890') request.session['phone'] = phone request.session.save() # Скрипт отправляет на свич телефон # и код и свич звонит и диктует params = { 'phone': phone, 'digit': request.session['confirm_phone'], } r = requests.get('%s/freeswitch/sms_service/say_code/' % settings.FREESWITCH_DOMAIN, params=params) result = r.json() return result
def save(self, *args, **kwargs): if self.phone: phone = kill_quotes(self.phone, 'int') if phone.startswith('7'): phone = '8%s' % (phone[1:], ) self.phone = phone super(PhonesWhiteList, self).save(*args, **kwargs)
def set_color(request): """Аякс запрос по сохранению цвета на товар """ result = {} product_id = request.GET.get('product_id') if not product_id.isdigit(): return JsonResponse(result, safe=False) color = request.GET.get('color') if color: color = kill_quotes(color, 'int') if not color: color = 0 product = Products.objects.filter(pk=product_id).first() if product: if request.user.has_perm('products.change_products'): product_color = ProductColor.objects.filter(product=product).first() if product_color: product_color.color = color else: product_color = ProductColor(product=product) product_color.save() result['success'] = 'Основной цвет сохранен' else: result['error'] = 'Недостаточно прав' else: result['error'] = 'Товар не найден' return JsonResponse(result, safe=False)
def update_product(self, attributes): """Обновление товара :param attributes: атрибуты товара """ articul = '_%s' % attributes.get(self.Articul) code = attributes.get(self.Kod) count = ''.join(attributes.get(self.Count, '').split()) manufacturer = attributes.get(self.Manufacturer) price = attributes.get(self.Cost) price = kill_quotes(price, 'int') price = price.replace(',', '.') name = attributes.get(self.Name) analog = Products.objects.filter(code=code).first() if not analog: #logger.info('[ERROR]: product not exists: %s' % articul) return params = { 'name': name, 'count': count, 'price': price, 'manufacturer': manufacturer, } try: Products.objects.filter(pk=analog.id).update(**params) except Exception as e: print(params, e) return self.updated.append(analog.code)
def defiz_phone(phone): """Дефизы в телефоне :param phone: телефон 83952123321 """ if not phone: return phone if type(phone) == int: phone = str(phone) phone = kill_quotes(phone, 'int') phone_len = len(phone) if phone_len == 5: phone = '%s-%s' % (phone[:3], phone[3:]) elif phone_len == 6: phone = '%s-%s' % (phone[:3], phone[3:]) elif phone_len == 7: phone = '%s-%s-%s' % (phone[:1], phone[1:4], phone[4:]) elif phone_len == 10: if phone.startswith('9'): # сотовые phone = '(%s) %s-%s-%s' % (phone[:3], phone[3], phone[4:7], phone[7:]) else: # городские phone = '(%s) %s-%s' % (phone[:4], phone[4:7], phone[7:]) elif phone_len == 11: if phone[1] == '9': # сотовые phone = '%s (%s) %s-%s-%s' % (phone[0], phone[1:4], phone[4], phone[5:8], phone[8:]) else: # городские phone = '%s (%s) %s-%s' % (phone[0], phone[1:5], phone[5:8], phone[8:]) return phone
def check_phone(phone): """Проверка телефона на валидность :param phone: телефон """ if not phone: return phone = kill_quotes(phone, 'int') if len(phone) == 11 and phone[0] in ('7', '8'): phone = '8%s' % phone[1:] return phone
def textize(text: str): """Убираем из текста все кавычки и спец символы Нужно для вставки в атрибуты тегов, например alt="" или title="" :param text: текст """ if not text: return '' if not isinstance(text, str): return text text = kill_quotes(text, 'strict_text', ' ') return text
def imagine(img: str, size: str, source: str, alt: str = ''): """Создание миниатюры изображения :param img: имя файла, например 1.jpg :param size: размер, например 150х150, x разделитель :param source: папка с исходным изображением, например, logos :param alt: текст alt для изображения, если тип bool вернем просто путь до изображения USAGE: <img src="{% imagine 'help.png' '150x150' 'img' %}"/> {% imagine 'help.png' '150x150' 'img' True %} - просто путь """ ups_path = UPS_PATH ups_image = '<img loading="lazy" src="%s" />' % ups_path if not img: if isinstance(alt, bool): return ups_path return ups_image # ----------------------------------- # Изображение на удаленном хостинге # Весь удаленно расположенный контент # следует грузить через lazy load js # Нужно передать размеры XXXxYYY # ----------------------------------- if img.startswith('http'): if isinstance(alt, bool): return img return '<img data-original="%s?size=%s" alt="%s" class="lazy" src="/static/img/misc/loading.gif" loading="lazy" />' % ( img, size, kill_quotes(alt, 'strict_text', ' ')) path_resized_img = imagine_image(img, size, source) if not path_resized_img: if isinstance(alt, bool): return ups_path return ups_image if isinstance(alt, bool): return path_resized_img return '<img src="%s" alt="%s" loading="lazy" />' % ( path_resized_img, kill_quotes(alt, 'strict_text', ' '))
def save(self, *args, **kwargs): super(Redirects, self).save(*args, **kwargs) if not self.is_active: self.drop_extension() return extension = """ <extension name="redirect_{}"> <condition field="destination_number" expression="^([78]{})$"> <action application="set" data="effective_caller_id_number={}"/> <action application="set" data="effective_caller_id_name={}"/> <action application="set" data="ringback={}"/> <action application="export" data="hold_music={}"/> <action application="set" data="ignore_early_media=true" /> <action application="set" data="record_file_name={}"/> <action application="set" data="media_bug_answer_req=true"/> <action application="export" data="execute_on_answer=record_session {}"/> <action application="set" data="sip_h_Diversion="{}" <sip: {}@{}>;reason=unconditional;"/> <action application="bridge" data="sofia/gateway/{}/{}"/> </condition> </extension>""".format(self.phone, kill_quotes(self.phone[1:], 'int'), '${caller_id_number}', '${caller_id_number}', '${us-ring}', '$${hold_music}', '$${base_dir}/${context}/${strftime(%Y-%m-%d)}/${destination_number}_${uuid}.wav', '${record_file_name}', '${diversion_phone}', '${diversion_phone}', '${diversion_domain}', self.gw, kill_quotes(self.dest, 'int')) fname = full_path('%s/redirect_%s.xml' % (self.FOLDER, self.id)) if check_path(fname): make_folder(self.FOLDER) with open(fname, 'w+') as f: f.write(extension) FreeswitchBackend(settings.FREESWITCH_URI).reloadxml()
def hershin(string, result): """1) Заменить в строке запятые на пробелы 2) Разбить по пробелам строку 3) Проверить не входит ли уже это слово в результат 4) Добавить в кортеж в нижнем регистре """ if not string: return result string = kill_quotes(string, 'strict_text', ' ') string = string.split() for item in string: if item: if item == '-': continue item = item.lower() if not item in result: result.append(item) return result
def save(self, *args, **kwargs): cid = kill_quotes(self.cid, 'int') if cid.startswith('7'): cid = '8%s' % (cid[1:], ) self.cid = cid super(FSUser, self).save(*args, **kwargs) if not self.is_active or not self.user or not self.passwd or not self.context or not self.cid: self.drop_extension() return extension = """ <include> <user id="{}"> <params> <param name="password" value="{}"/> </params> <variables> <variable name="toll_allow" value="domestic,international,local"/> <variable name="accountcode" value="{}"/> <variable name="user_context" value="{}"/> <variable name="effective_caller_id_name" value="{}"/> <variable name="effective_caller_id_number" value="{}"/> <variable name="outbound_caller_id_name" value="{}"/> <variable name="outbound_caller_id_number" value="{}"/> <variable name="callgroup" value="{}"/> </variables> </user> </include>""".format(self.user.username, self.passwd, self.user.username, self.context, self.user.username, self.user.username, self.cid, self.cid, self.callgroup) fname = full_path('%s/fs_user_%s.xml' % (self.FOLDER, self.id)) if check_path(fname): make_folder(self.FOLDER) with open(fname, 'w+') as f: f.write(extension) FreeswitchBackend(settings.FREESWITCH_URI).reloadxml()
def analyze_vik(sheet, titul: str, path: str): """Разбираем заибучее ВИК заключение, это первый лист в экселевском файле :param sheet: лист эксельки :param titul: экземпляр Titul :param path: путь до файла (для отладки) """ # Не всегда в титуле есть код титула, # может быть просто название, например, # Эстакада трубопроводов # Может вообще не быть названия титула titul_description = sheet['F6'].value or sheet['G6'].value titul_name = None if titul_description: if not 'У' in titul_description: titul_name = sheet['I6'].value else: titul_name = 'У%s' % titul_description.split('У')[1] titul_description = titul_description.split('У')[0] # -------------------------------------- # Захерачиваем описание титулу, # если не совпало имя титула, то алертим # -------------------------------------- if titul_name: titul_name = titul_name.strip() if titul_name != titul.name: pass #logger.info('TITUL HAS INCORRECT NAME %s vs %s' % (titul.name, titul_name)) #return # --------------------------------------- # Определяем описание титула накопительно # --------------------------------------- analyze_titul_description(titul, titul_description) # ----------------------------------- # Определяем шифр титула накопительно # ----------------------------------- titul_code = sheet['H7'].value or sheet['I7'].value analyze_titul_code(titul, titul_code) # ---------------- # Определяем линию # ---------------- line_str = sheet['A8'].value or sheet['B8'].value or sheet['A7'].value if not line_str: logger.info('--- LINE ABSENT %s---' % path) return line_str = line_str.replace('Линия', '').strip() line_str = line_str.replace('0 H', '0H') line_str = line_str.replace(' ', ' ') try: line_str = replace_rus2eng(line_str) except Exception as e: logger.info(e) return line = Line.objects.filter(name=line_str, titul=titul).first() if not line: logger.info('--- LINE NOT FOUND %s ---' % line_str) # Создаем линию, если название адекватное if len(line_str) < 5: return line = Line.objects.create(name=line_str, titul=titul) # ------------------- # Находим дату сварки # ------------------- request_control_date = get_welding_date(sheet['G11'].value) if not request_control_date: request_control_date = get_welding_date(sheet['H11'].value) if not request_control_date: request_control_date = get_welding_date(sheet['G10'].value) if not request_control_date: logger.info('--- DATE INCORRENT %s ---' % path) # -------------------------------- # Находим толщину стенки и диаметр # -------------------------------- side_thickness = diameter = None size_row_letter = 'I' is_completed_row = (sheet['I16'].value and sheet['I16'].value.strip() == 'выполнен') or (sheet['I14'].value and sheet['I14'].value.strip() == 'выполнен') if not sheet['A1'].value or is_completed_row: size_row_letter = 'J' size = None for i in (16, 17, 18): size_row_number = i size_row_value = sheet['%s%s' % (size_row_letter, size_row_number)].value if not size_row_value: continue #print('=', size_row_value) size = get_size(size_row_value) if size: break if not size: logger.info('--- SIDE_THICKNESS or DIAMETER NOT FOUND %s, %s ---' % (size_row_number, path)) else: diameter, side_thickness = size # ------------------------ # Находим номера стыков # У пидорасов на ВИК стыки # разделены точкой, # а на РК слешем # ------------------------ joint_row_letter = 'B' if not sheet['A1'].value: joint_row_letter = 'C' joints_str = sheet['%s%s' % (joint_row_letter, size_row_number)].value if not joints_str: logger.info('--- JOINTS NOT FOUND %s, %s ---' % (size, path)) return # Если есть говносмещение - мы найдем ячейку с № # вместо номеров стыков if joints_str == '№': if joint_row_letter == 'B': joint_row_letter = 'C' joints_str = sheet['%s%s' % (joint_row_letter, size_row_number)].value joints_str = '%s' % joints_str joints_arr = joints_str.split(',') # ---------------------------- # Находим строчку с материалом # и типом сварных соединений # ---------------------------- material = welding_conn_view = None material_str = None material_row_letter = 'A' if not sheet['A1'].value or (sheet['A18'].value is None and sheet['A19'].value is None and sheet['A20'].value is None and sheet['A21'].value is None): material_row_letter = 'B' material_q = ('Тип сварных соединений', 'материал') for i in (18, 19, 20, 21): material_row_number = i value = sheet['%s%s' % (material_row_letter, material_row_number)].value if not value: continue if material_q[0] in value and material_q[1] in value: material_str = value break if not material_str: logger.info('--- MATERIAL NOT FOUND %s ---' % path) else: material, welding_conn_view = get_material(material_str) if not material or not welding_conn_view: logger.info('--- MATERIAL NOT FOUND %s ---' % path) # ----------------- # Поиск типа сварки # ----------------- welding_type = None welding_type_row_letter = material_row_letter welding_type_row_number = material_row_number + 1 welding_type_str = sheet['%s%s' % ( welding_type_row_letter, welding_type_row_number )].value if not welding_type_str: logger.info('--- WELDING_TYPE NOT FOUND %s ---' % path) else: welding_type = get_welding_type(welding_type_str) if not welding_type: logger.info('--- WELDING_TYPE NOT FOUND %s ---' % path) # ------------- # Ищем сварщика # ------------- welders = [] welder_row_number = welding_type_row_number + 1 for letter in ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'): welders_str = sheet['%s%s' % ( letter, welder_row_number, )].value if not welders_str: continue welders += get_welders(welders_str) # Следующую строчку ищем тоже welder_row_number += 1 if not welders: for letter in ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'): welders_str = sheet['%s%s' % ( letter, welder_row_number, )].value if not welders_str: continue welders += get_welders(welders_str) if not welders: logger.info('--- WELDERS NOT FOUND %s ---' % path) # --------------------- # Ищем дефектоскопистов # Контроль выполнил: # --------------------- defectoscopists = [] letters = ('G', 'H', 'I', 'J') for letter in letters: for number in range(36, 46): adr = '%s%s' % (letter, number) value = sheet[adr].value if not value: continue defectoscopists += get_defectoscopists(value) if not defectoscopists: logger.info('--- DEFECTOSCOPISTS NOT FOUND %s ---' % path) for joint_str in joints_arr: joint_str = joint_str.replace('.', '/').replace('\\', '/').strip() if not joint_str: continue # Если нет цифр в номере стыка, тогда не создаем digits = kill_quotes(joint_str, 'int') if not digits: logger.info('--- BAD JOINT %s, %s ---' % (joint_str, path)) continue joint = Joint.objects.filter(line=line, name=joint_str).first() if not joint: logger.info('--- JOINT NOT FOUND %s, %s ---' % (joint_str, line.name)) # Ну создаем, блеать, раз линия найдена joint = Joint.objects.create(line=line, name=joint_str) # Стык найден - надо найти заключение, # если нету - создать или обновить welding_joints = WeldingJoint.objects.filter(joint=joint) if len(welding_joints) > 1: logger.info('--- MORE THAN 1 WeldingJoint %s' % joint) return if welding_joints: welding_joint = welding_joints[0] else: welding_joint = WeldingJoint(joint=joint) welding_joint.state = 3 welding_joint.diameter = diameter welding_joint.side_thickness = side_thickness welding_joint.request_control_date = request_control_date welding_joint.material = material welding_joint.welding_conn_view = welding_conn_view welding_joint.welding_type = welding_type welding_joint.save() for i, welder in enumerate(welders): if i > 3: break analog = JointWelder.objects.filter( welder=welder, welding_joint=welding_joint, ) if not analog: JointWelder.objects.create( welder=welder, welding_joint=welding_joint, position=i + 1, ) joint_conclusion = JointConclusion.objects.filter(welding_joint=welding_joint).first() if not joint_conclusion: joint_conclusion = JointConclusion(welding_joint=welding_joint) joint_conclusion.date = welding_joint.request_control_date joint_conclusion.vik_active = True joint_conclusion.vik_state = 1 if defectoscopists: joint_conclusion.vik_controller = defectoscopists[0] if len(defectoscopists) > 1: joint_conclusion.vik_director = defectoscopists[1] joint_conclusion.save()
def save(self, *args, **kwargs): if self.phone: phone = kill_quotes(self.phone, 'int') self.phone = phone super(Shopper, self).save(*args, **kwargs)
def save(self, *args, **kwargs): if self.phone: self.phone = kill_quotes(self.phone, 'int') super(customUser, self).save(*args, **kwargs)
def save(self, *args, **kwargs): """Сохранение""" if self.phone: self.phone = kill_quotes(self.phone, 'int') super(SMSPhone, self).save(*args, **kwargs)
def parse_css_line(self, css: str, line: str): """Парсинг css строчки в файле css :param css: путь к css файлу :param line: строка в css файле""" # ----------------------------------- # SUPPORT for @import "css/main.css"; # ----------------------------------- matches_import = rega_import.search(line) if matches_import: old_path = matches_import.group(1) if old_path.endswith('.css'): # ------------------------------------------------------------- # Тут ремарка скажем @import url("../medica-parent/style.css"); # тогда надо брать путь относительно пути текущего css файла, # а не базового => смотрим в функцию findpath # css => http://demo.themefuse.com/medica-child/style.css?v=1 # Видно, что надо отбросить финальный элемент пути # ------------------------------------------------------------- if css.endswith('.css') and '/' in css: css = os.path.split(css)[0] temp_css_file = self.findpath(css, kill_quotes(old_path, 'quotes')) self.css_files.append(temp_css_file) temp_css_name = os.path.split(temp_css_file)[1] line = line.replace(old_path, '../css/%s' % temp_css_name) matches_img = rega_img.findall(line) for match_img in matches_img: old_path = match_img if old_path.endswith('.css"'): # SUPPORT FOR @import url(../css/xxx.css); temp_css_file = self.findpath(css, kill_quotes(old_path, 'quotes')) css_files.append(temp_css_file) temp_css_name = os.path.split(temp_css_file)[1] line = line.replace(old_path, '../css/%s' % temp_css_name) continue # ----------------------- # Бывает, что svg попался # ----------------------- if 'data:' in match_img: continue # ---------------------------------- # Какие-то долбаебы в картинку якорь # и бывает, что это все что там есть # ---------------------------------- if '#' in old_path: old_path = old_path.split('#')[0].strip() if not old_path: continue img = self.findpath(css, kill_quotes(old_path, 'quotes')) img_name = os.path.split(img)[1] # Меняем путь в css img_folder = os.path.split(img)[0] line = line.replace(old_path, '../img/%s' % img_name) # Тащим картинку contents = self.grab_file(img, False) if not contents: continue img_file_path = os.path.join(self.img_path, img_name) # --------------------------- # Фикс на имя с ? параметрами # --------------------------- img_file_path = self.clean_path(img_file_path) # ПРОВЕРКА НА ДУБЛИ if not check_path(img_file_path): if not img in self.img_repeated: self.z += 1 img_file_path = img_file_path + str(self.z) if not img in self.img_repeated: self.img_repeated.append(img) with open_file(img_file_path, 'wb+') as f: f.write(contents) return line
def send_sms_helper(request): """Вспомогательная функция, чтобы отправить sms 1) достаем из spamcha телефоны для рассылки, смотрим по лимитам кто может отправить смс, следим за балансировкой - кто сколько отправил 2) у нас должен работать sms_hub.py на порту (5009) подключаемся в него и отправляем смс на телефон """ result = {} method = request.GET if request.method == 'GET' else request.POST text = method.get('text') phone = method.get('phone') token = method.get('token') if not token == settings.SMS_HUB_TOKEN: result['error'] = 'Неправильный токен' return result if not phone or not text: result['error'] = 'Телефон или сообщение отсутствует' return result phone = kill_quotes(phone, 'int') if len(phone) != 11: result['error'] = 'Телефон должен быть из 11 цифр' return result receiver_number = '8%s' % phone[1:] if not receiver_number.startswith('89'): result['error'] = 'Телефон не должен быть городским (начинаться с 89)' return result # Вариант узнать какие телефоны на связи, только через phones_from_cache = get_phones_from_cache() # -------------------------------------------- # Телефоны на связи, если дата меньше сегодня, # нужно просто пересохранять, # чтобы обновился счетчик отправленных смсин # -------------------------------------------- now = datetime.datetime.today() today = datetime.datetime(now.year, now.month, now.day, 0, 30, 0) refresh_query = SMSPhone.objects.filter(updated__lt=today) for_refresh = refresh_query.aggregate(Count('id'))['id__count'] if for_refresh: for item in refresh_query: item.sent = 0 item.save() # Находим телефоны через которые можно отправить смс cond_list = [{'code__in': phones_from_cache}] phones = get_phones(cond_list=cond_list) if not phones: result['error'] = 'Нет телефонов для отправки смс' return result candidate = phones[0] if not candidate['sent']: candidate['sent'] = 0 for phone in phones: if not phone['sent']: phone['sent'] = 0 if phone['sent'] < candidate['sent']: candidate = phone # Отправка в кэш-очередь смсины rediska = redis.Redis() cache_key = '%s_%s' % (settings.SMS_HUB_TOKEN, candidate['code']) queue = rediska.get(cache_key) if queue: queue = json.loads(queue) else: queue = [] queue.append({'phone': receiver_number, 'text': text}) rediska.set(cache_key, json.dumps(queue)) # Накидываем кол-во отправленных смсин candidate['sent'] += get_sms_volume(text) SMSPhone.objects.filter(pk=candidate['id']).update(sent=candidate['sent']) result['success'] = 1 return result