This commit is contained in:
maaa 2023-07-11 21:41:57 +02:00
parent f19e002fc5
commit adf6ad863c
10 changed files with 401 additions and 5 deletions

View File

@ -13,3 +13,6 @@ python main
### zero downtime restarts: ### zero downtime restarts:
- launch new burgercat server - launch new burgercat server
- close previous server - close previous server
### contribution guidelines:
- please check that your PR does not break anything

121
main
View File

@ -82,6 +82,16 @@ def get_comments(id):
return post 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) app.jinja_env.globals.update(getComments=get_comments)
def get_post(id): def get_post(id):
@ -138,6 +148,109 @@ def main():
else: else:
return render_template("main.html", posts=posts) 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")) @app.route("/@<pageusername>", methods=("GET", "POST"))
def user(pageusername): def user(pageusername):
@ -290,7 +403,7 @@ def apilogin():
return { return {
"key": randomCharacters "key": randomCharacters
}, 100 }, 200
else: else:
return { return {
"error": "https://http.cat/images/400.jpg" "error": "https://http.cat/images/400.jpg"
@ -346,7 +459,7 @@ def apipost():
conn.commit() conn.commit()
conn.close() conn.close()
return "success", 100 return "success", 200
@app.route("/apidocs", methods=("GET", "POST")) @app.route("/apidocs", methods=("GET", "POST"))
def apidocs(): def apidocs():
@ -445,7 +558,7 @@ def comment():
conn.commit() conn.commit()
conn.close() conn.close()
return "success", 100 return "success", 200
else: else:
return { return {
@ -581,7 +694,7 @@ def delete():
conn.execute("DELETE FROM posts WHERE id = ?", (postid,)) conn.execute("DELETE FROM posts WHERE id = ?", (postid,))
conn.commit() conn.commit()
conn.close() conn.close()
return "success", 100 return "success", 200
else: else:
return { return {
"error": "https://http.cat/images/403.jpg" "error": "https://http.cat/images/403.jpg"

18
newchatroom Normal file
View File

@ -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!")

View File

@ -2,3 +2,4 @@ flask
Flask-Limiter Flask-Limiter
werkzeug werkzeug
waitress waitress
requests

View File

@ -2,6 +2,8 @@ DROP TABLE IF EXISTS users;
DROP TABLE IF EXISTS posts; DROP TABLE IF EXISTS posts;
DROP TABLE IF EXISTS comments; DROP TABLE IF EXISTS comments;
DROP TABLE IF EXISTS sessions; DROP TABLE IF EXISTS sessions;
DROP TABLE IF EXISTS chatrooms;
DROP TABLE IF EXISTS chatmessages;
CREATE TABLE users ( CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
@ -29,6 +31,21 @@ CREATE TABLE comments (
textstr TEXT NOT NULL 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 ( CREATE TABLE sessions (
session TEXT PRIMARY KEY NOT NULL, session TEXT PRIMARY KEY NOT NULL,
id INTEGER NOT NULL id INTEGER NOT NULL

View File

@ -16,20 +16,25 @@ body {
background-color: white; background-color: white;
width: 100%; width: 100%;
position: fixed; position: fixed;
z-index: 2;
} }
.navbar .selected { .navbar .selected {
border: solid; border: solid;
border-color: #f1b739; border-color: #f1b739;
border-width: 0; border-width: 0;
border-bottom-width: 2px; border-bottom-width: 2px;
} }
.postDiv { .postDiv {
padding-top: 120px; padding-top: 120px;
} }
.profileDiv { .profileDiv {
padding-left: 10px; padding-left: 10px;
padding-right: 10px; padding-right: 10px;
} }
.profileIFrame { .profileIFrame {
border: solid; border: solid;
border-width: 0; border-width: 0;
@ -38,6 +43,7 @@ body {
width: 100%; width: 100%;
height: calc(100vh - 295px); height: calc(100vh - 295px);
} }
.profileDiv .badgeDiv p { .profileDiv .badgeDiv p {
background-color: black; background-color: black;
border-radius: 99px; border-radius: 99px;
@ -47,15 +53,18 @@ body {
padding-right: 10px; padding-right: 10px;
display: inline; display: inline;
} }
.editThing .htmlBox { .editThing .htmlBox {
width: calc(100% - 10px); width: calc(100% - 10px);
height: 300px; height: 300px;
text-align: top; text-align: top;
} }
.accountform { .accountform {
margin-left: 20%; margin-left: 20%;
margin-right: 20%; margin-right: 20%;
} }
.accountform input { .accountform input {
padding: 7px; padding: 7px;
border: solid; border: solid;
@ -65,6 +74,7 @@ body {
font-size: 16px; font-size: 16px;
border-radius: 8px; border-radius: 8px;
} }
.accountform .flash { .accountform .flash {
padding: 7px; padding: 7px;
border: solid; border: solid;
@ -74,6 +84,7 @@ body {
font-size: 16px; font-size: 16px;
border-radius: 8px; border-radius: 8px;
} }
.accountform button { .accountform button {
padding: 7px; padding: 7px;
border: solid; border: solid;
@ -124,6 +135,7 @@ body {
font-size: 16px; font-size: 16px;
font-family: "Inter", sans-serif; font-family: "Inter", sans-serif;
} }
.post button:hover { .post button:hover {
border-color: #f1b739; border-color: #f1b739;
} }
@ -138,11 +150,13 @@ body {
margin-top: 5px; margin-top: 5px;
font-family: "Inter", sans-serif; font-family: "Inter", sans-serif;
} }
.post hr { .post hr {
color: rgb(255, 255, 255); color: rgb(255, 255, 255);
background-color: rgb(255, 255, 255); background-color: rgb(255, 255, 255);
border-color: rgb(255, 255, 255); border-color: rgb(255, 255, 255);
} }
.post .commentsdiv { .post .commentsdiv {
background-color: #f5f5f5; background-color: #f5f5f5;
padding: 5px; padding: 5px;
@ -163,6 +177,88 @@ body {
text-decoration: none; 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 { .warning {
width: 100%; width: 100%;
background-color: #f1b739; background-color: #f1b739;

90
static/js/chat.js Normal file
View File

@ -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()
})

56
templates/chat.html Normal file
View File

@ -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>

View File

@ -13,6 +13,7 @@
<div class="navbar"> <div class="navbar">
<h1>burgercat</h1> <h1>burgercat</h1>
<a class="selected" href="/">home</a> <a class="selected" href="/">home</a>
<a href="/chat">chat</a>
<a href="/post">post</a> <a href="/post">post</a>
{% if userdata %} {% if userdata %}
<a href="/settings/logout" class="right r">log out</a> <a href="/settings/logout" class="right r">log out</a>

View File

@ -13,6 +13,7 @@
<div class="navbar"> <div class="navbar">
<h1>burgercat</h1> <h1>burgercat</h1>
<a href="/">home</a> <a href="/">home</a>
<a href="/chat">chat</a>
<a class="selected" href="/post">post</a> <a class="selected" href="/post">post</a>
{% if userdata %} {% if userdata %}
<a href="/settings/logout" class="right r">log out</a> <a href="/settings/logout" class="right r">log out</a>