forked from Roflin/gamenight
		
	Initial commit
This commit is contained in:
		
						commit
						ee500203e2
					
				
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
/target
 | 
			
		||||
.vscode
 | 
			
		||||
Rocket.toml
 | 
			
		||||
*.sqlite
 | 
			
		||||
							
								
								
									
										2019
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										2019
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										18
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
[package]
 | 
			
		||||
name = "gamenight"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
authors = ["Dennis Brentjes <d.brentjes@gmail.com>"]
 | 
			
		||||
edition = "2018"
 | 
			
		||||
 | 
			
		||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
rocket = { version = "0.5.0-rc.1", features = ["default", "json"] }
 | 
			
		||||
libsqlite3-sys = { version = ">=0.8.0, <0.19.0", features = ["bundled"] }
 | 
			
		||||
rocket_sync_db_pools = { version = "0.1.0-rc.1", features =  ["diesel_sqlite_pool"] }
 | 
			
		||||
diesel = { version = "1.4.8", features = ["sqlite"] }
 | 
			
		||||
diesel_migrations = "1.4.0"
 | 
			
		||||
rocket_dyn_templates = { version = "0.1.0-rc.1", features = ["handlebars"] }
 | 
			
		||||
chrono = "0.4.19"
 | 
			
		||||
serde = "1.0.136"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								Rocket.toml.example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								Rocket.toml.example
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
#Copy this file over to Rocket.toml after changing all relevant values.
 | 
			
		||||
 | 
			
		||||
[global.databases]
 | 
			
		||||
gamenight_database = { url = "gamenight.sqlite" }
 | 
			
		||||
							
								
								
									
										4
									
								
								migrations/2022-03-19-191822_initial/down.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								migrations/2022-03-19-191822_initial/down.sql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
-- This file should undo anything in `up.sql`
 | 
			
		||||
 | 
			
		||||
drop table gamenight;
 | 
			
		||||
drop table known_games;
 | 
			
		||||
							
								
								
									
										12
									
								
								migrations/2022-03-19-191822_initial/up.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								migrations/2022-03-19-191822_initial/up.sql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
-- Your SQL goes here
 | 
			
		||||
 | 
			
		||||
