Skip to content

Commit

Permalink
update chat socket handler
Browse files Browse the repository at this point in the history
  • Loading branch information
wuttinanhi committed Oct 31, 2022
1 parent ff85e20 commit 5d797ee
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 159 deletions.
48 changes: 42 additions & 6 deletions chat/handler.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
"""
chat socket handler
"""

from typing import Any, Dict

from auth.service import AuthService
from flask import request
from flask_socketio import Namespace, emit
from pagination.pagination import int_to_sort
from user.model import User
from user.service import UserService
from util.validate_request import validate_object
from werkzeug.exceptions import NotFound, Unauthorized

from chat.service import ChatService
from chat.service import ChatHistoryPaginationOptions, ChatService


class ChatMapper(Namespace):
Expand Down Expand Up @@ -75,16 +80,47 @@ def on_login(self, data):
ChatHandler.register(user, sid)
return user.json()

# retrieve chat history
# request data json:
# {
# "jwt_token": "USER-JWT-TOKEN",
# "to_user": 1,
# "page": 1,
# "limit": 20,
# "sort": 1,
# "order_by": "send_date",
# "search": null,
# }
def on_chat_list(self, data):
user = ChatHandler.auth_user(data)
to_user_id = data["to_user"]

from_user = UserService.find_by_id(user.id)
to_user = UserService.find_by_id(to_user_id)
opts_dict: Dict[Any, Any] = {}
opts_dict["page"] = int(data["page"])
opts_dict["limit"] = int(data["limit"])
opts_dict["sort"] = int(data["sort"])
opts_dict["order_by"] = data["order_by"]
opts_dict["from_user_id"] = int(user.id)
opts_dict["to_user_id"] = int(data["to_user"])
if hasattr(data, "search"):
opts_dict["search"] = data["search"]

vobj = validate_object(ChatHistoryPaginationOptions, opts_dict)

opts = ChatHistoryPaginationOptions()
opts.page = int(vobj.page)
opts.limit = int(vobj.limit)
opts.sort = int_to_sort(int(vobj.sort))
opts.order_by = vobj.order_by
opts.from_user_id = int(vobj.from_user_id)
opts.to_user_id = int(vobj.to_user_id)
if hasattr(vobj, "search"):
opts.search = vobj.search
else:
opts.search = ""

chat_history = ChatService.list_chat_history(opts)

response = []
chat_history = ChatService.list_chat_history(from_user, to_user)

for chat in chat_history:
response.append(chat.json())

Expand Down
34 changes: 31 additions & 3 deletions pagination/pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ class PaginationOptions(Schema):
)


def int_to_sort(i: int):
if i == 0:
return PaginationSortOptions.ASC
if i == 1:
return PaginationSortOptions.DESC
raise BadRequest(f"Invalid pagination sort integer: {i}")


def create_order_by(model, key: str, sort: PaginationSortOptions):
if hasattr(model, key):
result = model.__dict__.get(key)
Expand All @@ -40,9 +48,7 @@ def create_order_by(model, key: str, sort: PaginationSortOptions):
raise BadRequest(f"Invalid order by key!: {key}")


def create_pagination_options_from_request(request: Request):
data = validate_request(PaginationOptions, request, "GET")

def create_pagination_options_from_schema(data):
options = PaginationOptions()
options.page = int(data.page)
options.limit = int(data.limit)
Expand All @@ -60,6 +66,28 @@ def create_pagination_options_from_request(request: Request):

return options

def create_pagination_options_from_dict(data):
options = PaginationOptions()
options.page = int(data["page"])
options.limit = int(data["limit"])
options.order_by = data["order_by"]

if hasattr(data, "search"):
options.search = data["search"]
else:
options.search = ""

if int(data["sort"]) == 1:
options.sort = PaginationSortOptions.DESC
else:
options.sort = PaginationSortOptions.ASC

return options

def create_pagination_options_from_request(request: Request):
data = validate_request(PaginationOptions, request, "GET")
options = create_pagination_options_from_schema(data)
return options

