Сохранить разговор в чате в поле json - PullRequest
0 голосов
/ 27 февраля 2020

Я создал чат-бота. Я хочу сохранить беседу в JSONField ('question1': 'answer1', 'question2': 'answer2' ...), когда канал отключается, или пользователь завершает чат или через 5 минут бездействия. Я использую django каналы. Все работает, но я не знаю, как сохранить разговор после окончания чата.

Моя модель для сохранения разговора:

class ChatHistory(models.Model):
    question = models.TextField(null=True) # not required. added just to test
    answer = models.TextField(null=True) # not required. added just to test
    conversation = JSONField()
    customer = models.ForeignKey(Customer, on_delete=models.DO_NOTHING, related_name='customer_chat')
    date_time = models.DateTimeField(auto_now_add=True)
    talker = models.ForeignKey(User, on_delete=models.DO_NOTHING, related_name='user_chat', null=True)

потребителей. py

class ChatConsumer(WebsocketConsumer):
    def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['secret_key']
        self.user_email = self.scope['url_route']['kwargs']['user_email']
        self.room_group_name = 'chat_%s' % self.room_name + self.user_email

        # Join room group
        async_to_sync(self.channel_layer.group_add)(
            self.room_group_name,
            self.channel_name
        )

        self.accept()

    def disconnect(self, close_code):
        async_to_sync(self.channel_layer.group_discard)(
            self.room_group_name,
            self.channel_name
        )

    # Receive message from WebSocket
    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        dir_name = text_data_json['dir_name']
        reply = bot_reply(message, dir_name)
        secret_key = text_data_json['secret_key']
        u_id = text_data_json['user_id']
        customer = Customer.objects.get(u_field=u_id)
        company = Company.objects.get(secret_key=secret_key)
        conversation = {} 
        # I tried to save every question/answer when talker asked and bot responded. Please igore fields.

        # ChatHistory.objects.create(
        #     company=company,
        #     
        #     question=message,
        #     answer=reply,
        #     
        #     talker=company.company_name
        # )
        # Send message to room group
        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': message,
                'reply': reply
            }
        )

    # Receive message from room group
    def chat_message(self, event):
        message = event['message']
        reply = event['reply']

        # Send message to WebSocket
        self.send(text_data=json.dumps({
            'message': message,
            'reply': reply
        }))

При необходимости. Это шаблон. Я удалил несколько строк, чтобы сделать его короче. Это работает нормально.

var roomName = "{{ secret_key|escapejs }}";
var userEmail = "{{ u_id|escapejs }}";

var chatSocket = new ReconnectingWebSocket(
    'ws://' + window.location.host +
    '/ws/chat/' + roomName +'/'+ userEmail + '/');

chatSocket.onmessage = function(e) {
    var data = JSON.parse(e.data);
    var message = data['message'];
    var author = data['author'];
    var name = data['name']
    var reply = data['reply']
    if (reply == 'not found 404') {
        var rep = 404
        reply = 'System can not answer this question. Would you like to talk to our customer care service.'
    }

    $(".messages").animate({
        scrollTop: $(document).height()
    }, "fast");


};


chatSocket.onclose = function(e) {
    console.error('Chat socket closed unexpectedly');
};



document.querySelector('#chat-message-submit').onclick = function(e) {

    $(".messages").animate({
        scrollTop: $(document).height()
    }, "fast");
    chatSocket.send(JSON.stringify({
        'message': message,
        'command': 'new_message',
        'dir_name': '{{ dir_name }}',
        'secret_key': '{{ secret_key }}',
        'user_id': '{{ u_id }}',
    }));

    messageInputDom.value = '';
};

Редактировать

Модель для сохранения чата

class ChatHistory(models.Model):
    TYPE = (
        ('bot_chat', 'bot_chat'),
        ('user_chat', 'user_chat')
    )
    company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='company_chat')
    customer = models.ForeignKey(Customer, on_delete=models.DO_NOTHING, related_name='customer_chat')
    date_time = models.DateTimeField(auto_now_add=True)

Модель для сохранения сообщений в чате

class Conversation(models.Model):
    history = models.ForeignKey(ChatHistory, on_delete=models.CASCADE, related_name='chat_history')
    question = models.TextField(null=True)
    answer = models.TextField(null=True)
    time = models.TimeField(auto_now_add=True)

Я пробовал это. Когда канал подключается, он создает экземпляр ChatHistory и сохраняет его, и каждый раз, когда пользователь говорит, я сохраняю сообщение (Q и A) в Conversation с экземпляром ChatHistory.

1 Ответ

0 голосов
/ 03 марта 2020

Я решил проблему. Я не знаю, является ли это лучшим решением, но оно работает. Я сделал это в три шага.

  1. Когда канал подключен, создайте ChatHistory экземпляр с save_status = False.
  2. Когда пользователь говорит, я сохраняю сообщение в Conversation Модель с Экземпляр ChatHistory (save_status = False и customer = "current_customer")
  3. Когда канал отключен, значение change_status = True.

Это код.

consumer.py

def create_chat_history(self, data):
    user_id = data['user_id']
    secret_key = data['secret_key']
    customer = Customer.objects.get(u_field=user_id)
    company = Company.objects.get(secret_key=secret_key)
    talker = User.objects.filter(Q(company__secret_key=self.room_name) & Q(role='admin'))[0]
    chat_hist = ChatHistory.objects.create(
        company=company,
        chat_type='bot_chat',
        customer=customer,
        talker=talker
    )

def add_new_message(self, data):
    user_id = data['user_id']
    secret_key = data['secret_key']
    customer = Customer.objects.get(u_field=user_id)
    company = Company.objects.get(secret_key=secret_key)
    message = data['message']
    dir_name = data['dir_name']
    reply = bot_reply(message, dir_name)
    qry_filter = Q(saved_status=False) & Q(customer=customer) & Q(company=company)
    Conversation.objects.create(
        history=ChatHistory.objects.filter(qry_filter)[0],
        question=message,
        answer=reply,
    )
    return self.send_message(message, reply)

def add_history(self, data):
    user_id = data['user_id']
    secret_key = data['secret_key']
    customer = Customer.objects.get(u_field=user_id)
    company = Company.objects.get(secret_key=secret_key)
    qry_filter = Q(save_status=False) & Q(customer=customer) & Q(company=company)
    ChatHistory.objects.filter(qry_filter).update(saved_status=True)

process = {
    'open_channel': create_chat_history,
    'new_message': add_new_message,
    'close_channel': add_history,
}

def connect(self):
    self.room_name = self.scope['url_route']['kwargs']['secret_key']
    self.user_email = self.scope['url_route']['kwargs']['user_email']
    self.room_group_name = 'chat_%s' % self.room_name + self.user_email
    async_to_sync(self.channel_layer.group_add)(
        self.room_group_name,
        self.channel_name
    )

    self.accept()

def disconnect(self, close_code):
    async_to_sync(self.channel_layer.group_discard)(
        self.room_group_name,
        self.channel_name
    )

# Receive message from WebSocket
def receive(self, text_data):
    text_data_json = json.loads(text_data)
    self.process[text_data_json['process']](self, text_data_json)

def send_message(self, message, reply):
    # Send message to room group
    async_to_sync(self.channel_layer.group_send)(
        self.room_group_name,
        {
            'type': 'chat_message',
            'message': message,
            'reply': reply
        }
    )

# Receive message from room group
def chat_message(self, event):
    message = event['message']
    reply = event['reply']

    # Send message to WebSocket
    self.send(text_data=json.dumps({
        'message': message,
        'reply': reply
    }))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...