Compare commits

...

8 Commits

22 changed files with 154 additions and 106 deletions

View File

@ -3,16 +3,10 @@
- `/api/register` & `/api/login` now use JSON data - `/api/register` & `/api/login` now use JSON data
- Changing user info now uses Enum (Name, Pin, or Pronouns) - Changing user info now uses Enum (Name, Pin, or Pronouns)
### 0.5.2 ### 0.6.1
- When changing a username, it now deletes the previous user instead of creating a new one - Add basic support for different user roles & moderator commands
- Database functions should now use some error handling - Any user names "admin" will be made into an Admin user
- Functions use `db_read_user()` instead of reading in the whole database - User pronouns are stored in message body now
### 0.5.1
- `/api/logout` API to delete session token
- Add basic support for different message types
- Messages now use unix timestamps
- Backend finds timestamp
## 0.5.0 ## 0.5.0
- Most actions should now fail on a NULL token - Most actions should now fail on a NULL token
@ -20,6 +14,17 @@
- Use sled database instead of json file to store users - Use sled database instead of json file to store users
- Now use `GET /api/token/<name>` to validate a users session token - Now use `GET /api/token/<name>` to validate a users session token
### 0.5.1
- `/api/logout` API to delete session token
- Add basic support for different message types
- Messages now use unix timestamps
- Backend finds timestamp
### 0.5.2
- When changing a username, it now deletes the previous user instead of creating a new one
- Database functions should now use some error handling
- Functions use `db_read_user()` instead of reading in the whole database
## 0.4.0 ## 0.4.0
- Serve frontend code - Serve frontend code
- Set cookie for token - Set cookie for token

38
Cargo.lock generated
View File

@ -576,6 +576,25 @@ version = "0.2.98"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
[[package]]
name = "lila-chat"
version = "0.6.1"
dependencies = [
"bincode",
"chrono",
"env_logger",
"log 0.4.14",
"once_cell",
"random-string",
"rocket",
"rocket_contrib",
"serde",
"serde_json",
"sha1",
"sled",
"uuid",
]
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.4" version = "0.4.4"
@ -805,25 +824,6 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pogchat"
version = "0.6.0"
dependencies = [
"bincode",
"chrono",
"env_logger",
"log 0.4.14",
"once_cell",
"random-string",
"rocket",
"rocket_contrib",
"serde",
"serde_json",
"sha1",
"sled",
"uuid",
]
[[package]] [[package]]
name = "polyval" name = "polyval"
version = "0.4.5" version = "0.4.5"

View File

