Browse Source

Merge branch 'unstable' of blezz-tech/sharix-open-webservice-running into unstable

+ 12 - 3
handlers/classes/Ticket.py

@@ -1,10 +1,12 @@
 from datetime import datetime
+from config import DEFAULT_INTERVAL_ATTEMPTS
 
 class Ticket(object):
     def __init__(
             self,
             id,
             status,
+            ticket_list,
             ticket_type,
             title,
             created_at,
@@ -13,10 +15,13 @@ class Ticket(object):
             priority,
             created_by,
             assigned_to=None,
-            note=None
+            note=None,
+
+            interval_attempts: int = DEFAULT_INTERVAL_ATTEMPTS
     ):
         self.id = id
         self.status = status
+        self.ticket_list = ticket_list
         self.ticket_type = ticket_type
         self.title = title
         self.created_at = created_at
@@ -27,10 +32,13 @@ class Ticket(object):
         self.assigned_to = assigned_to
         self.note = note
 
+        self.interval_attempts = interval_attempts
+
     def __str__(self):
         return "{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}".format(
             self.id,
             self.status,
+            self.ticket_list,
             self.ticket_type,
             self.title,
             self.created_at,
@@ -41,11 +49,12 @@ class Ticket(object):
             self.assigned_to
         )
 
-    # Method to convert the object to a dictionary, if needed for JSON responses or serialization
     def to_dict(self):
+        """ Method to convert the object to a dictionary, if needed for JSON responses or serialization """
         return {
             "id": self.id,
             "status": self.status,
+            "ticket_list": self.ticket_list,
             "ticket_type": self.ticket_type,
             "title": self.title,
             "created_at": self.created_at,
@@ -59,7 +68,7 @@ class Ticket(object):
 
     def update_status(self, new_status):
         self.status = new_status
-        self.updated_at = datetime.utcnow().isoformat()
+        self.updated_at = datetime.now().isoformat()
 
     def assign_to(self, user_id):
         self.assigned_to = user_id

+ 2 - 0
handlers/config.py

@@ -33,3 +33,5 @@ API_URL = "https://testopen.sharix-app.org/"
 
 # LOG_DIR = "/var/log/"
 LOG_DIR = "./log/"
+
+DEFAULT_INTERVAL_ATTEMPTS = 10

+ 202 - 0
handlers/handlers/open_access_request_pending.py

@@ -0,0 +1,202 @@
+import hashlib
+from datetime import datetime
+import config
+import logging
+from EchoBot import JabberBot
+from slixmpp.stanza import Message
+import jsonAndRequest as jsreq
+from time import sleep
+from lib import filter_interval_tickets
+from classes.Ticket import Ticket
+from typing import List
+
+botname = "open_access_request_pending"
+operating_status = 320
+
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+bot = JabberBot(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = [
+    "test@ej.sharix-app.org",
+    "open_template_bot@ej.sharix-app.org"
+]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [
+    JID,
+    "open_st_request_declined@ej.sharix-app.org",
+    "open_service_request_forcemajeure@ej.sharix-app.org"
+]
+
+INTERVAL_ATTEMPTS = 3
+# INTERVAL_TIME = 30 * 60  # 30 минут в секундах
+INTERVAL_TIME = 5 # Для проверки
+
+global tickets
+tickets: List[Ticket] 
+
+def message_handler(msg: Message):
+    """Обработчик входящих сообщений"""
+
+    if msg['type'] in ('chat', 'normal'):
+        text = msg['body']  # текст сообщения боту
+        sender = msg['from']  # отправитель сообщения
+
+        if (str(sender).split("/")[0]) in listen_to:
+            if text is not None:
+                logging.info(f"Сообщение получено")
+
+def start_handler():
+    """Событие запуска обработчика."""
+
+    logging.info(">>>>>  %s  |---| %s  <<<<<", JID, PASSWORD)
+
+    global tickets
+    tickets = get_fake_data()
+
+    while(True):
+        # TODO: Придумать более надёжный механизм парарельной обработки тикетов
+        # А также более надёжный механизм удаления тикетов из массива
+        if tickets:
+            for ticket in tickets:
+                ticket.interval_attempts -= 1
+                if ticket.interval_attempts <= 0:
+                    interval_attempts_unlimited(ticket)
+                else:
+                    processing(ticket)
+            tickets = filter_interval_tickets(tickets)
+        
+        logging.debug(tickets)
+        logging.debug("Sleep")
+        sleep(INTERVAL_TIME)
+
+
+# START CUSTOM FUNCTIONS
+
+def interval_attempts_unlimited(ticket):
+    logging.debug(f"Лимит попыток обработки тикета {ticket.id} исчерпан")
+    
+    # db.changestatus
+    # bot.send_message(JID, f"Сообщение отправлено {JID}: {datetime.now()}")
+    # bot message:
+    # {
+    #   "action": "add_ticket"
+    #   "ticket_id":      0
+    #   "ticket_list_id": 0
+    # }
+
+
+def processing(ticket):
+    logging.debug(f"Начало обработки тикета {ticket.id}")
+
+    # Do something
+
+    logging.debug(f"Конец обработки тикета {ticket.id}")
+
+
+def get_fake_data() -> List[Ticket]:
+    return [
+        Ticket(0, "t", 0,0,0,0,0,0,0,0,0,"note",INTERVAL_ATTEMPTS - 2),
+        Ticket(1, "t", 0,1,0,0,0,0,0,0,0,"note",INTERVAL_ATTEMPTS + 1),
+        Ticket(2, "t", 0,2,0,0,0,0,0,0,0,"note",INTERVAL_ATTEMPTS - 1),
+        Ticket(3, "t", 0,3,0,0,0,0,0,0,0,"note",INTERVAL_ATTEMPTS + 2),
+        Ticket(4, "t", 0,4,0,0,0,0,0,0,0,"note",INTERVAL_ATTEMPTS + 1),
+        Ticket(5, "t", 0,5,0,0,0,0,0,0,0,"note",INTERVAL_ATTEMPTS - 1),
+    ]
+
+# def get_token():
+#     return jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/auth/token/login/")
+
+# def set_tasklist(token):
+#     global tasklist
+
+#     tasklist = []
+#     tasklist = jsreq.requestGetList(token, config.API_URL + "/tickets/api/tickets/?list_id=10")
+
+
+# END CUSTOM FUNCTIONS
+
+
+#  ---------------------------------------
+#  ---------------------------------------
+#  ---------------------------------------
+#  ---------------------------------------
+#  ---------------------------------------
+
+
+# # обработчик входящих сообщений
+# def message_handler(conn, mess):
+#     text = mess.getBody()  # текст сообщения боту
+#     user = mess.getFrom()  # отправитель сообщения
+
+#     print(str(user).split("/")[0])
+#     if (str(user).split("/")[0]) in listen_to:
+#         print(text)
+#         print(mess)
+
+#         if text is not None:
+#             orderObj = jsreq.jsonToOrderTicket(text)
+#             print(orderObj)
+#             tasklist.append(orderObj)
+#             bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+# def open_access_request_pending_wait(period, localtask):
+#     bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+#     time.sleep(period)
+
+#     # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+#     localtask.title = localtask.title + "1"
+
+#     # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+#     bot.proceed_status(proceed_to[1], localtask)
+#     bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ перенаправлен\n")
+
+
+# def open_access_request_pending_process(localtask):
+#     bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+#     push_notifications(localtask)
+#     open_access_request_pending_wait(100, localtask)
+
+
+# # Пока не уверен
+# def push_notifications(localtask):
+#     # Отправка уведомлений
+#     # ...
+#     return True
+
+
+# def open_access_request_pending():
+#     while (len(tasklist)):
+#         localtask = tasklist.pop(0)
+#         bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+#         print("EACH TASKLIST", tasklist)
+
+#         if (localtask.status != operating_status):
+#             bot.proceed_status(proceed_to[-1], localtask)
+#             bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+#             continue
+
+#         # if (localtask.title!="10"):
+#         #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+#         #     t1.start()
+
+#         # if (localtask.title=="101"):
+#         #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+#         #     t1.start()
+
+#         t1 = threading.Thread(target=open_access_request_pending_process, args=(localtask))
+#         t1.start()
+
+#         # если никакие обработчики не подошли - отправляем обратно в очередь
+#         bot.proceed_status(proceed_to[0], localtask)
+#         print("Заказ возвращен в очередь\n")
+#         print(tasklist)
+
+
+# # пустой список заказов

+ 5 - 0
handlers/lib.py

@@ -0,0 +1,5 @@
+
+def filter_interval_tickets(tickets):
+    """ Очистка тикетов, у которых закончились попытки """
+    return list(filter(lambda ticket: ticket.interval_attempts > 0, tickets))
+

+ 7 - 0
handlers/requirements.txt

@@ -1,7 +1,14 @@
+aiodns==3.2.0
 certifi==2022.12.7
+cffi==1.17.1
 charset-normalizer==3.1.0
 idna==3.4
+pyasn1==0.6.1
+pyasn1_modules==0.4.1
+pycares==4.5.0
+pycparser==2.22
 requests==2.29.0
 six==1.16.0
+slixmpp==1.9.1
 urllib3==1.26.15
 xmpppy==0.7.1