CREATE TABLE gamenight (
 | 
			
		||||
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
 | 
			
		||||
    game text TEXT NOT NULL,
 | 
			
		||||
    datetime TEXT NOT NULL
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
CREATE TABLE known_games (
 | 
			
		||||
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
 | 
			
		||||
    game TEXT UNIQUE NOT NULL
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										30
									
								
								readme.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								readme.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
# Gamenight
 | 
			
		||||
 | 
			
		||||
Een online tooltje voor het organiseren van een \(board\)gamenight
 | 
			
		||||
 | 
			
		||||
Het doel, Je kan een GameNight organiseren, je geeft wanneer je zou willen spelen, je geeft aan waar je zin in hebt, welke games je hebt, en of je kan hosten. Mensen kunnen zich erbij klikken, hopelijk volgt er een spelletjes consensus, en go. 
 | 
			
		||||
 | 
			
		||||
Ik wil iets maken wat georganiseerder is dan een mailthread en minder push bericht is dan een boargame appgroep.
 | 
			
		||||
 | 
			
		||||
Geplande features:
 | 
			
		||||
* Account systeem zodat het niet allemaal publiek is.
 | 
			
		||||
* Manier om een event toe te voegen.
 | 
			
		||||
* Manier voor owners om een event te verwijderen.
 | 
			
		||||
* Lijst aan upcoming events.
 | 
			
		||||
* Lijst aan archived events
 | 
			
		||||
* Manier om te koppelen aan je account welke games je hebt, zodat dit automatisch aangevult.wordt als je een party joined,
 | 
			
		||||
* manier om comments te plaatsen op een event.
 | 
			
		||||
* manier om een of meer spellen te selecten zodat mensen dit ook daadwerkelijk meenemen en niet iedereen alles hoeft mee te nemen #QOL
 | 
			
		||||
* manier om recurring game avonden te plannen.
 | 
			
		||||
 | 
			
		||||
Meta features:
 | 
			
		||||
* Api apart van de site ontwikkelen zodat je shit kan automagiseren, zelf push berichten kan fixen als je wil via de API.
 | 
			
		||||
* Een beetje sexy website bouwen zodat hij op zijn minst bruikbaar is op je mobiel.
 | 
			
		||||
 | 
			
		||||
# Mee devven?
 | 
			
		||||
 | 
			
		||||
Graag!
 | 
			
		||||
 | 
			
		||||
Belangrijkste devding dat je moet weten is dat je diesel migrations kan genereren en invulling kan geven, deze database migraties worden automatisch uitgevoerd als je de binary daarna start, of je kan ze handmatig uitvoeren met de diesel executable zelf. Ik weet niet zeker of je diesel nog handmatig moet installeren, maar ik denk het wel `cargo install diesel`
 | 
			
		||||
 | 
			
		||||
database migration genereren: `diesel migration generate <descriptive name>`
 | 
			
		||||
							
								
								
									
										58
									
								
								src/api.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/api.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,58 @@
 | 
			
		||||
use crate::schema;
 | 
			
		||||
use rocket::form::Form;
 | 
			
		||||
use rocket::serde::json::{Json, json, Value};
 | 
			
		||||
use rocket::http::Status;
 | 
			
		||||
use rocket::request::{self, Request, FromRequest};
 | 
			
		||||
use rocket::outcome::Outcome::{Success, Failure};
 | 
			
		||||
use rocket::response::{Redirect, Flash};
 | 
			
		||||
 | 
			
		||||
pub struct Referer(String);
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub enum ReferrerError {
 | 
			
		||||
    Missing,
 | 
			
		||||
    MoreThanOne
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Responder)]
 | 
			
		||||
pub enum ApiResponse {
 | 
			
		||||
    Status(Status),
 | 
			
		||||
    Redirect(Redirect),
 | 
			
		||||
    Value(Value),
 | 
			
		||||
    Flash(Flash<Redirect>)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[rocket::async_trait]
 | 
			
		||||
impl<'r> FromRequest<'r> for Referer {
 | 
			
		||||
    type Error = ReferrerError;
 | 
			
		||||
 | 
			
		||||
    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
 | 
			
		||||
        let referers : Vec<_> = req.headers().get("Referer").collect();
 | 
			
		||||
        match referers.len() {
 | 
			
		||||
            0 => Failure((Status::BadRequest, ReferrerError::Missing)),
 | 
			
		||||
            1 => Success(Referer(referers[0].to_string())),
 | 
			
		||||
            _ => Failure((Status::BadRequest, ReferrerError::MoreThanOne)),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[get("/gamenights")]
 | 
			
		||||
pub async fn gamenights(conn: schema::DbConn) -> ApiResponse {
 | 
			
		||||
    let gamenights = schema::get_all_gamenights(conn).await;
 | 
			
		||||
    ApiResponse::Value(json!(gamenights))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[post("/gamenight", format = "application/json", data = "<gamenight_json>")]
 | 
			
		||||
pub async fn gamenight_post_json(conn: schema::DbConn, gamenight_json: Json<schema::GameNightNoId>) -> ApiResponse  {
 | 
			
		||||
    schema::insert_gamenight(conn, gamenight_json.into_inner()).await;
 | 
			
		||||
    ApiResponse::Status(Status::Accepted)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[post("/gamenight", format = "application/x-www-form-urlencoded", data = "<gamenight_form>")]
 | 
			
		||||
pub async fn gamenight_post_form(referer: Option<Referer>, conn: schema::DbConn, gamenight_form: Form<schema::GameNightNoId>) -> ApiResponse {
 | 
			
		||||
    schema::insert_gamenight(conn, gamenight_form.into_inner()).await;
 | 
			
		||||
    match referer {
 | 
			
		||||
        None => ApiResponse::Status(Status::Accepted),
 | 
			
		||||
        Some(referer) => ApiResponse::Flash(Flash::success(Redirect::to(referer.0), "Added Gamenight."))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
#[macro_use] extern crate rocket;
 | 
			
		||||
#[macro_use] extern crate diesel_migrations;
 | 
			
		||||
#[macro_use] extern crate diesel;
 | 
			
		||||
 | 
			
		||||
use rocket::fairing::AdHoc;
 | 
			
		||||
use rocket_dyn_templates::Template;
 | 
			
		||||
 | 
			
		||||
mod api;
 | 
			
		||||
pub mod schema;
 | 
			
		||||
mod site;
 | 
			
		||||
 | 
			
		||||
#[launch]
 | 
			
		||||
fn rocket() -> _ {
 | 
			
		||||
    rocket::build()
 | 
			
		||||
        .attach(schema::DbConn::fairing())
 | 
			
		||||
        .attach(Template::fairing())
 | 
			
		||||
        .attach(AdHoc::on_ignite("Run Migrations", schema::run_migrations))
 | 
			
		||||
        .mount("/", routes![site::index, site::gamenights, site::add_game_night])
 | 
			
		||||
        .mount("/api", routes![api::gamenights, api::gamenight_post_form, api::gamenight_post_json])
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										83
									
								
								src/schema.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								src/schema.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,83 @@
 | 
			
		||||
use rocket_sync_db_pools::database;
 | 
			
		||||
use serde::{Serialize, Deserialize};
 | 
			
		||||
use rocket::{Rocket, Build};
 | 
			
		||||
use diesel::RunQueryDsl;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[database("gamenight_database")]
 | 
			
		||||
pub struct DbConn(diesel::SqliteConnection);
 | 
			
		||||
 | 
			
		||||
table! {
 | 
			
		||||
    gamenight (id) {
 | 
			
		||||
        id -> Integer,
 | 
			
		||||
        game -> Text,
 | 
			
		||||
        datetime -> Text,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table! {
 | 
			
		||||
    known_games (game) {
 | 
			
		||||
        id -> Integer,
 | 
			
		||||
        game -> Text,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
allow_tables_to_appear_in_same_query!(
 | 
			
		||||
    gamenight,
 | 
			
		||||
    known_games,
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
pub async fn get_all_gamenights(conn: DbConn) -> Vec::<GameNight> {
 | 
			
		||||
    conn.run(|c| {
 | 
			
		||||
        gamenight::table.load::<GameNight>(c).unwrap()
 | 
			
		||||
    }).await
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub async fn insert_gamenight(conn: DbConn, new_gamenight: GameNightNoId) -> () {
 | 
			
		||||
    conn.run(|c| {
 | 
			
		||||
        diesel::insert_into(gamenight::table)
 | 
			
		||||
            .values(new_gamenight)
 | 
			
		||||
            .execute(c)
 | 
			
		||||
            .unwrap()
 | 
			
		||||
    }).await;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub async fn run_migrations(rocket: Rocket<Build>) -> Rocket<Build> {
 | 
			
		||||
    // This macro from `diesel_migrations` defines an `embedded_migrations`
 | 
			
		||||
    // module containing a function named `run`. This allows the example to be
 | 
			
		||||
    // run and tested without any outside setup of the database.
 | 
			
		||||
    embed_migrations!();
 | 
			
		||||
 | 
			
		||||
    let conn = DbConn::get_one(&rocket).await.expect("database connection");
 | 
			
		||||
    conn.run(|c| embedded_migrations::run(c)).await.expect("can run migrations");
 | 
			
		||||
 | 
			
		||||
    rocket
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug, FromForm, Insertable)]
 | 
			
		||||
#[table_name="known_games"]
 | 
			
		||||
pub struct GameNoId {
 | 
			
		||||
    pub game : String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug, FromForm, Queryable)]
 | 
			
		||||
pub struct Game {
 | 
			
		||||
    pub id: i32,
 | 
			
		||||
    pub game : String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug, FromForm, Insertable)]
 | 
			
		||||
#[table_name="gamenight"]
 | 
			
		||||
pub struct GameNightNoId {
 | 
			
		||||
    pub game : String,
 | 
			
		||||
    pub datetime : String, 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug, FromForm, Queryable)]
 | 
			
		||||
pub struct GameNight {
 | 
			
		||||
    pub id: i32,
 | 
			
		||||
    pub game : String,
 | 
			
		||||
    pub datetime : String, 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										57
									
								
								src/site.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/site.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,57 @@
 | 
			
		||||
use serde::{Serialize, Deserialize};
 | 
			
		||||
use rocket_dyn_templates::Template;
 | 
			
		||||
use rocket::response::{Redirect};
 | 
			
		||||
use rocket::request::{FlashMessage};
 | 
			
		||||
use crate::schema;
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug)]
 | 
			
		||||
struct FlashData {
 | 
			
		||||
    has_data: bool,
 | 
			
		||||
    kind: String,
 | 
			
		||||
    message: String
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug)]
 | 
			
		||||
struct GameNightsData {
 | 
			
		||||
    gamenights: Vec::<schema::GameNight>,
 | 
			
		||||
    flash: FlashData
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[get("/gamenights")]
 | 
			
		||||
pub async fn gamenights(conn: schema::DbConn) -> Template {
 | 
			
		||||
    let gamenights = schema::get_all_gamenights(conn).await;
 | 
			
		||||
    
 | 
			
		||||
    let data = GameNightsData {
 | 
			
		||||
        gamenights: gamenights,
 | 
			
		||||
        flash: FlashData { has_data: false, message: "".to_string(), kind: "".to_string() }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Template::render("gamenights", &data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[get("/")]
 | 
			
		||||
pub async fn index() -> Redirect {
 | 
			
		||||
    Redirect::to(uri!(gamenights))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug)]
 | 
			
		||||
struct GameNightAddData {
 | 
			
		||||
    post_url: String,
 | 
			
		||||
    flash : FlashData
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[get("/gamenight/add")]
 | 
			
		||||
pub async fn add_game_night(flash: Option<FlashMessage<'_>>) -> Template {
 | 
			
		||||
    let flash_data = match flash {
 | 
			
		||||
        None => FlashData { has_data: false, message: "".to_string(), kind: "".to_string() },
 | 
			
		||||
        Some(flash) => FlashData { has_data: true, message: flash.message().to_string(), kind: flash.kind().to_string() }
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    let data = GameNightAddData {
 | 
			
		||||
        post_url: "/api/gamenight".to_string(),
 | 
			
		||||
        flash: flash_data
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Template::render("gamenight_add", &data)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								templates/flash.html.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								templates/flash.html.hbs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
    {{#if has_data}}
 | 
			
		||||
    <div>
 | 
			
		||||
      <p>{{kind}}: {{message}}</p>
 | 
			
		||||
    </div>
 | 
			
		||||
    {{/if}}
 | 
			
		||||
							
								
								
									
										16
									
								
								templates/gamenight_add.html.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								templates/gamenight_add.html.hbs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
<html>
 | 
			
		||||
  <head>
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
 | 
			
		||||
    {{> flash flash }}
 | 
			
		||||
 | 
			
		||||
    <form action="{{post_url}}" method="post">
 | 
			
		||||
      <label for="game">Game:</label><br>
 | 
			
		||||
      <input type="text" id="game" name="game"><br>
 | 
			
		||||
      <label for="datetime">Wanneer:</label><br>
 | 
			
		||||
      <input type="text" id="datetime" name="datetime">
 | 
			
		||||
      <input type="submit" value="Submit">
 | 
			
		||||
    </form>
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										14
									
								
								templates/gamenights.html.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								templates/gamenights.html.hbs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
<html>
 | 
			
		||||
  <head>
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
    {{> flash flash }}
 | 
			
		||||
 | 
			
		||||
    {{#each gamenights}}
 | 
			
		||||
      <div>
 | 
			
		||||
        <span>game: {{this.game}}</span>
 | 
			
		||||
        <span>when: {{this.datetime}}</span>
 | 
			
		||||
      </div>
 | 
			
		||||
    {{/each}}
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user