forked from Anvilcraft/jmserver
Changed config format
This commit is contained in:
parent
e0eeccefe5
commit
408bf0b3fa
7 changed files with 97 additions and 43 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,3 +2,4 @@
|
|||
.idea
|
||||
*.iml
|
||||
Cargo.lock
|
||||
config.toml
|
|
@ -8,10 +8,12 @@ edition = "2018"
|
|||
|
||||
[dependencies]
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
axum = "0.2.1"
|
||||
axum = { version = "0.2.8", features = ["headers"] }
|
||||
tower = { version = "0.4", features = ["util", "timeout"] }
|
||||
tower-http = { version = "0.1", features = ["add-extension", "trace"] }
|
||||
tower-http = { version = "0.1", features = ["add-extension", "trace", "fs", "set-header"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0.51"
|
||||
sqlx = { version = "0.3", features = [ "mysql" ] }
|
||||
rand = "0.8.0"
|
||||
structopt = "0.3.22"
|
||||
toml = "0.5.8"
|
29
src/config.rs
Normal file
29
src/config.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
use std::net::SocketAddr;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Config {
|
||||
pub addr: SocketAddr,
|
||||
pub database: String,
|
||||
pub cdn: String,
|
||||
}
|
||||
|
||||
pub struct ConfVars {
|
||||
pub cdn: String,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
|
||||
pub fn vars(&self) -> ConfVars {
|
||||
ConfVars {
|
||||
cdn: self.cdn.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Clone for ConfVars {
|
||||
fn clone(&self) -> Self {
|
||||
Self { cdn: self.cdn.clone() }
|
||||
}
|
||||
}
|
37
src/main.rs
37
src/main.rs
|
@ -1,25 +1,42 @@
|
|||
use std::{io, env};
|
||||
use std::{env, io, path::PathBuf};
|
||||
use config::Config;
|
||||
use sqlx::MySqlPool;
|
||||
use std::net::SocketAddr;
|
||||
use axum::Router;
|
||||
use tower_http::add_extension::AddExtensionLayer;
|
||||
use structopt::StructOpt;
|
||||
use axum::{Router, body::Body, http::{HeaderValue, Request, header}};
|
||||
use tower_http::{add_extension::AddExtensionLayer, set_header::SetResponseHeaderLayer};
|
||||
|
||||
mod v1;
|
||||
mod config;
|
||||
|
||||
#[derive(StructOpt)]
|
||||
struct Opt {
|
||||
#[structopt(
|
||||
short,
|
||||
long,
|
||||
help = "config file to use",
|
||||
default_value = "./config.toml"
|
||||
)]
|
||||
config: PathBuf,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
|
||||
let database_url = env::var("DBURL").unwrap();
|
||||
let db_pool = MySqlPool::new(&database_url).await.unwrap();
|
||||
let opt = Opt::from_args();
|
||||
let config = std::fs::read(&opt.config).expect("Config file reading error");
|
||||
let config = toml::from_slice::<Config>(&config).expect("Config file parsing error");
|
||||
|
||||
let db_pool = MySqlPool::new(&config.database).await.expect("Database connection error");
|
||||
|
||||
let app = Router::new()
|
||||
.nest("/v1", v1::routes())
|
||||
.layer(AddExtensionLayer::new(db_pool));
|
||||
.layer(AddExtensionLayer::new(db_pool))
|
||||
.layer(AddExtensionLayer::new(config.vars()))
|
||||
.layer(SetResponseHeaderLayer::<_, Request<Body>>::if_not_present(header::ACCESS_CONTROL_ALLOW_ORIGIN, HeaderValue::from_static("*")));
|
||||
|
||||
let addr: SocketAddr = env::var("LISTEN").expect("The LISTEN env var ist not set").parse().expect("The LISTEN env var is set incorrectly");
|
||||
|
||||
axum::Server::bind(&addr)
|
||||
axum::Server::bind(&config.addr)
|
||||
.serve(app.into_make_service())
|
||||
.await
|
||||
.expect("Something went wrong :(");
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ pub struct Meme {
|
|||
pub category: String,
|
||||
pub user: String,
|
||||
pub timestamp: String,
|
||||
pub ipfs: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::config::ConfVars;
|
||||
use crate::v1::models::*;
|
||||
use sqlx::{MySqlPool, Error};
|
||||
use axum::{Router, Json};
|
||||
|
@ -7,8 +8,8 @@ use axum::handler::get;
|
|||
use axum::extract::{Query, Extension};
|
||||
use axum::http::StatusCode;
|
||||
|
||||
async fn meme(params: Query<MemeIDQuery>, Extension(db_pool): Extension<MySqlPool>) -> impl IntoResponse {
|
||||
let q = Meme::get(params.id, &db_pool).await;
|
||||
async fn meme(params: Query<MemeIDQuery>, Extension(db_pool): Extension<MySqlPool>, Extension(vars): Extension<ConfVars>) -> impl IntoResponse {
|
||||
let q = Meme::get(params.id, &db_pool, vars.cdn).await;
|
||||
match q {
|
||||
Ok(meme) => (StatusCode::OK, Json(MemeResponse {
|
||||
status: 200,
|
||||
|
@ -30,8 +31,8 @@ async fn meme(params: Query<MemeIDQuery>, Extension(db_pool): Extension<MySqlPoo
|
|||
}
|
||||
}
|
||||
|
||||
async fn memes(params: Query<MemeFilterQuery>, Extension(db_pool): Extension<MySqlPool>) -> impl IntoResponse {
|
||||
let q = Meme::get_all(params.0, &db_pool).await;
|
||||
async fn memes(params: Query<MemeFilterQuery>, Extension(db_pool): Extension<MySqlPool>, Extension(vars): Extension<ConfVars>) -> impl IntoResponse {
|
||||
let q = Meme::get_all(params.0, &db_pool, vars.cdn).await;
|
||||
match q {
|
||||
Ok(memes) => (StatusCode::OK, Json(MemesResponse {
|
||||
status: 200,
|
||||
|
@ -101,8 +102,8 @@ async fn users(Extension(db_pool): Extension<MySqlPool>) -> impl IntoResponse {
|
|||
}
|
||||
}
|
||||
|
||||
async fn random(params: Query<MemeFilterQuery>, Extension(db_pool): Extension<MySqlPool>) -> impl IntoResponse {
|
||||
let q = Meme::get_random(params.0, &db_pool).await;
|
||||
async fn random(params: Query<MemeFilterQuery>, Extension(db_pool): Extension<MySqlPool>, Extension(vars): Extension<ConfVars>) -> impl IntoResponse {
|
||||
let q = Meme::get_random(params.0, &db_pool, vars.cdn).await;
|
||||
match q {
|
||||
Ok(random) => (StatusCode::OK, Json(MemeResponse {
|
||||
status: 200,
|
||||
|
|
|
@ -10,72 +10,75 @@ pub struct DBMeme {
|
|||
pub userdir: String,
|
||||
pub category: String,
|
||||
pub timestamp: i64,
|
||||
pub ipfs: Option<String>,
|
||||
}
|
||||
|
||||
|
||||
impl Meme {
|
||||
pub async fn get(id: i32, pool: &MySqlPool) -> Result<Meme> {
|
||||
let q: Meme = sqlx::query("SELECT memes.id, user, filename, category, name, UNIX_TIMESTAMP(timestamp) AS ts FROM memes, users WHERE memes.user = users.id AND memes.id=?").bind(id)
|
||||
.map(|row: MySqlRow| Meme::from(DBMeme {
|
||||
|
||||
pub fn new(meme: DBMeme, cdn: String) -> Self {
|
||||
Meme {
|
||||
id: meme.id.to_string(),
|
||||
link: format!("{}/{}/{}", cdn, meme.userdir, meme.filename),
|
||||
category: meme.category,
|
||||
user: meme.user,
|
||||
timestamp: meme.timestamp.to_string(),
|
||||
ipfs: meme.ipfs,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get(id: i32, pool: &MySqlPool, cdn: String) -> Result<Meme> {
|
||||
let q: Meme = sqlx::query("SELECT memes.id, user, filename, category, name, UNIX_TIMESTAMP(timestamp) AS ts, cid FROM memes, users WHERE memes.user = users.id AND memes.id=?").bind(id)
|
||||
.map(|row: MySqlRow| Meme::new(DBMeme {
|
||||
id: row.get("id"),
|
||||
filename: row.get("filename"),
|
||||
user: row.get("name"),
|
||||
userdir: row.get("user"),
|
||||
category: row.get("category"),
|
||||
timestamp: row.get("ts"),
|
||||
}))
|
||||
ipfs: row.get("cid"),
|
||||
}, cdn.clone()))
|
||||
.fetch_one(pool).await?;
|
||||
Ok(q)
|
||||
}
|
||||
|
||||
pub async fn get_all(params: MemeFilterQuery, pool: &MySqlPool) -> Result<Vec<Meme>> {
|
||||
let q: Vec<Meme> = sqlx::query("SELECT memes.id, user, filename, category, name, UNIX_TIMESTAMP(timestamp) AS ts FROM memes, users WHERE memes.user = users.id AND (category LIKE ? AND name LIKE ? AND filename LIKE ?) ORDER BY memes.id")
|
||||
pub async fn get_all(params: MemeFilterQuery, pool: &MySqlPool, cdn: String) -> Result<Vec<Meme>> {
|
||||
let q: Vec<Meme> = sqlx::query("SELECT memes.id, user, filename, category, name, UNIX_TIMESTAMP(timestamp) AS ts, cid FROM memes, users WHERE memes.user = users.id AND (category LIKE ? AND name LIKE ? AND filename LIKE ?) ORDER BY memes.id")
|
||||
.bind(params.category.unwrap_or(String::from("%")))
|
||||
.bind(format!("%{}%", params.user.unwrap_or(String::from(""))))
|
||||
.bind(format!("%{}%", params.search.unwrap_or(String::from(""))))
|
||||
.map(|row: MySqlRow| Meme::from(DBMeme {
|
||||
.map(|row: MySqlRow| Meme::new(DBMeme {
|
||||
id: row.get("id"),
|
||||
filename: row.get("filename"),
|
||||
user: row.get("name"),
|
||||
userdir: row.get("user"),
|
||||
category: row.get("category"),
|
||||
timestamp: row.get("ts"),
|
||||
}))
|
||||
ipfs: row.get("cid"),
|
||||
}, cdn.clone()))
|
||||
.fetch_all(pool).await?;
|
||||
Ok(q)
|
||||
}
|
||||
|
||||
pub async fn get_random(params: MemeFilterQuery, pool: &MySqlPool) -> Result<Meme> {
|
||||
let q: Meme = sqlx::query("SELECT memes.id, user, filename, category, name, UNIX_TIMESTAMP(timestamp) AS ts FROM memes, users WHERE memes.user = users.id AND (category LIKE ? AND name LIKE ? AND filename LIKE ?) ORDER BY RAND() LIMIT 1")
|
||||
pub async fn get_random(params: MemeFilterQuery, pool: &MySqlPool, cdn: String) -> Result<Meme> {
|
||||
let q: Meme = sqlx::query("SELECT memes.id, user, filename, category, name, UNIX_TIMESTAMP(timestamp) AS ts, cid FROM memes, users WHERE memes.user = users.id AND (category LIKE ? AND name LIKE ? AND filename LIKE ?) ORDER BY RAND() LIMIT 1")
|
||||
.bind(params.category.unwrap_or(String::from("%")))
|
||||
.bind(format!("%{}%", params.user.unwrap_or(String::from(""))))
|
||||
.bind(format!("%{}%", params.search.unwrap_or(String::from(""))))
|
||||
.map(|row: MySqlRow| Meme::from(DBMeme {
|
||||
.map(|row: MySqlRow| Meme::new(DBMeme {
|
||||
id: row.get("id"),
|
||||
filename: row.get("filename"),
|
||||
user: row.get("name"),
|
||||
userdir: row.get("user"),
|
||||
category: row.get("category"),
|
||||
timestamp: row.get("ts"),
|
||||
}))
|
||||
ipfs: row.get("cid"),
|
||||
}, cdn.clone()))
|
||||
.fetch_one(pool).await?;
|
||||
Ok(q)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl From<DBMeme> for Meme {
|
||||
fn from(meme: DBMeme) -> Self {
|
||||
Meme {
|
||||
id: meme.id.to_string(),
|
||||
link: format!("{}/{}/{}", env::var("CDNURL").unwrap(), meme.userdir, meme.filename),
|
||||
category: meme.category,
|
||||
user: meme.user,
|
||||
timestamp: meme.timestamp.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Category {
|
||||
pub async fn get(id: &String, pool: &MySqlPool) -> Result<Category> {
|
||||
let q: Category = sqlx::query("SELECT * FROM categories WHERE id=?").bind(id)
|
||||
|
|
Loading…
Reference in a new issue