@ -1,7 +1,7 @@
[package] [package]
name = "lila-chat" name = "lila-chat"
description = "A basic chat server written in rust" description = "A basic chat server written in rust"
version = "0.6.0" version = "0.6.1"
documentation = "https://git.lavender.software/erin/lila-chat/wiki" documentation = "https://git.lavender.software/erin/lila-chat/wiki"
repository = "https://git.lavender.software/erin/lila-chat/" repository = "https://git.lavender.software/erin/lila-chat/"
license = "CNPLv6+" license = "CNPLv6+"

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -9,9 +9,6 @@
id="svg5" id="svg5"
inkscape:version="1.1 (c4e8f9ed74, 2021-05-24)" inkscape:version="1.1 (c4e8f9ed74, 2021-05-24)"
sodipodi:docname="favicon.svg" sodipodi:docname="favicon.svg"
inkscape:export-filename="/home/erin/bitmap.png"
inkscape:export-xdpi="200"
inkscape:export-ydpi="200"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1,9 +1,14 @@
html { html {
background: #F7A8B8; background: #F7A8B8;
text-align: center; text-align: center;
font-family: "Lucida Console", "Courier New", monospace; font-family: "Linotte", "Lucida Console", monospace;
} }
@font-face {
font-family: Linotte;
src: url(../assets/LinotteRegular.otf);
}
form { form {
width: 100%; width: 100%;
overflow:hidden; overflow:hidden;

View File

@ -1,8 +1,13 @@
html { html {
background: #F7A8B8; background: #F7A8B8;
font-family: "Lucida Console", "Courier New", monospace; font-family: "Linotte", "Lucida Console", monospace;
} }
@font-face {
font-family: Linotte;
src: url(../assets/LinotteRegular.otf);
}
a { a {
color: black; color: black;
font-weight: bold; font-weight: bold;
@ -23,8 +28,10 @@ a {
height: 540px; height: 540px;
margin-right: 0.3em; margin-right: 0.3em;
margin-left: -40%; margin-left: -40%;
margin-top: auto; margin-top: 5%;
margin-bottom: 20%; margin-bottom: 20%;
font-size: 250%;
text-align: center;
} }
#streamframe { #streamframe {
@ -37,16 +44,18 @@ a {
height: 53rem; height: 53rem;
margin-left: 0.3em; margin-left: 0.3em;
margin-right: -30%; margin-right: -30%;
margin-top: -8%;
border: none; border: none;
} }
.navigation-list { .navigation-list {
display: flex; display: inline-flex;
list-style-type: none; list-style-type: none;
flex-wrap: wrap; flex-wrap: wrap;
gap: 10px; gap: 10px;
justify-content: center; justify-content: center;
padding: 0; padding: 0;
margin-left: 5%;
} }
.buttons { .buttons {

View File

@ -7,7 +7,7 @@
<meta name="description" content="Maya's Stream Chat"> <meta name="description" content="Maya's Stream Chat">
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="chat.css"> <link rel="stylesheet" href="../css/chat.css">
<link rel="icon" href=""> <link rel="icon" href="">
</head> </head>
@ -34,8 +34,8 @@
<div id="errormessage"></div> <div id="errormessage"></div>
<script src="chat.js"></script> <script src="../js/chat.js"></script>
<script src="logout.js"></script> <script src="../js/logout.js"></script>
</body> </body>

View File

@ -7,8 +7,8 @@
<meta name="description" content="Chat Login"> <meta name="description" content="Chat Login">
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="../css/style.css">
<link rel="icon" href="/favicon.svg"> <link rel="icon" href="../assets/favicon.svg">
</head> </head>
<body> <body>
@ -27,7 +27,7 @@
</form> </form>
</div> </div>
<script src="login.js"></script> <script src="../js/login.js"></script>
<div id="errormessage"></div> <div id="errormessage"></div>

View File

@ -7,8 +7,8 @@
<meta name="description" content="Chat Register"> <meta name="description" content="Chat Register">
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="../css/style.css">
<link rel="icon" href="/favicon.svg"> <link rel="icon" href="../assets/favicon.svg">
</head> </head>
<h1>Register:</h1> <h1>Register:</h1>
@ -45,7 +45,7 @@
<div id="errormessage"></div> <div id="errormessage"></div>
<script src="register.js"></script> <script src="../js/register.js"></script>
</body> </body>
</html> </html>

View File

@ -7,8 +7,8 @@
<meta name="description" content="Chat Login Change"> <meta name="description" content="Chat Login Change">
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="../css/style.css">
<link rel="icon" href="/favicon.svg"> <link rel="icon" href="../assets/favicon.svg">
</head> </head>
<body> <body>
@ -53,7 +53,7 @@
</form> </form>
</div> </div>
<script src="updateinfo.js"></script> <script src="../js/updateinfo.js"></script>
<div id="errormessage"></div> <div id="errormessage"></div>
</body> </body>

View File

@ -7,8 +7,8 @@
<meta name="description" content="Maya's Stream"> <meta name="description" content="Maya's Stream">
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="index.css"> <link rel="stylesheet" href="css/index.css">
<link rel="icon" href="/favicon.svg"> <link rel="icon" href="assets/favicon.svg">
</head> </head>
<body> <body>
@ -18,16 +18,16 @@
<li><a href="index.html"> <li><a href="index.html">
<div class="buttons">Stream</div> <div class="buttons">Stream</div>
</a></li> </a></li>
<li><a href="chat.html"> <li><a href="/html/chat.html">
<div class="buttons">Just Chat</div> <div class="buttons">Just Chat</div>
</a></li> </a></li>
<li><a href="register.html"> <li><a href="/html/register.html">
<div class="buttons">Register</div> <div class="buttons">Register</div>
</a></li> </a></li>
<li><a href="login.html"> <li><a href="/html/login.html">
<div class="buttons">Login</div> <div class="buttons">Login</div>
</a></li> </a></li>
<li><a href="updateinfo.html"> <li><a href="/html/updateinfo.html">
<div class="buttons">Update Info</div> <div class="buttons">Update Info</div>
</a></li> </a></li>
</ul> </ul>
@ -35,16 +35,33 @@
</nav> </nav>
<script>
// Checking if the stream is down and displays a message if it is.
async function isStreamDown() {
const response = await fetch(`https://cdn.chaos.stream/hls/src/maya.m3u8`);
if (response.status === 404) {
document.getElementById("streamframe").style.display = "none";
document.getElementById("stream").style.border = 'double'
document.getElementById("stream").innerHTML = 'Currently not streaming.'
}
}
window.onload = isStreamDown()
</script>
<main> <main>
<section> <section>
<div id="streamchat"> <div id="streamchat">
<div id="stream"> <div id="stream">
<iframe id="streamframe" src="https://live.on.chaos.stream/maya" title="mayas stream" scrolling="no"></iframe> <iframe id="streamframe" src="https://live.on.chaos.stream/maya" title="mayas stream"
scrolling="no"></iframe>
</div> </div>
<iframe id="chatbox" src="chat.html" title="chat box" scrolling="no"></iframe> <iframe id="chatbox" src="/html/chat.html" title="chat box" scrolling="no"></iframe>
</div> </div>

View File

@ -14,7 +14,7 @@ form.addEventListener("submit", async function (event) {
//KINDA UNNECESSARY //KINDA UNNECESSARY
//CHECKS TO SEE IF THE PERSON IS LOGGED IN IN ORDER TO SEND A MESSAGE. //CHECKS TO SEE IF THE PERSON IS LOGGED IN IN ORDER TO SEND A MESSAGE.
const response = await fetch(`api/token/${username}/`); const response = await fetch(`../api/token/${username}/`);
const matches = await response.json(); const matches = await response.json();
//YES THIS IS CONFUSING I KNOW. //YES THIS IS CONFUSING I KNOW.
@ -27,14 +27,14 @@ form.addEventListener("submit", async function (event) {
localStorage.removeItem('username') localStorage.removeItem('username')
form.reset() form.reset()
} }
return formMessage;
}) })
//SEND MESSAGE FETCH FUNCTION //SEND MESSAGE FETCH FUNCTION
async function sendMessage() { async function sendMessage() {
sendMessageInfo = { "name": username, "body": formMessage } sendMessageInfo = { "name": username, "body": formMessage }
fetch('/api/message/send', { fetch('../api/message/send', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@ -42,6 +42,7 @@ async function sendMessage() {
body: JSON.stringify(sendMessageInfo), body: JSON.stringify(sendMessageInfo),
}) })
form.reset() form.reset()
modCommand()
} }
@ -55,7 +56,17 @@ async function fetchMessages() {
document.getElementById("chatbox").innerHTML = "" document.getElementById("chatbox").innerHTML = ""
for (const message of recievedMessages) { for (const message of recievedMessages) {
printText(message.user.bold().toString() + ": " + message.body.toString());
let leftBracket = '('
let rightBracket = ')'
let space = ' '
if (message.pronouns === '' || message.pronouns === 'none' || message.pronouns === null) {
leftBracket = ''
rightBracket = ''
space = ''
}
printText(message.user.bold().toString() + space + "<i style='color:#b8d1e7'>" + leftBracket.small() + message.pronouns.small().toString() + rightBracket.small() + "</i>" + " : " + "<span style='color:#e4e4ef'>" + message.body.toString() + "</span>");
} }
@ -90,12 +101,48 @@ function loggedIn() {
loggedIn() loggedIn()
//MODERATION
async function modCommand() {
let action = ''
let target = ''
if (formMessage.startsWith('/ban')) {
action = "Ban"
target = formMessage.replace('/ban ', '')
sendCommand()
} else if (formMessage.startsWith('/kick')) {
action = "Kick"
target = formMessage.replace('/kick ', '')
sendCommand()
} else if (formMessage.startsWith('/promote')) {
action = "Promote"
target = formMessage.replace('/promote ', '')
sendCommand()
} else if (formMessage.startsWith('/demote')) {
action = "Demote"
target = formMessage.replace('/demote ', '')
sendCommand()
} else {
return;
}
async function sendCommand() {
let sendCommand = { "name": username, "action": action, "target": target }
const response = await fetch('/api/mod/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(sendCommand),
});
if (response.status === 'ok') {
return;
} else {
printText('Error Issuing Command. Are you an Admin or Mod?')
}
}
}
//REVIECE USERS PRONOUNS
async function getPronouns() {
const response = await fetch(`api/users/${username}/`);
const data = await response.json();
pronouns = data.pronouns
return pronouns;
}

View File

@ -38,7 +38,7 @@ form.addEventListener("submit", async function (event) {
if (regRes.status === 'ok') { if (regRes.status === 'ok') {
document.querySelector("#errormessage").innerHTML = 'Registered!' document.querySelector("#errormessage").innerHTML = 'Registered!'
window.location.replace("/login.html") window.location.replace("../html/login.html")
} else { } else {
document.querySelector("#errormessage").innerHTML = 'Failed to register. Try again later.' document.querySelector("#errormessage").innerHTML = 'Failed to register. Try again later.'
} }
@ -52,7 +52,7 @@ form.addEventListener("submit", async function (event) {
//CHECKS IF A USERNAME IS TAKEN //CHECKS IF A USERNAME IS TAKEN
async function isUnameTaken() { async function isUnameTaken() {
const response = await fetch(`api/users/${uname}/`); const response = await fetch(`/api/users/${uname}/`);
const isTaken = await response.json(); const isTaken = await response.json();
//YES THIS IS CONFUSING I KNOW. //YES THIS IS CONFUSING I KNOW.
@ -67,7 +67,7 @@ async function isUnameTaken() {
async function register() { async function register() {
let sendRegisterInfo = { "name": uname, "pin": pin, "pronouns": pronouns } let sendRegisterInfo = { "name": uname, "pin": pin, "pronouns": pronouns }
const response = await fetch('/api/register/', { const response = await fetch('../api/register/', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',

View File

@ -82,7 +82,7 @@ form.addEventListener("submit", async function (event) {
if (updateResponse.status === 'ok') { if (updateResponse.status === 'ok') {
document.querySelector("#errormessage").innerHTML = 'Login Changed!' document.querySelector("#errormessage").innerHTML = 'Login Changed!'
window.location.replace("/login.html") window.location.replace("../html/login.html")
} else { } else {
document.querySelector("#errormessage").innerHTML = 'Failed to update info. Try again later.' document.querySelector("#errormessage").innerHTML = 'Failed to update info. Try again later.'
} }

View File

@ -1,34 +0,0 @@
html {
background: #F7A8B8;
text-align: center;
font-family: "Lucida Console", "Courier New", monospace;
}
body {
margin-top: 3%;
}
#streamchat {
display: flex;
height: 100%;
max-width: 960px;
margin: 0 auto;
}
#stream {
background-color: white;
padding: 5%;
box-shadow: 10px 10px 10px black;
border-radius: 5px;
width: 100%;
height: 100%;
margin-right: 4em;
}
#chatbox {
width: 100%;
height: 100%;
margin-left: 4em;
}

View File

@ -42,6 +42,7 @@ fn create_message(message: Json<MessageInput>, user: &User) -> JsonValue {
id: Uuid::new_v4(), id: Uuid::new_v4(),
event_type, event_type,
user: user.name.to_lowercase().to_owned(), user: user.name.to_lowercase().to_owned(),
pronouns: user.pronouns.to_lowercase().to_owned(),
body: message.body.to_string(), body: message.body.to_string(),
created_at: Utc::now(), created_at: Utc::now(),
}; };

View File

@ -21,6 +21,7 @@ pub struct Message {
pub id: Uuid, pub id: Uuid,
pub event_type: MessageType, pub event_type: MessageType,
pub user: String, pub user: String,
pub pronouns: String,
pub body: String, pub body: String,
pub created_at: DateTime<Utc>, pub created_at: DateTime<Utc>,
} }