def create_pagination_options(
page=1, limit=10, sort=PaginationSortOptions.ASC, order_by="id"
Expand Down
170 changes: 170 additions & 0 deletions static/chat.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Socket-IO test</title>
</head>

<body class="p-5">
<h1>Chat Test:</h1>
<div class="flex w-full">
<div class="basis-6/12 w-full">
<label for="">JWT Token:</label>
<input type="text" name="jwt_token" id="jwt_token" class="w-1/3">
<br><br>
<label for="">To User:</label>
<input type="text" name="to_user" id="to_user" value="3" class="w-1/3">
<br><br>
<button onclick="loadChat()">getChat</button>
</div>
<div class="basis-6/12 w-full">
<div id="chat_box" class="w-full overflow-y-scroll h-[30vw] max-h-[30vw] border-2 bg-gray-100">
<div id="chat_history" class="w-full"></div>
</div>
<br><br>
<div class="flex w-full">
<input type="text" name="chat_input" id="chat_input" class="w-full">
<button onclick="sendChat()">sendChat</button>
</div>
</div>
</div>
</body>
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = { theme: { extend: {} } }
</script>
<style type="text/tailwindcss"> /* @layer utilities {
.content-auto {
content-visibility: auto;
}
} */

input, button {
@apply border-2;
}
</style>
<script src="https://cdn.socket.io/4.5.0/socket.io.min.js"
integrity="sha384-7EyYLQZgWBi67fBtVxw60/OWl1kjsfrPFcaU0pp0nAh+i8FD068QogUvg85Ewy1k"
crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf-8">
var socket = io();
var USER = null;

function getJwtToken() {
return document.querySelector("#jwt_token").value;
}

function getToUser() {
return document.querySelector("#to_user").value;
}

function getChatInput() {
return document.querySelector("#chat_input").value;
}

function loginUser() {
socket.emit("login", { jwt_token: getJwtToken() }, (response) => {
console.log("Logged in!");
USER = response;
})
}

function clearChat() {
var chat_history_element = document.querySelector('#chat_history');
chat_history_element.innerHTML = "";
}

function appendChat(from, msg, left = true) {
var div = document.createElement('div');
div.innerHTML += `
<div class="mx-3 my-2">
<div class="border-2 w-fit h-fit ${left === true ? "mr" : "ml"}-auto p-3 rounded-lg bg-blue-300 text-white">
<p>${from}</p>
<p class="mt-2">${msg}</p>
</div>
</div>
`

var chat_history_element = document.querySelector('#chat_history');
chat_history_element.appendChild(div);
}

function scrollChatboxToBottom() {
setTimeout(() => {
const chatboxElement = document.getElementById("chat_box");
chatboxElement.scrollTop = chatboxElement.scrollHeight;
}, 300);
}

function renderChat(chat) {
if (chat.chat_from_system === true) {
appendChat("SYSTEM", chat.chat_message, true);
} else {
if (USER.id === chat.chat_from_user_id) {
appendChat(chat.chat_from_user_id, chat.chat_message, false);
} else {
appendChat(chat.chat_from_user_id, chat.chat_message, true);
}
}
}

function loadChat() {
clearChat()

loginUser()

setTimeout(() => {
socket.emit("chat_list", {
"jwt_token": getJwtToken(),
"to_user": getToUser(),
"page": 1,
"limit": 20,
"sort": 1,
"order_by": "send_date",
"search": "1"
},
(response) => {
if (!response) return console.log("chat_list return null!");

const chat_history = response;
// console.table(chat_history)

clearChat();

chat_history.forEach((chat) => {
renderChat(chat)
// appendChat(`<li>${chat.chat_from_user_id} => ${chat.chat_to_user_id} : ${chat.chat_message}</li>`);
})

scrollChatboxToBottom()
});
}, 500);
}

function sendChat() {
const chatMessage = getChatInput();
socket.emit("chat_send", { jwt_token: getJwtToken(), to_user: getToUser(), message: chatMessage }, (response) => {
console.log("chat_send", response)
})
}

socket.on('connect', function () {
console.log("Connected!");
});

socket.on('chat_receive', (response) => {
console.log(response)
const chat = response
renderChat(chat)
scrollChatboxToBottom()
});

socket.on('exception', (response) => {
console.error(response);
});
</script>

</html>
Loading

0 comments on commit 5d797ee

Please sign in to comment.