add chat
This commit is contained in:
parent
f19e002fc5
commit
adf6ad863c
|
@ -13,3 +13,6 @@ python main
|
|||
### zero downtime restarts:
|
||||
- launch new burgercat server
|
||||
- close previous server
|
||||
|
||||
### contribution guidelines:
|
||||
- please check that your PR does not break anything
|
121
main
121
main
|
@ -82,6 +82,16 @@ def get_comments(id):
|
|||
return post
|
||||
|
||||
|
||||
def get_messages(chatroomid):
|
||||
conn = get_db_connection()
|
||||
post = conn.execute("SELECT * FROM chatmessages WHERE chatroom_id = ? ORDER BY created DESC;",
|
||||
(chatroomid,)).fetchall()
|
||||
conn.close()
|
||||
if post is None:
|
||||
return "error"
|
||||
return post
|
||||
|
||||
|
||||
app.jinja_env.globals.update(getComments=get_comments)
|
||||
|
||||
def get_post(id):
|
||||
|
@ -138,6 +148,109 @@ def main():
|
|||
else:
|
||||
return render_template("main.html", posts=posts)
|
||||
|
||||
@app.route("/chat", methods=("GET", "POST"))
|
||||
def chat():
|
||||
usersession = request.cookies.get("session_DO_NOT_SHARE")
|
||||
if usersession:
|
||||
userCookie = get_session(usersession)
|
||||
user = get_user(userCookie["id"])
|
||||
return render_template("chat.html", userdata=user)
|
||||
else:
|
||||
return render_template("chat.html")
|
||||
|
||||
@app.route("/api/chat/listrooms")
|
||||
def chatlistrooms():
|
||||
conn = get_db_connection()
|
||||
rooms = conn.execute("SELECT * FROM chatrooms ORDER BY roomname ASC;").fetchall()
|
||||
conn.close()
|
||||
|
||||
template = []
|
||||
|
||||
for room in rooms:
|
||||
roomtemplate = {
|
||||
"id": room["id"],
|
||||
"name": room["roomname"]
|
||||
}
|
||||
template.append(roomtemplate)
|
||||
|
||||
return(template), 200
|
||||
|
||||
@app.route("/api/chat/getmessages/<roomid>")
|
||||
def chatget(roomid):
|
||||
messages = get_messages(roomid)
|
||||
|
||||
template = []
|
||||
|
||||
for message in messages:
|
||||
creatorid = message["creator"]
|
||||
|
||||
creatortemplate = {
|
||||
"id": message["creator"],
|
||||
"username": get_user(creatorid)["username"]
|
||||
}
|
||||
|
||||
messagetemplate = {
|
||||
"id": message["id"],
|
||||
"content": message["content"],
|
||||
"creator": creatortemplate,
|
||||
"created": message["created"]
|
||||
}
|
||||
template.append(messagetemplate)
|
||||
|
||||
return(template), 200
|
||||
|
||||
burgerMessageUpdate = True
|
||||
burgerMessageCache = ""
|
||||
|
||||
@app.route("/api/chat/send/<roomid>", methods=("GET", "POST"))
|
||||
def chatsend(roomid):
|
||||
usersession = request.cookies.get("session_DO_NOT_SHARE")
|
||||
if usersession:
|
||||
if request.method == "POST":
|
||||
|
||||
data = request.get_json()
|
||||
content = data["content"]
|
||||
|
||||
print(content)
|
||||
print(roomid)
|
||||
|
||||
userCookie = get_session(usersession)
|
||||
user = get_user(userCookie["id"])
|
||||
|
||||
if not user["banned"] == "0":
|
||||
return {
|
||||
"error": "banned"
|
||||
}, 403
|
||||
|
||||
conn = get_db_connection()
|
||||
conn.execute("INSERT INTO chatmessages (content, chatroom_id, creator, created) VALUES (?, ?, ?, ?)",
|
||||
(content, roomid, userCookie["id"], str(time.time())))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
global burgerMessageCache
|
||||
global burgerMessageUpdate
|
||||
burgerMessageUpdate = True
|
||||
burgerMessageCache = user["username"] + ": " + content
|
||||
|
||||
return "success", 200
|
||||
|
||||
|
||||
@sock.route("/api/chat/listen")
|
||||
def chatlisten(ws):
|
||||
global burgerMessageCache
|
||||
global burgerMessageUpdate
|
||||
|
||||
while burgerMessageUpdate == True:
|
||||
ws.send(burgerMessageCache)
|
||||
burgerMessageUpdate = False
|
||||
|
||||
@app.route("/erm", methods=("GET", "POST"))
|
||||
def erm():
|
||||
print(burgerMessageCache)
|
||||
print(burgerMessageUpdate)
|
||||
|
||||
return "fart"
|
||||
|
||||
@app.route("/@<pageusername>", methods=("GET", "POST"))
|
||||
def user(pageusername):
|
||||
|
@ -290,7 +403,7 @@ def apilogin():
|
|||
|
||||
return {
|
||||
"key": randomCharacters
|
||||
}, 100
|
||||
}, 200
|
||||
else:
|
||||
return {
|
||||
"error": "https://http.cat/images/400.jpg"
|
||||
|
@ -346,7 +459,7 @@ def apipost():
|
|||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return "success", 100
|
||||
return "success", 200
|
||||
|
||||
@app.route("/apidocs", methods=("GET", "POST"))
|
||||
def apidocs():
|
||||
|
@ -445,7 +558,7 @@ def comment():
|
|||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return "success", 100
|
||||
return "success", 200
|
||||
|
||||
else:
|
||||
return {
|
||||
|
@ -581,7 +694,7 @@ def delete():
|
|||
conn.execute("DELETE FROM posts WHERE id = ?", (postid,))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return "success", 100
|
||||
return "success", 200
|
||||
else:
|
||||
return {
|
||||
"error": "https://http.cat/images/403.jpg"
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/python3
|
||||
import sqlite3
|
||||
import time
|
||||
import os
|
||||
|
||||
chatroomname = input("Insert name: ")
|
||||
|
||||
def get_db_connection():
|
||||
conn = sqlite3.connect("database.db")
|
||||
conn.row_factory = sqlite3.Row
|
||||
return conn
|
||||
|
||||
conn = get_db_connection()
|
||||
conn.execute("INSERT INTO chatrooms (roomname, creator, created) VALUES (?, ?, ?)",
|
||||
(chatroomname, 1, str(time.time())))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
print("Success!")
|
|
@ -1,4 +1,5 @@
|
|||
flask
|
||||
Flask-Limiter
|
||||
werkzeug
|
||||
waitress
|
||||
waitress
|
||||
requests
|
17
schema.sql
17
schema.sql
|
@ -2,6 +2,8 @@ DROP TABLE IF EXISTS users;
|
|||
DROP TABLE IF EXISTS posts;
|
||||
DROP TABLE IF EXISTS comments;
|
||||
DROP TABLE IF EXISTS sessions;
|
||||
DROP TABLE IF EXISTS chatrooms;
|
||||
DROP TABLE IF EXISTS chatmessages;
|
||||
|
||||
CREATE TABLE users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
|
@ -29,6 +31,21 @@ CREATE TABLE comments (
|
|||
textstr TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE chatrooms (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created TEXT NOT NULL,
|
||||
creator TEXT NOT NULL,
|
||||
roomname TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE chatmessages (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
chatroom_id INTEGER NOT NULL,
|
||||
created TEXT NOT NULL,
|
||||
creator TEXT NOT NULL,
|
||||
content TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE sessions (
|
||||
session TEXT PRIMARY KEY NOT NULL,
|
||||
id INTEGER NOT NULL
|
||||
|
|
|
@ -16,20 +16,25 @@ body {
|
|||
background-color: white;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.navbar .selected {
|
||||
border: solid;
|
||||
border-color: #f1b739;
|
||||
border-width: 0;
|
||||
border-bottom-width: 2px;
|
||||
}
|
||||
|
||||
.postDiv {
|
||||
padding-top: 120px;
|
||||
}
|
||||
|
||||
.profileDiv {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.profileIFrame {
|
||||
border: solid;
|
||||
border-width: 0;
|
||||
|
@ -38,6 +43,7 @@ body {
|
|||
width: 100%;
|
||||
height: calc(100vh - 295px);
|
||||
}
|
||||
|
||||
.profileDiv .badgeDiv p {
|
||||
background-color: black;
|
||||
border-radius: 99px;
|
||||
|
@ -47,15 +53,18 @@ body {
|
|||
padding-right: 10px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.editThing .htmlBox {
|
||||
width: calc(100% - 10px);
|
||||
height: 300px;
|
||||
text-align: top;
|
||||
}
|
||||
|
||||
.accountform {
|
||||
margin-left: 20%;
|
||||
margin-right: 20%;
|
||||
}
|
||||
|
||||
.accountform input {
|
||||
padding: 7px;
|
||||
border: solid;
|
||||
|
@ -65,6 +74,7 @@ body {
|
|||
font-size: 16px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.accountform .flash {
|
||||
padding: 7px;
|
||||
border: solid;
|
||||
|
@ -74,6 +84,7 @@ body {
|
|||
font-size: 16px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.accountform button {
|
||||
padding: 7px;
|
||||
border: solid;
|
||||
|
@ -124,6 +135,7 @@ body {
|
|||
font-size: 16px;
|
||||
font-family: "Inter", sans-serif;
|
||||
}
|
||||
|
||||
.post button:hover {
|
||||
border-color: #f1b739;
|
||||
}
|
||||
|
@ -138,11 +150,13 @@ body {
|
|||
margin-top: 5px;
|
||||
font-family: "Inter", sans-serif;
|
||||
}
|
||||
|
||||
.post hr {
|
||||
color: rgb(255, 255, 255);
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-color: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
.post .commentsdiv {
|
||||
background-color: #f5f5f5;
|
||||
padding: 5px;
|
||||
|
@ -163,6 +177,88 @@ body {
|
|||
text-decoration: none;
|
||||
}
|
||||
|
||||
.chatDiv {
|
||||
width: 292vh;
|
||||
margin-top: 2px;
|
||||
height: calc(100vh - 121px);
|
||||
}
|
||||
|
||||
.channelDiv {
|
||||
position: absolute;
|
||||
width: 220px;
|
||||
height: calc(100%);
|
||||
left: 0;
|
||||
background-color: rgb(245, 245, 245);
|
||||
}
|
||||
|
||||
.channelDiv .statusMessage {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
bottom: 122.5px;
|
||||
}
|
||||
|
||||
.channelDiv button {
|
||||
width: calc(100% - 20px);
|
||||
margin: 10px;
|
||||
margin-bottom: 0;
|
||||
padding-left: 10px;
|
||||
background-color: white;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
color: black;
|
||||
font-size: 16px;
|
||||
text-align: left;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.channelDiv .selected {
|
||||
border: solid;
|
||||
border-width: 1px;
|
||||
border-color: #f1b739;
|
||||
}
|
||||
|
||||
.channelDiv button:hover {
|
||||
background-color: rgb(249, 249, 249);
|
||||
transition: background-color ease-in-out 100ms
|
||||
}
|
||||
|
||||
.messageDiv {
|
||||
position: absolute;
|
||||
width: calc(100% - 220px);
|
||||
height: calc(100%);
|
||||
padding-bottom: 50px;
|
||||
right: 0;
|
||||
margin-top: -180px;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
.messageDiv p {
|
||||
font-size: 16px;
|
||||
margin-left: 10px;
|
||||
line-height: 8px;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.messageBar {
|
||||
position: absolute;
|
||||
width: calc(100% - 220px);
|
||||
height: 50px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgb(228, 228, 228);
|
||||
}
|
||||
|
||||
.messageBar input {
|
||||
width: calc(100% - 20px);
|
||||
height: calc(100% - 15px);
|
||||
border: none;
|
||||
border-radius: 99px;
|
||||
padding-left: 10px;
|
||||
font-size: 15px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.warning {
|
||||
width: 100%;
|
||||
background-color: #f1b739;
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
let channelDiv = document.getElementById("channelDiv")
|
||||
let messageDiv = document.getElementById("messageDiv")
|
||||
let messageBox = document.getElementById("messageBox")
|
||||
let statusMessage = document.getElementById("statusMessage")
|
||||
|
||||
let channelID = 0
|
||||
|
||||
async function updateMessages(id) {
|
||||
try {
|
||||
let response = await fetch("/api/chat/getmessages/" + id);
|
||||
let messages = await response.json()
|
||||
statusMessage.innerText = ""
|
||||
document.querySelectorAll(".messageParagraph").forEach(el => el.remove());
|
||||
for (let i in messages) {
|
||||
let messageParagraph = document.createElement("p")
|
||||
messageParagraph.appendChild(document.createTextNode(messages[i]["creator"]["username"] + ": " + messages[i]["content"]))
|
||||
messageParagraph.classList.add("messageParagraph")
|
||||
messageParagraph.id = "messageParagraph" + messages[i]["id"]
|
||||
messageDiv.append(messageParagraph)
|
||||
}
|
||||
}
|
||||
catch {
|
||||
statusMessage.innerText = "Not connected"
|
||||
}
|
||||
}
|
||||
|
||||
function selectChannel(id) {
|
||||
channelID = id
|
||||
|
||||
let selectedButton = channelDiv.querySelector(".selected");
|
||||
if (selectedButton) {
|
||||
selectedButton.classList.remove("selected");
|
||||
}
|
||||
|
||||
let channelButton = document.getElementById("channelButton" + id)
|
||||
if (channelButton) {
|
||||
channelButton.classList.add("selected")
|
||||
}
|
||||
else {
|
||||
console.log("channelButton not found")
|
||||
}
|
||||
|
||||
updateMessages(id)
|
||||
}
|
||||
|
||||
async function updateRooms() {
|
||||
let response = await fetch("/api/chat/listrooms");
|
||||
let rooms = await response.json()
|
||||
for (let i in rooms) {
|
||||
let channelButton = document.createElement("button")
|
||||
channelButton.appendChild(document.createTextNode(rooms[i]["name"]))
|
||||
channelButton.id = "channelButton" + rooms[i]["id"]
|
||||
channelButton.onclick = function () { selectChannel(rooms[i]["id"]) }
|
||||
|
||||
channelDiv.append(channelButton)
|
||||
}
|
||||
|
||||
selectChannel(1)
|
||||
}
|
||||
|
||||
async function sendMessage(content, id) {
|
||||
fetch("/api/chat/send/" + String(id), {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
content: content
|
||||
}),
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
messageBox.addEventListener("keyup", function onEvent(event) {
|
||||
if (event.key === "Enter") {
|
||||
sendMessage(messageBox.value, channelID)
|
||||
updateMessages(channelID)
|
||||
messageBox.value = ""
|
||||
}
|
||||
})
|
||||
|
||||
function update() {
|
||||
updateMessages(channelID)
|
||||
|
||||
setTimeout(update, 1500);
|
||||
}
|
||||
|
||||
window.addEventListener("load", function () {
|
||||
updateRooms()
|
||||
update()
|
||||
})
|
|
@ -0,0 +1,56 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<style>
|
||||
body {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
<head>
|
||||
<title>burgercat</title>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="navbar">
|
||||
<h1>burgercat</h1>
|
||||
<a href="/">home</a>
|
||||
<a class="selected" href="/chat">chat</a>
|
||||
<a href="/post">post</a>
|
||||
{% if userdata %}
|
||||
<a href="/settings/logout" class="right r">log out</a>
|
||||
<a href="/settings" class="right">{{ userdata.username }}</a>
|
||||
{% else %}
|
||||
<a href="/signup" class="right r">sign up</a>
|
||||
<a href="/login" class="right">log in</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="postDiv">
|
||||
{% if userdata %}
|
||||
{% if userdata.banned == "0" %}
|
||||
{% else %}
|
||||
<p class="warning">Your account has been banned. Reason: "{{ userdata.banned }}". <a href="/settings/logout">Log out</a></p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<div class="chatDiv">
|
||||
<div id="channelDiv" class="channelDiv">
|
||||
<p class="statusMessage" id="statusMessage">Connected</p>
|
||||
</div>
|
||||
<div id="messageDiv" class="messageDiv">
|
||||
</div>
|
||||
<div class="messageBar">
|
||||
<input id="messageBox" type="text" placeholder="Type something.." id="chatBox">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/static/js/chat.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -13,6 +13,7 @@
|
|||
<div class="navbar">
|
||||
<h1>burgercat</h1>
|
||||
<a class="selected" href="/">home</a>
|
||||
<a href="/chat">chat</a>
|
||||
<a href="/post">post</a>
|
||||
{% if userdata %}
|
||||
<a href="/settings/logout" class="right r">log out</a>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<div class="navbar">
|
||||
<h1>burgercat</h1>
|
||||
<a href="/">home</a>
|
||||
<a href="/chat">chat</a>
|
||||
<a class="selected" href="/post">post</a>
|
||||
{% if userdata %}
|
||||
<a href="/settings/logout" class="right r">log out</a>
|
||||
|
|
Reference in New Issue