mirror of
https://github.com/RGBCube/GDUS
synced 2025-07-28 21:47:45 +00:00
Move webserver to server/
This commit is contained in:
parent
1fa76f9a15
commit
d525fd353f
8 changed files with 11 additions and 4 deletions
20
server/.rustfmt.toml
Normal file
20
server/.rustfmt.toml
Normal file
|
@ -0,0 +1,20 @@
|
|||
condense_wildcard_suffixes = true
|
||||
control_brace_style = "ClosingNextLine"
|
||||
enum_discrim_align_threshold = 25
|
||||
force_explicit_abi = false
|
||||
force_multiline_blocks = true
|
||||
format_code_in_doc_comments = true
|
||||
format_macro_matchers = true
|
||||
format_strings = true
|
||||
hex_literal_case = "Upper"
|
||||
imports_layout = "Vertical"
|
||||
match_block_trailing_comma = true
|
||||
imports_granularity = "Crate"
|
||||
newline_style = "Unix"
|
||||
normalize_comments = true
|
||||
normalize_doc_attributes = true
|
||||
reorder_impl_items = true
|
||||
group_imports = "StdExternalCrate"
|
||||
unstable_features = true
|
||||
use_try_shorthand = true
|
||||
wrap_comments = true
|
2285
server/Cargo.lock
generated
Normal file
2285
server/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
19
server/Cargo.toml
Normal file
19
server/Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "proje"
|
||||
description = "TÜBİTAK Projesi"
|
||||
authors = [ "RGBCube" ]
|
||||
repository = "https://github.com/RGBCube/NamelessProje"
|
||||
license = "GPL"
|
||||
version = "0.0.1"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
actix-web = "4.4.0"
|
||||
chrono = "0.4.31"
|
||||
maud = { version = "0.25.0", features = [ "actix-web" ] }
|
||||
serde = { version = "1.0.192", features = [ "derive" ] }
|
||||
sqlx = { version = "0.7.3", features = [ "chrono", "sqlite", "runtime-tokio" ] }
|
||||
tokio = { version = "1.34.0", features = [ "full" ] }
|
||||
|
||||
[profile.dev]
|
||||
incremental = true
|
55
server/src/index.rs
Normal file
55
server/src/index.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
use actix_web as web;
|
||||
use maud::{
|
||||
html,
|
||||
Markup,
|
||||
DOCTYPE,
|
||||
};
|
||||
|
||||
#[web::get("/")]
|
||||
async fn index() -> web::Result<Markup> {
|
||||
Ok(html! {
|
||||
(DOCTYPE)
|
||||
|
||||
style {r#"
|
||||
body {
|
||||
font-family: sans;
|
||||
background-color: #f4f4f4;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.links {
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.links a {
|
||||
display: inline-block;
|
||||
margin: 10px;
|
||||
padding: 8px 16px;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
background-color: #4caf50;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.links a:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
"#}
|
||||
|
||||
div class="links" {
|
||||
a href="/submit" { "Hatırlatıcı Koy" }
|
||||
a href="/view" { "Hatırlatıcıları Görüntüle" }
|
||||
}
|
||||
})
|
||||
}
|
46
server/src/main.rs
Normal file
46
server/src/main.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
mod index;
|
||||
mod submit;
|
||||
mod view;
|
||||
|
||||
use std::io;
|
||||
|
||||
use actix_web as web;
|
||||
use sqlx::{
|
||||
sqlite::SqliteConnectOptions,
|
||||
SqlitePool,
|
||||
};
|
||||
|
||||
#[web::main]
|
||||
async fn main() -> io::Result<()> {
|
||||
let db = SqlitePool::connect_with(
|
||||
SqliteConnectOptions::new()
|
||||
.filename("data.db")
|
||||
.create_if_missing(true),
|
||||
)
|
||||
.await
|
||||
.expect("Failed to connect to SQLite database.");
|
||||
|
||||
sqlx::query(
|
||||
r"
|
||||
CREATE TABLE IF NOT EXISTS reminders (
|
||||
date DATETIME NOT NULL,
|
||||
message TEXT NOT NULL
|
||||
)
|
||||
",
|
||||
)
|
||||
.execute(&db)
|
||||
.await
|
||||
.expect("Failed to create table reminders.");
|
||||
|
||||
web::HttpServer::new(move || {
|
||||
web::App::new()
|
||||
.app_data(web::web::Data::new(db.clone()))
|
||||
.service(index::index)
|
||||
.service(submit::submit)
|
||||
.service(submit::submit_form)
|
||||
.service(view::view)
|
||||
})
|
||||
.bind(("127.0.0.1", 80))?
|
||||
.run()
|
||||
.await
|
||||
}
|
139
server/src/submit.rs
Normal file
139
server/src/submit.rs
Normal file
|
@ -0,0 +1,139 @@
|
|||
use actix_web as web;
|
||||
use actix_web::web::{
|
||||
Data,
|
||||
Query,
|
||||
};
|
||||
use chrono::NaiveDateTime;
|
||||
use maud::{
|
||||
html,
|
||||
Markup,
|
||||
PreEscaped,
|
||||
DOCTYPE,
|
||||
};
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub struct Reminder {
|
||||
date: String,
|
||||
message: String,
|
||||
}
|
||||
|
||||
#[web::get("/submit-form")]
|
||||
async fn submit_form(
|
||||
data: Data<SqlitePool>,
|
||||
Query(reminder): Query<Reminder>,
|
||||
) -> web::Result<Markup> {
|
||||
println!("{reminder:?}");
|
||||
|
||||
let date_time = NaiveDateTime::parse_from_str(&reminder.date, "%Y-%m-%dT%H:%M").unwrap();
|
||||
|
||||
sqlx::query(
|
||||
r"
|
||||
INSERT INTO
|
||||
reminders (date, message)
|
||||
VALUES
|
||||
(?, ?)
|
||||
",
|
||||
)
|
||||
.bind(date_time)
|
||||
.bind(reminder.message)
|
||||
.execute(&**data)
|
||||
.await
|
||||
.expect("Failed to save reminder.");
|
||||
|
||||
Ok(html! {
|
||||
(DOCTYPE)
|
||||
|
||||
style {r#"
|
||||
body {
|
||||
font-family: sans;
|
||||
background-color: #f4f4f4;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #333;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #666;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
"#}
|
||||
|
||||
h1 { "Kaydedildi." }
|
||||
p { "Ana sayfaya geri yönlendiriliyorsun..." }
|
||||
script type="text/javascript" {(PreEscaped(r#"
|
||||
setTimeout(function() { window.location.href = "/"; }, 5000);
|
||||
"#))}
|
||||
})
|
||||
}
|
||||
|
||||
#[web::get("/submit")]
|
||||
async fn submit() -> web::Result<Markup> {
|
||||
Ok(html! {
|
||||
(DOCTYPE)
|
||||
|
||||
style {r#"
|
||||
body {
|
||||
font-family: sans;
|
||||
background-color: #f4f4f4;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
form {
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
margin-bottom: 16px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #4caf50;
|
||||
color: #fff;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
"#}
|
||||
|
||||
form action="/submit-form" {
|
||||
button type="submit" { "Kaydet" }
|
||||
br;
|
||||
label for="date" { "Tarih:" }
|
||||
input type="datetime-local" id="date" name="date";
|
||||
br;
|
||||
label for="message" { "Mesaj:" }
|
||||
input id="message" name="message";
|
||||
}
|
||||
})
|
||||
}
|
126
server/src/view.rs
Normal file
126
server/src/view.rs
Normal file
|
@ -0,0 +1,126 @@
|
|||
use actix_web as web;
|
||||
use actix_web::web::Data;
|
||||
use chrono::{
|
||||
Local,
|
||||
NaiveDateTime,
|
||||
TimeZone,
|
||||
};
|
||||
use maud::{
|
||||
html,
|
||||
Markup,
|
||||
PreEscaped,
|
||||
DOCTYPE,
|
||||
};
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
#[web::get("/view")]
|
||||
async fn view(data: Data<SqlitePool>) -> web::Result<Markup> {
|
||||
let reminders = sqlx::query_as::<_, (NaiveDateTime, String)>(
|
||||
r#"
|
||||
SELECT
|
||||
date, message
|
||||
FROM
|
||||
reminders
|
||||
WHERE
|
||||
date > datetime("now")
|
||||
ORDER BY date ASC
|
||||
"#,
|
||||
)
|
||||
.fetch_all(&**data)
|
||||
.await
|
||||
.expect("Failed to fetch reminders.");
|
||||
|
||||
println!("{reminders:?}");
|
||||
|
||||
let formatted_reminders: Vec<(i64, String, String)> = reminders
|
||||
.into_iter()
|
||||
.map(|(date_time, message)| {
|
||||
let local_time = Local.from_local_datetime(&date_time).unwrap();
|
||||
(
|
||||
local_time.timestamp() as i64,
|
||||
local_time.format("%Y/%m/%d %H:%M").to_string(),
|
||||
message,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(html! {
|
||||
(DOCTYPE)
|
||||
|
||||
style {r#"
|
||||
body {
|
||||
font-family: sans;
|
||||
background-color: #f4f4f4;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul li {
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
ul li h3 {
|
||||
margin-bottom: 10px;
|
||||
font-size: 18px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
ul li p {
|
||||
color: #666;
|
||||
}
|
||||
"#}
|
||||
|
||||
ul id="reminders" {
|
||||
@for reminder in formatted_reminders {
|
||||
li {
|
||||
p class="timestamp" data-timestamp=(reminder.0) style="display: none;" {}
|
||||
h3 { (reminder.1) }
|
||||
p { (reminder.2) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
script defer {(PreEscaped(r##"
|
||||
const alertIfTime = () => {
|
||||
const reminders = Array.from(
|
||||
document
|
||||
.querySelectorAll("#reminders .timestamp")
|
||||
)
|
||||
.map(timestampItem => ({
|
||||
content: timestampItem
|
||||
.parentNode
|
||||
.querySelector("p:not(.timestamp)")
|
||||
.textContent,
|
||||
timestamp: +timestampItem.getAttribute("data-timestamp"),
|
||||
}));
|
||||
|
||||
const currentTime = Math.floor(Date.now() / 1000);
|
||||
|
||||
reminders.forEach(reminder => {
|
||||
const differenceSeconds = currentTime - reminder.timestamp;
|
||||
|
||||
if (differenceSeconds < 1 * 60) {
|
||||
// new Audio("/beep.mp3").play();
|
||||
alert("Geldi! " + reminder.content);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
alertIfTime();
|
||||
|
||||
setInterval(() => {
|
||||
location.reload();
|
||||
alertIfTime();
|
||||
}, 1 * 60 * 1000);
|
||||
"##))}
|
||||
})
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue