Compare commits
26 Commits
break-data
...
main
Author | SHA1 | Date |
---|---|---|
~erin | cd2e47a852 | |
Luna | 2161bc6d5d | |
Luna | 62614bf461 | |
Luna | cbe1b254cc | |
Luna | 34326c00eb | |
Luna | eb6bec830e | |
~erin | 1de762f788 | |
~erin | da51a37b49 | |
~erin | b3fa390c72 | |
Luna | adb6d054dd | |
~erin | ebcda9b067 | |
~erin | b099448006 | |
~erin | ba90ca471b | |
~erin | b4e537b8df | |
~erin | c665951b9d | |
~erin | 7963ce9199 | |
~erin | 625485674e | |
Luna | ccd7a2c267 | |
Luna | 356524d35e | |
Luna | df873ec77a | |
Luna | d88f243ee0 | |
Luna | 971e0e338f | |
Luna | 1b8694ef8d | |
~erin | 475729b1a0 | |
~erin | e5384ac588 | |
Luna | e73108f830 |
25
CHANGELOG.md
25
CHANGELOG.md
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
10
Cargo.toml
10
Cargo.toml
|
@ -1,7 +1,11 @@
|
||||||
[package]
|
[package]
|
||||||
name = "pogchat"
|
name = "lila-chat"
|
||||||
version = "0.6.0"
|
description = "A basic chat server written in rust"
|
||||||
authors = ["Erin Nova <erin@the-system.eu.org>"]
|
version = "0.6.1"
|
||||||
|
documentation = "https://git.lavender.software/erin/lila-chat/wiki"
|
||||||
|
repository = "https://git.lavender.software/erin/lila-chat/"
|
||||||
|
license = "CNPLv6+"
|
||||||
|
authors = ["Erin Nova <erin@the-system.eu.org>", "Charlotte"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
109
README.md
109
README.md
|
@ -4,101 +4,7 @@ A simple chat system for built for maya's livestream.
|
||||||
Provides a simple API for user authentication, and chat functions.
|
Provides a simple API for user authentication, and chat functions.
|
||||||
Frontend & backend code stored here.
|
Frontend & backend code stored here.
|
||||||
|
|
||||||
## Auth API Documentation
|
## Implemented Features:
|
||||||
|
|
||||||
Most API functions will return JSON in the following format:
|
|
||||||
|
|
||||||
`status`: either `ok` if action succeeded, or `fail` otherwise.
|
|
||||||
|
|
||||||
`reason`: More info about why the action failed.
|
|
||||||
|
|
||||||
### Register & Login:
|
|
||||||
|
|
||||||
`POST /api/register` with JSON body values of: `name`, `pin`, `pronouns`.
|
|
||||||
|
|
||||||
Will return JSON with `status` and `reason`.
|
|
||||||
|
|
||||||
`POST /api/login` with JSON body values of: `name`, `pin`.
|
|
||||||
|
|
||||||
Will return JSON with `status` and `reason`.
|
|
||||||
|
|
||||||
Will set a private cookie named `token` which is used for authentication.
|
|
||||||
|
|
||||||
### Change User Information
|
|
||||||
|
|
||||||
User information such as name, pin, and pronouns, can be changed currently one at a time.
|
|
||||||
|
|
||||||
`POST /api/change` with JSON body values of: `name`, `changed_event`, `new_event`.
|
|
||||||
|
|
||||||
`name` the user's current username. used for authentication.
|
|
||||||
|
|
||||||
`changed_event` which event to change. value can be one of: `Name`, `Pin`, `Pronouns`.
|
|
||||||
|
|
||||||
`new_event` the new value for the changed event.
|
|
||||||
|
|
||||||
User is authenticated via token.
|
|
||||||
|
|
||||||
### Check if User is Still Logged in
|
|
||||||
|
|
||||||
Instead of having to save the pin and re-login every time to check wether they're logged in, you can just check via the token.
|
|
||||||
|
|
||||||
`GET /api/token/<name>` where `<name>` is the current username.
|
|
||||||
|
|
||||||
Will return JSON with `status` and `reason`.
|
|
||||||
|
|
||||||
### Logout
|
|
||||||
|
|
||||||
This API will remove the cookie from the client, as well as invalidating the token serverside.
|
|
||||||
|
|
||||||
`POST /api/logout` with JSON body values of: `name`.
|
|
||||||
|
|
||||||
Will use the current token as authentication.
|
|
||||||
|
|
||||||
Will return JSON with `status` and `reason`.
|
|
||||||
|
|
||||||
### Get Info About A User
|
|
||||||
|
|
||||||
This API will return info about a user on success.
|
|
||||||
|
|
||||||
`GET /api/users/<name>`
|
|
||||||
|
|
||||||
On success returns JSON in format:
|
|
||||||
```
|
|
||||||
status: ok
|
|
||||||
user:
|
|
||||||
name: user's name
|
|
||||||
pronouns: user's pronouns
|
|
||||||
role: the users role, one of either 'Normal', 'Moderator', or 'Admin'
|
|
||||||
```
|
|
||||||
|
|
||||||
eg:
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
status: "ok",
|
|
||||||
user: {
|
|
||||||
name: "example",
|
|
||||||
pronouns: "they/them",
|
|
||||||
role: "Normal",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Chat API Documentation
|
|
||||||
|
|
||||||
`POST /api/message/send {"name":"username","body":"message body"}` Post a message with JSON body values of: `name` & `body`
|
|
||||||
|
|
||||||
Will return JSON with `status` and `reason`.
|
|
||||||
|
|
||||||
`GET /api/message/messages.json` Returns a json file of all the messages
|
|
||||||
|
|
||||||
## Chat Planning
|
|
||||||
|
|
||||||
Clientside js will register & check login of users, if login is correct will ask for a random token.
|
|
||||||
Backend will generate token, store it, and then send it to the client to set as a cookie.
|
|
||||||
Whenever user sends a message, client will send message & token and backend will check if token matches.
|
|
||||||
|
|
||||||
## To-Do:
|
|
||||||
|
|
||||||
- [x] Basic auth API
|
- [x] Basic auth API
|
||||||
- [x] Return json instead of string
|
- [x] Return json instead of string
|
||||||
|
@ -108,7 +14,6 @@ Whenever user sends a message, client will send message & token and backend will
|
||||||
- [x] Finish up `chat::create_message()`
|
- [x] Finish up `chat::create_message()`
|
||||||
- [x] Create `chat::fetch_messages()`
|
- [x] Create `chat::fetch_messages()`
|
||||||
- [x] Use unix timestamp for date
|
- [x] Use unix timestamp for date
|
||||||
- [ ] Create `chat::delete_message()`
|
|
||||||
- [x] Switch to using sled database to store users
|
- [x] Switch to using sled database to store users
|
||||||
- [x] Error handling
|
- [x] Error handling
|
||||||
- [x] Token generation & storage
|
- [x] Token generation & storage
|
||||||
|
@ -123,10 +28,20 @@ Whenever user sends a message, client will send message & token and backend will
|
||||||
- [x] Set pronouns
|
- [x] Set pronouns
|
||||||
- [x] Change pronouns
|
- [x] Change pronouns
|
||||||
- [x] make changed_event Enum, use token instead of pin
|
- [x] make changed_event Enum, use token instead of pin
|
||||||
|
|
||||||
|
## To-Do:
|
||||||
|
|
||||||
|
- [x] Better messaging system
|
||||||
|
- [ ] Use websockets for chat [issue#3](https://git.lavender.software/erin/lila-chat/issues/3)
|
||||||
|
- [ ] Create `chat::delete_message()`
|
||||||
|
- [ ] Display pronouns [issue#4](https://git.lavender.software/erin/lila-chat/issues/4)
|
||||||
|
- [ ] Various database improvements [issue#1](https://git.lavender.software/erin/lila-chat/issues/1)
|
||||||
|
- [ ] Improve error handling on write functions
|
||||||
|
- [ ] Allow for asyncronous reading/writing
|
||||||
- [ ] Some form of plural support?
|
- [ ] Some form of plural support?
|
||||||
- [ ] User management (banning, etc.)
|
- [ ] User management (banning, etc.)
|
||||||
- [x] User roles (admin, mod, etc.)
|
- [x] User roles (admin, mod, etc.)
|
||||||
- [ ] Commands to affect users
|
- [ ] Commands to affect users [issue#2](https://git.lavender.software/erin/lila-chat/issues/2)
|
||||||
- [ ] Blacklist words from chat/names
|
- [ ] Blacklist words from chat/names
|
||||||
- [ ] More advanced chat features
|
- [ ] More advanced chat features
|
||||||
- [x] Different types of message events? eg. default, announcement, command
|
- [x] Different types of message events? eg. default, announcement, command
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
@ -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 |
|
@ -1,43 +0,0 @@
|
||||||
html {
|
|
||||||
background: #F7A8B8;
|
|
||||||
text-align: center;
|
|
||||||
font-family: "Lucida Console", "Courier New", monospace;
|
|
||||||
}
|
|
||||||
|
|
||||||
form {
|
|
||||||
width: 100%
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
padding: 3%;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
#chatbox {
|
|
||||||
background-color: white;
|
|
||||||
padding: 1rem;
|
|
||||||
box-shadow: 10px 10px 10px black;
|
|
||||||
width: 40rem;
|
|
||||||
height: 40rem;
|
|
||||||
display: inline-flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
#innerchatbox {
|
|
||||||
background-color: rgba(60, 60, 60, .75);
|
|
||||||
width: 100%;
|
|
||||||
height: 90%;
|
|
||||||
overflow-y: scroll;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
#loggeduser {
|
|
||||||
padding-top: 1%
|
|
||||||
}
|
|
||||||
|
|
||||||
#error {
|
|
||||||
padding-top: 2.5%;
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
// VARIABLES
|
|
||||||
let date = '2021-07-22'
|
|
||||||
let messageCount = 0;
|
|
||||||
let username = localStorage.getItem('username');
|
|
||||||
const form = document.querySelector('form');
|
|
||||||
|
|
||||||
// SEND A MESSAGE
|
|
||||||
|
|
||||||
// GRABS MESSAGE FROM FORM & SENDS
|
|
||||||
form.addEventListener("submit", async function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
const formData = new FormData(form);
|
|
||||||
|
|
||||||
formMessage = formData.get('message');
|
|
||||||
|
|
||||||
sendMessage()
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
//SEND MESSAGE FETCH FUNCTION
|
|
||||||
|
|
||||||
async function sendMessage() {
|
|
||||||
sendMessageInfo = { "name": username, "body": formMessage, "date": date }
|
|
||||||
fetch('/api/message/send', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify(sendMessageInfo),
|
|
||||||
})
|
|
||||||
form.reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// RECIEVE MESSAGES
|
|
||||||
|
|
||||||
let messageUpdate = window.setInterval(fetchMessages, 500);
|
|
||||||
|
|
||||||
async function fetchMessages() {
|
|
||||||
const response = await fetch('/api/message/messages.json');
|
|
||||||
const recievedMessages = await response.json();
|
|
||||||
document.getElementById("innerchatbox").innerHTML = ""
|
|
||||||
|
|
||||||
for (const message of recievedMessages) {
|
|
||||||
printText(message.user.bold() + ": " + message.body);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (recievedMessages.length != messageCount) {
|
|
||||||
let scroll = document.getElementById("innerchatbox");
|
|
||||||
scroll.scrollTop = scroll.scrollHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
messageCount = recievedMessages.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// FUNCTION TO PRINT MESSAGES IN THE CHAT BOX
|
|
||||||
|
|
||||||
function printText(text) {
|
|
||||||
let p = document.createElement("p");
|
|
||||||
const div = document.getElementById("innerchatbox");
|
|
||||||
div.appendChild(p)
|
|
||||||
p.innerHTML = text
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//LOGGED IN STUFF
|
|
||||||
//TODO ADD CHECK TO SEE IF USERNAME AND TOKEN MATCHES
|
|
||||||
if (username === null) {
|
|
||||||
document.querySelector("#loggeduser").innerHTML = 'You are not logged in'
|
|
||||||
username = ''
|
|
||||||
} else {
|
|
||||||
document.querySelector("#loggeduser").innerHTML = `You are logged in as ${username}`
|
|
||||||
}
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
html {
|
||||||
|
background: #F7A8B8;
|
||||||
|
text-align: center;
|
||||||
|
font-family: "Linotte", "Lucida Console", monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Linotte;
|
||||||
|
src: url(../assets/LinotteRegular.otf);
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
width: 100%;
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
margin-top: 1%;
|
||||||
|
padding: 2%;
|
||||||
|
width: 100%;
|
||||||
|
background-color: darkgrey;
|
||||||
|
border-style: none;
|
||||||
|
border-bottom-style: solid;
|
||||||
|
border-bottom-color: black;
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
font-family: "Lucida Console", "Courier New", monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
margin-top: 1%;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 1%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loggeduser {
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#outerchatbox {
|
||||||
|
background-color: rgb(255, 199, 207);
|
||||||
|
padding: 1rem;
|
||||||
|
box-shadow: 10px 10px 10px black;
|
||||||
|
width: 30rem;
|
||||||
|
height: 40rem;
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chatbox {
|
||||||
|
background-color: rgb(60, 60, 60);
|
||||||
|
width: 100%;
|
||||||
|
height: 90%;
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
|
text-align: left;
|
||||||
|
color: white;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loggeduser {
|
||||||
|
padding-top: 2%
|
||||||
|
}
|
||||||
|
|
||||||
|
#errormessage {
|
||||||
|
padding-top: 2.5%;
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
html {
|
||||||
|
background: #F7A8B8;
|
||||||
|
font-family: "Linotte", "Lucida Console", monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Linotte;
|
||||||
|
src: url(../assets/LinotteRegular.otf);
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: black;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#streamchat {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
max-width: 960px;
|
||||||
|
margin: 0 auto;
|
||||||
|
margin-top: -1%;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#stream {
|
||||||
|
width: 960px;
|
||||||
|
height: 540px;
|
||||||
|
margin-right: 0.3em;
|
||||||
|
margin-left: -40%;
|
||||||
|
margin-top: 5%;
|
||||||
|
margin-bottom: 20%;
|
||||||
|
font-size: 250%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#streamframe {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#chatbox {
|
||||||
|
flex: 1;
|
||||||
|
height: 53rem;
|
||||||
|
margin-left: 0.3em;
|
||||||
|
margin-right: -30%;
|
||||||
|
margin-top: -8%;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation-list {
|
||||||
|
display: inline-flex;
|
||||||
|
list-style-type: none;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0;
|
||||||
|
margin-left: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
width: 150px;
|
||||||
|
background-color: #55CDFC;
|
||||||
|
margin: auto;
|
||||||
|
margin-bottom: 2%;
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: center;
|
||||||
|
opacity: 0.8;
|
||||||
|
font-size: larger;
|
||||||
|
color: black;
|
||||||
|
padding: 15px;
|
||||||
|
border-bottom: solid;
|
||||||
|
border-left: solid;
|
||||||
|
border-color: lightblue;
|
||||||
|
border-width: 2px;
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ form {
|
||||||
}
|
}
|
||||||
|
|
||||||
#box {
|
#box {
|
||||||
background-color: white;
|
background-color: rgb(255, 199, 207);
|
||||||
padding: 5%;
|
padding: 5%;
|
||||||
box-shadow: 10px 10px 10px black;
|
box-shadow: 10px 10px 10px black;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
@ -25,6 +25,10 @@ form {
|
||||||
padding-top: 1%;
|
padding-top: 1%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#logoutlink {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
font-family: "Lucida Console", "Courier New", monospace;
|
font-family: "Lucida Console", "Courier New", monospace;
|
||||||
}
|
}
|
|
@ -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>
|
||||||
|
|
||||||
|
@ -15,22 +15,27 @@
|
||||||
|
|
||||||
<h1>Welcome to the chat!</h1>
|
<h1>Welcome to the chat!</h1>
|
||||||
|
|
||||||
<div id="chatbox">
|
<div id="outerchatbox">
|
||||||
|
|
||||||
<div id="innerchatbox">
|
<div id="chatbox">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form autocomplete="off">
|
<form autocomplete="off">
|
||||||
<label for="message">Input Message Here:</label>
|
|
||||||
<input type="text" id="message" name="message" required>
|
<input type="text" id="message" name="message" required>
|
||||||
|
<label for="message">Input Message Above</label>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="loggeduser"></div>
|
<div id="loggeduser"></div>
|
||||||
|
|
||||||
<script src="chat.js"></script>
|
<button type="button" id="logoutbutton" onclick="logout()">Logout</button>
|
||||||
|
|
||||||
|
<div id="errormessage"></div>
|
||||||
|
|
||||||
|
<script src="../js/chat.js"></script>
|
||||||
|
<script src="../js/logout.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
@ -24,12 +24,12 @@
|
||||||
|
|
||||||
<label for="selected">Pronouns:</label><br>
|
<label for="selected">Pronouns:</label><br>
|
||||||
<select id="selected" name="selected">
|
<select id="selected" name="selected">
|
||||||
<option value="nothing"></option>
|
<option value="none"></option>
|
||||||
<option value="she.her">she/her</option>
|
<option value="she/her">she/her</option>
|
||||||
<option value="he.him">he/him</option>
|
<option value="he/him">he/him</option>
|
||||||
<option value="they.them">they/them</option>
|
<option value="they/them">they/them</option>
|
||||||
<option value="it.its">it/its</option>
|
<option value="it/its">it/its</option>
|
||||||
<option value="fae.faer">fae/faer</option>
|
<option value="fae/faer">fae/faer</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<p>Or.</p>
|
<p>Or.</p>
|
||||||
|
@ -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>
|
|
@ -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>
|
|
@ -1,34 +1,73 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>Maya's Stream</title>
|
<title>Maya's Stream</title>
|
||||||
<meta name="author" content="Luna">
|
<meta name="author" content="Luna">
|
||||||
<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="stream.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>
|
||||||
<nav>
|
<nav>
|
||||||
|
|
||||||
<a href="register.html">Register Page</a>
|
<ul class="navigation-list">
|
||||||
|
<li><a href="index.html">
|
||||||
|
<div class="buttons">Stream</div>
|
||||||
|
</a></li>
|
||||||
|
<li><a href="/html/chat.html">
|
||||||
|
<div class="buttons">Just Chat</div>
|
||||||
|
</a></li>
|
||||||
|
<li><a href="/html/register.html">
|
||||||
|
<div class="buttons">Register</div>
|
||||||
|
</a></li>
|
||||||
|
<li><a href="/html/login.html">
|
||||||
|
<div class="buttons">Login</div>
|
||||||
|
</a></li>
|
||||||
|
<li><a href="/html/updateinfo.html">
|
||||||
|
<div class="buttons">Update Info</div>
|
||||||
|
</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<a href="login.html">Login Page</a>
|
|
||||||
|
|
||||||
<a href="updateinfo.html">Update Info Page</a>
|
</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>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
|
||||||
|
<div id="streamchat">
|
||||||
|
<div id="stream">
|
||||||
|
<iframe id="streamframe" src="https://live.on.chaos.stream/maya" title="mayas stream"
|
||||||
|
scrolling="no"></iframe>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<iframe id="chatbox" src="/html/chat.html" title="chat box" scrolling="no"></iframe>
|
||||||
|
|
||||||
</nav>
|
|
||||||
<div id="streamchat">
|
|
||||||
<div id="stream">
|
|
||||||
<h1>Test Text</h1>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<iframe id="chatbox" src="chat.html" title="chat box"></iframe>
|
</section>
|
||||||
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
</main>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,148 @@
|
||||||
|
// VARIABLES
|
||||||
|
let messageCount = 0;
|
||||||
|
let username = localStorage.getItem('username');
|
||||||
|
const form = document.querySelector('form');
|
||||||
|
|
||||||
|
// SEND A MESSAGE
|
||||||
|
|
||||||
|
// GRABS MESSAGE FROM FORM & SENDS
|
||||||
|
form.addEventListener("submit", async function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
const formData = new FormData(form);
|
||||||
|
|
||||||
|
formMessage = formData.get('message').toString();
|
||||||
|
|
||||||
|
//KINDA UNNECESSARY
|
||||||
|
//CHECKS TO SEE IF THE PERSON IS LOGGED IN IN ORDER TO SEND A MESSAGE.
|
||||||
|
const response = await fetch(`../api/token/${username}/`);
|
||||||
|
const matches = await response.json();
|
||||||
|
|
||||||
|
//YES THIS IS CONFUSING I KNOW.
|
||||||
|
if (matches.status === "ok") {
|
||||||
|
sendMessage()
|
||||||
|
} else {
|
||||||
|
const mismatch = 'Username and token mismatch. Try logging in again.'
|
||||||
|
printText(mismatch.bold())
|
||||||
|
logout()
|
||||||
|
localStorage.removeItem('username')
|
||||||
|
form.reset()
|
||||||
|
}
|
||||||
|
return formMessage;
|
||||||
|
})
|
||||||
|
|
||||||
|
//SEND MESSAGE FETCH FUNCTION
|
||||||
|
|
||||||
|
async function sendMessage() {
|
||||||
|
sendMessageInfo = { "name": username, "body": formMessage }
|
||||||
|
fetch('../api/message/send', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(sendMessageInfo),
|
||||||
|
})
|
||||||
|
form.reset()
|
||||||
|
modCommand()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// RECIEVE MESSAGES
|
||||||
|
|
||||||
|
let messageUpdate = window.setInterval(fetchMessages, 1000);
|
||||||
|
|
||||||
|
async function fetchMessages() {
|
||||||
|
const response = await fetch('/api/message/messages.json');
|
||||||
|
const recievedMessages = await response.json();
|
||||||
|
document.getElementById("chatbox").innerHTML = ""
|
||||||
|
|
||||||
|
for (const message of recievedMessages) {
|
||||||
|
|
||||||
|
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>");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (recievedMessages.length != messageCount) {
|
||||||
|
let scroll = document.getElementById("chatbox");
|
||||||
|
scroll.scrollTop = scroll.scrollHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
messageCount = recievedMessages.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FUNCTION TO PRINT MESSAGES IN THE CHAT BOX
|
||||||
|
|
||||||
|
function printText(text) {
|
||||||
|
let p = document.createElement("p");
|
||||||
|
const div = document.getElementById("chatbox");
|
||||||
|
div.appendChild(p)
|
||||||
|
p.innerHTML = text
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//LOGGED IN STUFF
|
||||||
|
//TODO ADD CHECK TO SEE IF USERNAME AND TOKEN MATCHES
|
||||||
|
function loggedIn() {
|
||||||
|
if (username === '' || username === null) {
|
||||||
|
document.querySelector("#loggeduser").innerHTML = 'You are not logged in'
|
||||||
|
} else {
|
||||||
|
document.querySelector("#loggeduser").innerHTML = `You are logged in as "${username}"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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?')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
let uname = document.querySelector('#uname').value;
|
let uname = document.querySelector('#uname').value;
|
||||||
let pin = document.querySelector('#pin').value;
|
let pin = document.querySelector('#pin').value;
|
||||||
const form = document.querySelector('form');
|
const form = document.querySelector('form');
|
||||||
|
let username = localStorage.getItem('username');
|
||||||
|
|
||||||
// SUBMIT FORM FUNCTION. AND FETCH USERNAME AND PIN FROM API.
|
// SUBMIT FORM FUNCTION. AND FETCH USERNAME AND PIN FROM API.
|
||||||
|
|
||||||
|
@ -14,24 +15,43 @@ form.addEventListener("submit", async function (event) {
|
||||||
uname = formData.get('uname');
|
uname = formData.get('uname');
|
||||||
pin = formData.get('pin');
|
pin = formData.get('pin');
|
||||||
|
|
||||||
const response = await fetch(`/api/users/${uname}/${pin}`);
|
try {
|
||||||
const loginInfo = await response.json();
|
const loginInfo = await loginFetch();
|
||||||
|
|
||||||
if (loginInfo.status === "ok") {
|
if (loginInfo.status === 'ok') {
|
||||||
login()
|
login()
|
||||||
} else {
|
} else {
|
||||||
incorrectLogin()
|
incorrectLogin()
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
document.querySelector("#errormessage").innerHTML = 'An Error has Occurred. Try again later. ' + e.toString();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// LOGIN FETCH
|
||||||
|
|
||||||
|
async function loginFetch() {
|
||||||
|
let sendLoginInfo = { "name": uname, "pin": pin }
|
||||||
|
const res = await fetch('/api/login/', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(sendLoginInfo),
|
||||||
|
});
|
||||||
|
return await res.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// FUNCTIONS FOR WHETHER THE LOGIN WAS A SUCCESS OR FAILURE
|
// FUNCTIONS FOR WHETHER THE LOGIN WAS A SUCCESS OR FAILURE
|
||||||
|
|
||||||
function login() {
|
function login() {
|
||||||
console.log('You have logged in!')
|
|
||||||
document.querySelector("#username").innerHTML = `Logged in as ${uname}`
|
|
||||||
document.querySelector("#errormessage").innerHTML = ''
|
document.querySelector("#errormessage").innerHTML = ''
|
||||||
localStorage.setItem("username", `${uname}`);
|
localStorage.setItem('username', `${uname}`);
|
||||||
|
document.querySelector("#username").innerHTML = `Logged in as ${uname}`
|
||||||
|
window.location.replace("/index.html")
|
||||||
}
|
}
|
||||||
|
|
||||||
function incorrectLogin() {
|
function incorrectLogin() {
|
|
@ -0,0 +1,32 @@
|
||||||
|
// // //VARIBLES
|
||||||
|
// myStorage = window.localStorage;
|
||||||
|
// allCookies = document.cookie;
|
||||||
|
|
||||||
|
//LOGOUT FETCH FUNCTION
|
||||||
|
|
||||||
|
async function logout() {
|
||||||
|
let sendLogoutInfo = { "name": username }
|
||||||
|
fetch('/api/logout/', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(sendLogoutInfo),
|
||||||
|
});
|
||||||
|
document.querySelector("#errormessage").innerHTML = 'Logged out.'
|
||||||
|
document.getElementById("logoutbutton").style.display = "none";
|
||||||
|
localStorage.removeItem('username')
|
||||||
|
username = null;
|
||||||
|
loggedIn()
|
||||||
|
}
|
||||||
|
|
||||||
|
// // IF THERE IS A TOKEN BUT NO USERNAME LOGOUT
|
||||||
|
// if (allCookies !== '' && myStorage.length === 0) {
|
||||||
|
// logout()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // IF THERE IS NO COOKIE BUT A USERNAME GET RID OF USERNAME LOCALLY.
|
||||||
|
// if (allCookies === '' && myStorage.length !== 0) {
|
||||||
|
// localStorage.removeItem('username')
|
||||||
|
// document.querySelector("#loggeduser").innerHTML = 'You are not logged in'
|
||||||
|
// }
|
|
@ -0,0 +1,82 @@
|
||||||
|
|
||||||
|
//DECLARING VARIABLES AND GRABBING VALUES FROM FORM.
|
||||||
|
|
||||||
|
let uname = document.querySelector('#uname').value;
|
||||||
|
let pin = document.querySelector('#pin').value;
|
||||||
|
let selected = document.querySelector('#selected').value;
|
||||||
|
let custom = document.querySelector('#custom').value;
|
||||||
|
let pronouns = ''
|
||||||
|
const form = document.querySelector('form');
|
||||||
|
|
||||||
|
//SUBMIT FUNCTION & CHECKING IF USERNAME IS TAKEN
|
||||||
|
|
||||||
|
form.addEventListener("submit", async function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
const formData = new FormData(form);
|
||||||
|
|
||||||
|
uname = formData.get('uname');
|
||||||
|
pin = formData.get('pin');
|
||||||
|
selected = formData.get('selected');
|
||||||
|
custom = formData.get('custom')
|
||||||
|
|
||||||
|
if (custom === '' && selected === 'none') {
|
||||||
|
pronouns = ''
|
||||||
|
} else if (custom !== '') {
|
||||||
|
pronouns = custom
|
||||||
|
} else {
|
||||||
|
pronouns = selected
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//IF THE API SUCCESSFULLY REGISTERS A USER THEN DO THIS
|
||||||
|
try {
|
||||||
|
const regRes = await isUnameTaken();
|
||||||
|
|
||||||
|
if (regRes == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (regRes.status === 'ok') {
|
||||||
|
document.querySelector("#errormessage").innerHTML = 'Registered!'
|
||||||
|
window.location.replace("../html/login.html")
|
||||||
|
} else {
|
||||||
|
document.querySelector("#errormessage").innerHTML = 'Failed to register. Try again later.'
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
document.querySelector("#errormessage").innerHTML = 'An Error has Occurred. Try again later. ' + e.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
//CHECKS IF A USERNAME IS TAKEN
|
||||||
|
async function isUnameTaken() {
|
||||||
|
|
||||||
|
const response = await fetch(`/api/users/${uname}/`);
|
||||||
|
const isTaken = await response.json();
|
||||||
|
|
||||||
|
//YES THIS IS CONFUSING I KNOW.
|
||||||
|
if (isTaken.status === "fail") {
|
||||||
|
return await register()
|
||||||
|
} else {
|
||||||
|
document.querySelector('#errormessage').innerHTML = `${uname} is already taken.`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//FETCH FUNCTIONS. GETTING USERNAME FROM API & REGISTERING USER ASSIGNED NAME AND PIN.
|
||||||
|
|
||||||
|
async function register() {
|
||||||
|
let sendRegisterInfo = { "name": uname, "pin": pin, "pronouns": pronouns }
|
||||||
|
const response = await fetch('../api/register/', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(sendRegisterInfo),
|
||||||
|
});
|
||||||
|
return await response.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
// function errorMessage() {
|
||||||
|
// document.querySelector("#errormessage").innerHTML = 'An error has occurrred. Please try again later.'
|
||||||
|
// }
|
|
@ -8,7 +8,6 @@ let newPin = document.querySelector('#newpin').value;
|
||||||
const form = document.querySelector('form');
|
const form = document.querySelector('form');
|
||||||
let selected = document.querySelector('#selected').value;
|
let selected = document.querySelector('#selected').value;
|
||||||
let custom = document.querySelector('#custom').value;
|
let custom = document.querySelector('#custom').value;
|
||||||
let responseText;
|
|
||||||
let updateEvent = ''
|
let updateEvent = ''
|
||||||
let newEvent = ''
|
let newEvent = ''
|
||||||
let newPronouns = ''
|
let newPronouns = ''
|
||||||
|
@ -27,6 +26,8 @@ form.addEventListener("submit", async function (event) {
|
||||||
selected = formData.get('selected');
|
selected = formData.get('selected');
|
||||||
custom = formData.get('custom')
|
custom = formData.get('custom')
|
||||||
|
|
||||||
|
|
||||||
|
//SETS NEWPRONOUNS DEPENDING ON WHAT THE USER SELECTED/TYPED
|
||||||
if (custom === '' && selected === 'none') {
|
if (custom === '' && selected === 'none') {
|
||||||
newPronouns = ''
|
newPronouns = ''
|
||||||
} else if (custom !== '') {
|
} else if (custom !== '') {
|
||||||
|
@ -35,79 +36,116 @@ form.addEventListener("submit", async function (event) {
|
||||||
newPronouns = selected
|
newPronouns = selected
|
||||||
}
|
}
|
||||||
|
|
||||||
//CHECKS IF THE USER IS CHANGING MORE THAN ONE TEXT FIELD AT A TIME
|
unameCheck()
|
||||||
let onlyChangeOne = document.querySelector("#errormessage").innerHTML = 'You can only change one at a time!'
|
|
||||||
|
//CHECKS IF THE USER IS CHANGING MORE THAN ONE TEXT FIELD AT A TIME
|
||||||
if (newUname !== '' && newPin !== '') {
|
if (newUname !== '' && newPin !== '') {
|
||||||
onlyChangeOne
|
document.querySelector("#errormessage").innerHTML = 'You can only change one at a time!'
|
||||||
|
return;
|
||||||
} else if (newUname !== '' && newPronouns !== '') {
|
} else if (newUname !== '' && newPronouns !== '') {
|
||||||
onlyChangeOne
|
document.querySelector("#errormessage").innerHTML = 'You can only change one at a time!'
|
||||||
|
return;
|
||||||
} else if (newPin !== '' && newPronouns !== '') {
|
} else if (newPin !== '' && newPronouns !== '') {
|
||||||
onlyChangeOne
|
document.querySelector("#errormessage").innerHTML = 'You can only change one at a time!'
|
||||||
|
return;
|
||||||
|
} else if (newUname !== '' && newPin !== '' && newPronouns !== '') {
|
||||||
|
document.querySelector("#errormessage").innerHTML = 'You can only change one at a time!'
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
checkLoginInfo()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ASSIGNS VARIABLES TO BE SENT TO API
|
// ASSIGNS VARIABLES TO BE SENT TO API
|
||||||
if (newUname === '' && newPin === '' && newPronouns !== '') {
|
if (newUname === '' && newPin === '' && newPronouns !== '') {
|
||||||
newEvent = newPronouns
|
newEvent = newPronouns
|
||||||
updateEvent = 'pronouns'
|
updateEvent = 'Pronouns'
|
||||||
} else if (newUname === '' && newPronouns === '' && newPin !== '') {
|
} else if (newUname === '' && newPronouns === '' && newPin !== '') {
|
||||||
newEvent = newPin
|
newEvent = newPin
|
||||||
updateEvent = 'pin'
|
updateEvent = 'Pin'
|
||||||
} else if (newPin === '' && newPronouns === '' && newUname !== '') {
|
} else if (newPin === '' && newPronouns === '' && newUname !== '') {
|
||||||
newEvent = newUname
|
newEvent = newUname
|
||||||
updateEvent = 'name'
|
updateEvent = 'Name'
|
||||||
} else if (newPin === '' && newUname === '' && newPronouns === '') {
|
} else if (newPin === '' && newUname === '' && newPronouns === '') {
|
||||||
document.querySelector("#errormessage").innerHTML = 'Please enter a new name, pin, or pronouns!'
|
document.querySelector("#errormessage").innerHTML = 'Please enter a new name, pin, or pronouns!'
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
checkLoginInfo()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//CHECKS IF USERNAME IS TAKEN
|
|
||||||
const isTaken = await getUname();
|
|
||||||
|
|
||||||
if (isTaken.status === 'ok') {
|
//IF THE API SUCCESSFULLY UPDATES INFO FOR A USER THEN DO THIS
|
||||||
document.querySelector("#errormessage").innerHTML = `username ${newUname} is already taken! `
|
try {
|
||||||
|
const updateResponse = await loginStatus();
|
||||||
|
|
||||||
|
if (updateResponse == null) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (updateResponse.status === 'ok') {
|
||||||
|
document.querySelector("#errormessage").innerHTML = 'Login Changed!'
|
||||||
|
window.location.replace("../html/login.html")
|
||||||
|
} else {
|
||||||
|
document.querySelector("#errormessage").innerHTML = 'Failed to update info. Try again later.'
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
document.querySelector("#errormessage").innerHTML = 'An Error has Occurred. Try again later. ' + e.toString();
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
//CHECKS IF A USERNAME IS TAKEN
|
||||||
|
async function unameCheck(){
|
||||||
|
if (newUname !== '') {
|
||||||
|
const response = await fetch(`api/users/${newUname}/`);
|
||||||
|
const isTaken = await response.json();
|
||||||
|
|
||||||
// FETCH FUNTIONS. FETCHING USERNAME TO SEE IF ITS TAKEN.
|
if (isTaken.status === "ok") {
|
||||||
|
document.querySelector('#errormessage').innerHTML = `${newUname} is already taken.`
|
||||||
async function getUname() {
|
return;
|
||||||
let response = await fetch(`/api/users/${newUname}`);
|
} else {
|
||||||
responseJson = await response.json();
|
}
|
||||||
return responseJson;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//CHECKS IF THE LOGIN IS A SUCCESS
|
||||||
|
async function loginStatus() {
|
||||||
|
const loginInfo = await checkLoginInfo();
|
||||||
|
|
||||||
//FETCH FUNCTION TO UPDATE USER INFO
|
if (loginInfo.status === 'ok') {
|
||||||
|
return await updateInfo()
|
||||||
//TODO ADD CHECKING THE TOKEN with LOGIN IN IF STATEMENT
|
|
||||||
//CHECKING IF THE USER CAN LOGIN WITH GIVEN CURRENT USERNAME AND PIN
|
|
||||||
async function checkLoginInfo() {
|
|
||||||
const response = await fetch(`/api/users/${uname}/${pin}`);
|
|
||||||
const loginInfo = await response.json();
|
|
||||||
|
|
||||||
if (loginInfo.status === "ok") {
|
|
||||||
updateInfo()
|
|
||||||
} else {
|
} else {
|
||||||
incorrectLogin()
|
incorrectLogin()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO ADD CHECKING THE TOKEN WITH LOGIN IN IF STATEMENT
|
||||||
|
//CHECKING IF THE USER CAN LOGIN WITH GIVEN CURRENT USERNAME AND PIN
|
||||||
|
// LOGIN FETCH
|
||||||
|
|
||||||
|
async function checkLoginInfo() {
|
||||||
|
let sendLoginInfo = { "name": uname, "pin": pin }
|
||||||
|
const res = await fetch('/api/login/', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(sendLoginInfo),
|
||||||
|
});
|
||||||
|
return await res.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
//FETCH FUNCTION TO UPDATE USER INFO
|
||||||
|
|
||||||
async function updateInfo() {
|
async function updateInfo() {
|
||||||
let sendUpdateInfo = { "name": uname, "pin": pin, "changed_event": updateEvent, "new_event": newEvent }
|
let sendUpdateInfo = { "name": uname, "pin": pin, "changed_event": updateEvent, "new_event": newEvent }
|
||||||
fetch('/api/users/change', {
|
const response = await fetch('/api/change', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify(sendUpdateInfo),
|
body: JSON.stringify(sendUpdateInfo),
|
||||||
});
|
});
|
||||||
//document.querySelector("#errormessage").innerHTML = 'Login Changed!'
|
return await response.json()
|
||||||
//window.location.replace("/login.html")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function incorrectLogin() {
|
function incorrectLogin() {
|
|
@ -1,62 +0,0 @@
|
||||||
|
|
||||||
//DECLARING VARIABLES AND GRABBING VALUES FROM FORM.
|
|
||||||
|
|
||||||
let uname = document.querySelector('#uname').value;
|
|
||||||
let pin = document.querySelector('#pin').value;
|
|
||||||
let selected = document.querySelector('#selected').value;
|
|
||||||
let custom = document.querySelector('#custom').value;
|
|
||||||
let pronouns = ''
|
|
||||||
let responseText;
|
|
||||||
const form = document.querySelector('form');
|
|
||||||
|
|
||||||
//SUBMIT FUNCTION &CHECKING IF USERNAME IS TAKEN
|
|
||||||
|
|
||||||
form.addEventListener("submit", async function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
const formData = new FormData(form);
|
|
||||||
|
|
||||||
uname = formData.get('uname');
|
|
||||||
pin = formData.get('pin');
|
|
||||||
selected = formData.get('selected');
|
|
||||||
custom = formData.get('custom')
|
|
||||||
|
|
||||||
if (custom !== '') {
|
|
||||||
pronouns = custom
|
|
||||||
} else {
|
|
||||||
pronouns = selected
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const isNotTaken = await getUname();
|
|
||||||
|
|
||||||
if (isNotTaken.status === "fail") {
|
|
||||||
register()
|
|
||||||
} else {
|
|
||||||
document.querySelector("#errormessage").innerHTML = `${uname} is already taken.`
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
document.querySelector("#errormessage").innerHTML = 'An Error has Occurred. Try again later.'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
//FETCH FUNCTIONS. GETTING USERNAME FROM API & REGISTERING USER ASSIGNED NAME AND PIN.
|
|
||||||
|
|
||||||
async function getUname() {
|
|
||||||
let response = await fetch(`/api/users/${uname}`);
|
|
||||||
responseJson = await response.json();
|
|
||||||
return responseJson;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function register() {
|
|
||||||
let sendRegisterInfo = { "name": uname, "pin": pin, "pronouns": pronouns }
|
|
||||||
fetch('/api/register/', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify(sendRegisterInfo),
|
|
||||||
});
|
|
||||||
document.querySelector("#errormessage").innerHTML = 'Registered!'
|
|
||||||
window.location.replace("/login.html")
|
|
||||||
}
|
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
138
src/auth.rs
138
src/auth.rs
|
@ -1,4 +1,5 @@
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
use uuid::Uuid;
|
||||||
use crate::file_io::*;
|
use crate::file_io::*;
|
||||||
use rocket::http::{Cookie, Cookies};
|
use rocket::http::{Cookie, Cookies};
|
||||||
use crate::user::*;
|
use crate::user::*;
|
||||||
|
@ -19,14 +20,18 @@ pub fn register(data: Json<RegisterEvent>) -> JsonValue {
|
||||||
} else {
|
} else {
|
||||||
let pin_hashed = sha1::Sha1::from(&data.pin).digest().to_string(); // hash the pin
|
let pin_hashed = sha1::Sha1::from(&data.pin).digest().to_string(); // hash the pin
|
||||||
|
|
||||||
let new_user: User = User {
|
let mut new_user: User = User {
|
||||||
name: data.name.to_string().to_lowercase(),
|
name: data.name.to_string().to_lowercase(),
|
||||||
pin_hashed,
|
pin_hashed,
|
||||||
pronouns: data.pronouns.to_string().to_lowercase(),
|
pronouns: data.pronouns.to_string().to_lowercase(),
|
||||||
session_token: "NULL".to_string(),
|
session_token: "NULL".to_string(),
|
||||||
role: UserType::Normal,
|
role: UserType::Normal,
|
||||||
|
id: Uuid::new_v4(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if new_user.name == "admin".to_string() { // if name is admin, make them an admin
|
||||||
|
new_user.role = UserType::Admin;
|
||||||
|
}
|
||||||
db_add(&new_user);
|
db_add(&new_user);
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
|
@ -272,6 +277,7 @@ pub fn get_user(name: String) -> JsonValue {
|
||||||
"name": user.name.to_lowercase(),
|
"name": user.name.to_lowercase(),
|
||||||
"pronouns": user.pronouns,
|
"pronouns": user.pronouns,
|
||||||
"role": user.role,
|
"role": user.role,
|
||||||
|
"id": user.id.to_string(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -281,6 +287,117 @@ pub fn get_user(name: String) -> JsonValue {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Make a user into a moderator
|
||||||
|
fn premote(name: &str) -> JsonValue {
|
||||||
|
if let Some(mut user) = db_read_user(&name.to_lowercase()).ok().flatten() {
|
||||||
|
if user.role != UserType::Admin { // make sure mods can't demote admins ;3
|
||||||
|
user.role = UserType::Moderator;
|
||||||
|
db_remove(&user);
|
||||||
|
db_add(&user);
|
||||||
|
info!("succesfully premoted user {}", &user.name);
|
||||||
|
return json!({
|
||||||
|
"status": "ok",
|
||||||
|
"reason": "premoted user",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
warn!("user is an admin, cannot make moderator");
|
||||||
|
return json!({
|
||||||
|
"status": "fail",
|
||||||
|
"reason": "user is admin",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("could not premote {}, user not found", &name);
|
||||||
|
return json!({
|
||||||
|
"status": "fail",
|
||||||
|
"reason": "user not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a user into a normal user
|
||||||
|
fn demote(name: &str) -> JsonValue {
|
||||||
|
if let Some(mut user) = db_read_user(&name.to_lowercase()).ok().flatten() {
|
||||||
|
if user.role != UserType::Admin { // make sure mods can't demote admins ;3
|
||||||
|
user.role = UserType::Normal;
|
||||||
|
db_remove(&user);
|
||||||
|
db_add(&user);
|
||||||
|
info!("succesfully demoted user {}", &user.name);
|
||||||
|
return json!({
|
||||||
|
"status": "ok",
|
||||||
|
"reason": "demoted user",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
warn!("user is an admin, cannot demote");
|
||||||
|
return json!({
|
||||||
|
"status": "fail",
|
||||||
|
"reason": "user is admin",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("could not demote {}, user not found", &name);
|
||||||
|
return json!({
|
||||||
|
"status": "fail",
|
||||||
|
"reason": "user not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kick a user (temporarilly log them out for a certain amount of time)
|
||||||
|
fn kick(name: &str) -> JsonValue {
|
||||||
|
if let Some(mut user) = db_read_user(&name.to_lowercase()).ok().flatten() {
|
||||||
|
if user.role != UserType::Admin { // make sure mods can't kick admins
|
||||||
|
user.session_token = "NULL".to_string();
|
||||||
|
db_remove(&user);
|
||||||
|
db_add(&user);
|
||||||
|
info!("succesfully kicked user {}", &user.name);
|
||||||
|
return json!({
|
||||||
|
"status": "ok",
|
||||||
|
"reason": "kicked user",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
warn!("user is an admin, cannot kick");
|
||||||
|
return json!({
|
||||||
|
"status": "fail",
|
||||||
|
"reason": "user is admin",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("could not kick {}, user not found", &name);
|
||||||
|
return json!({
|
||||||
|
"status": "fail",
|
||||||
|
"reason": "user not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ban a user (remove their account)
|
||||||
|
fn ban(name: &str) -> JsonValue {
|
||||||
|
if let Some(mut user) = db_read_user(&name.to_lowercase()).ok().flatten() {
|
||||||
|
if user.role != UserType::Admin { // make sure mods can't kick admins
|
||||||
|
db_remove(&user);
|
||||||
|
info!("succesfully banned user {}", &user.name);
|
||||||
|
return json!({
|
||||||
|
"status": "ok",
|
||||||
|
"reason": "banned user",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
warn!("user is an admin, cannot ban");
|
||||||
|
return json!({
|
||||||
|
"status": "fail",
|
||||||
|
"reason": "user is admin",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("could not ban {}, user not found", &name);
|
||||||
|
return json!({
|
||||||
|
"status": "fail",
|
||||||
|
"reason": "user not found",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* User Management */
|
/* User Management */
|
||||||
#[post("/mod", format = "json", data = "<data>")]
|
#[post("/mod", format = "json", data = "<data>")]
|
||||||
|
@ -303,18 +420,15 @@ pub fn moderation_actions(data: Json<ModerationAction>, mut cookies: Cookies) ->
|
||||||
"reason": "NULL token",
|
"reason": "NULL token",
|
||||||
});
|
});
|
||||||
} else if user.session_token == token.value() { // if token matches
|
} else if user.session_token == token.value() { // if token matches
|
||||||
if user.role == UserType::Normal {
|
if user.role == UserType::Moderator || user.role == UserType::Admin {
|
||||||
match data.action {
|
match data.action {
|
||||||
ModActions::Kick => {
|
ModActions::Kick => kick(&data.target),
|
||||||
info!("kicked user {}", data.target)
|
ModActions::Ban => ban(&data.target),
|
||||||
},
|
ModActions::Demote => demote(&data.target),
|
||||||
ModActions::Ban => info!("banned user {}", data.target),
|
ModActions::Premote => premote(&data.target),
|
||||||
_ => info!("F"),
|
_ => return json!({"status":"fail","reason":"bad command"}),
|
||||||
};
|
};
|
||||||
return json!({
|
return json!({"status":"fail","reason":"idk"});
|
||||||
"status": "ok",
|
|
||||||
"reason": "completed action",
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
warn!("user does not have sufficient permissions to perform that action!");
|
warn!("user does not have sufficient permissions to perform that action!");
|
||||||
return json!({
|
return json!({
|
||||||
|
|
|
@ -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(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -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>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
/* User Data */
|
/* User Data */
|
||||||
// enum of different user types
|
// enum of different user types
|
||||||
|
@ -17,6 +18,7 @@ pub struct User {
|
||||||
pub pronouns: String, // user's pronouns
|
pub pronouns: String, // user's pronouns
|
||||||
pub session_token: String, // generated session token
|
pub session_token: String, // generated session token
|
||||||
pub role: UserType, // type/role of user
|
pub role: UserType, // type/role of user
|
||||||
|
pub id: Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Moderation Data */
|
/* Moderation Data */
|
||||||
|
|
Loading…
Reference in New Issue