Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
|
d38429390c | |
|
a9acc17c79 |
|
@ -1,3 +1,3 @@
|
|||
libsig/target/
|
||||
sigweb/target/
|
||||
target/
|
||||
libsig/target
|
||||
sigweb/target
|
||||
target
|
|
@ -585,6 +585,35 @@ dependencies = [
|
|||
"regex-automata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maud"
|
||||
version = "0.22.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59d449907de7d1ae5b290cbaf9ea34a8a7df3fa5db027664bb55bb2b0fc1407c"
|
||||
dependencies = [
|
||||
"maud_htmlescape",
|
||||
"maud_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maud_htmlescape"
|
||||
version = "0.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0555daa37f94b5ebb206faf8cdc7b260c2aa371b509e929de9a1e37416d97fa6"
|
||||
|
||||
[[package]]
|
||||
name = "maud_macros"
|
||||
version = "0.22.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6896f8e8cdcea80b99ac0f1f7a233708e640737a8517448f50500e401bb8d76"
|
||||
dependencies = [
|
||||
"maud_htmlescape",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.4.1"
|
||||
|
@ -1162,6 +1191,7 @@ name = "sigweb"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libsig",
|
||||
"maud",
|
||||
"rocket",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
|
@ -4,6 +4,8 @@ Consisting of a Rust library for generating song ideas `libsig`,
|
|||
a command line tool for calling `libsig`,
|
||||
and a web interface with a JSON API for getting structured results from `libsig`.
|
||||
|
||||
![an example of sigweb in use](sigweb.png)
|
||||
|
||||
## Usage
|
||||
|
||||
The primary type of `libsig` is the `SongIdea`. You can generate human-readable representations with `Display` (so, `println!("{}", my_song_idea)`).
|
||||
|
@ -20,3 +22,7 @@ surfy lead, blownout pad, light vocals, acidic snare, sonorous hat, and digital
|
|||
```
|
||||
|
||||
It also takes a parameter `--ambient` to avoid suggesting percussion parts.
|
||||
|
||||
`sigweb` is a very basic Rocket app. I suggest building it with `x86_64-unknown-linux-musl`. Once built take the `sigweb` binary and put it in a folder with an appropriate `Rocket.toml`. You can set a base URL with the environment variable `SIGWEB_BASE_URL`. See the provided `sigweb.service` for a sample SystemD unit.
|
||||
|
||||
It provides a JSON API with the endpoints `/api/v1/{generate, generate_ambient}`.
|
|
@ -1,2 +0,0 @@
|
|||
/target
|
||||
Cargo.lock
|
|
@ -0,0 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "libsig"
|
||||
version = "0.1.0"
|
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
|
@ -6,6 +6,7 @@ edition = "2018"
|
|||
[dependencies]
|
||||
serde = "1"
|
||||
serde_json = "1"
|
||||
maud = "0.22"
|
||||
libsig = { path = "../libsig" }
|
||||
|
||||
[dependencies.rocket]
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
[Unit]
|
||||
Description=Song Idea Generator Web Service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=nora
|
||||
WorkingDirectory=/home/nora/sigweb
|
||||
ExecStart=/home/nora/sigweb/sigweb
|
||||
Environment=SIGWEB_BASE_URL="https://nora.codes/sigweb/"
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -1,9 +1,16 @@
|
|||
#[macro_use]
|
||||
extern crate rocket;
|
||||
use libsig;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use rocket::response::content::{Css, Html};
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::State;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
mod templates;
|
||||
|
||||
struct BaseUrl {
|
||||
url: String,
|
||||
}
|
||||
|
||||
#[get("/api")]
|
||||
fn api_version_available() -> Json<Value> {
|
||||
|
@ -26,24 +33,64 @@ struct Output {
|
|||
}
|
||||
|
||||
#[get("/api/v1/generate")]
|
||||
fn generate() -> Json<Output> {
|
||||
fn api_v1_generate() -> Json<Output> {
|
||||
let idea = libsig::SongIdea::generate();
|
||||
Json(Output {
|
||||
data: idea.clone(),
|
||||
text: idea.to_string()
|
||||
text: idea.to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
#[get("/api/v1/generate_ambient")]
|
||||
fn generate_ambient() -> Json<Output> {
|
||||
fn api_v1_generate_ambient() -> Json<Output> {
|
||||
let idea = libsig::SongIdea::generate_ambient();
|
||||
Json(Output {
|
||||
data: idea.clone(),
|
||||
text: idea.to_string()
|
||||
text: idea.to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
fn index(base: &State<BaseUrl>) -> Html<String> {
|
||||
Html(templates::main_page_template(None, &base.url))
|
||||
}
|
||||
|
||||
#[get("/generate")]
|
||||
fn generate(base: &State<BaseUrl>) -> Html<String> {
|
||||
Html(templates::main_page_template(Some(
|
||||
libsig::SongIdea::generate(),
|
||||
), &base.url))
|
||||
}
|
||||
|
||||
#[get("/generate_ambient")]
|
||||
fn generate_ambient(base: &State<BaseUrl>) -> Html<String> {
|
||||
Html(templates::main_page_template(Some(
|
||||
libsig::SongIdea::generate_ambient(),
|
||||
), &base.url))
|
||||
}
|
||||
|
||||
#[get("/style.css")]
|
||||
async fn style_css() -> Css<String> {
|
||||
Css(include_str!("../static/style.css").into())
|
||||
}
|
||||
|
||||
#[launch]
|
||||
fn rocket() -> _ {
|
||||
rocket::build().mount("/", routes![api_version_available, api_v1_index, generate, generate_ambient])
|
||||
rocket::build()
|
||||
.manage(BaseUrl {
|
||||
url: std::env::var("SIGWEB_BASE_URL").unwrap_or("/".to_string()),
|
||||
})
|
||||
.mount(
|
||||
"/",
|
||||
routes![
|
||||
api_version_available,
|
||||
api_v1_index,
|
||||
api_v1_generate,
|
||||
api_v1_generate_ambient,
|
||||
generate,
|
||||
generate_ambient,
|
||||
index,
|
||||
style_css,
|
||||
],
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
use maud::{html, DOCTYPE};
|
||||
use libsig::SongIdea;
|
||||
|
||||
pub fn main_page_template(idea: Option<SongIdea>, base_url: &str) -> String {
|
||||
let html = html! {
|
||||
(DOCTYPE)
|
||||
head {
|
||||
link rel="stylesheet" href="style.css";
|
||||
base href=(base_url);
|
||||
}
|
||||
body {
|
||||
h1 { "Song Idea Generator" }
|
||||
(match idea {
|
||||
Some(idea) => html!{
|
||||
p { "Why don't you make a song like this: " }
|
||||
p.content { (idea) }
|
||||
},
|
||||
None => html! { p { "Generate a new idea with the links below!" } p.content {} }
|
||||
})
|
||||
footer {
|
||||
p {
|
||||
a href="./generate" { "generate new" }
|
||||
" | "
|
||||
a href="./generate_ambient" { "generate new (ambient)" }
|
||||
}
|
||||
p {
|
||||
a href="http://nora.codes" { "my blog" }
|
||||
" | "
|
||||
a href="https://git.nora.codes/nora/song-idea-generator" { "code" }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
html.into()
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
body {
|
||||
background-color: bisque;
|
||||
color: darkblue;
|
||||
font-size: 12pt;
|
||||
font-family: sans-serif;
|
||||
max-width: 300pt;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
p.content {
|
||||
padding-top: auto;
|
||||
min-height: 100pt;
|
||||
}
|
||||
|
||||
footer {
|
||||
font-size: 10pt;
|
||||
text-align: center;
|
||||
}
|
Loading…
Reference in New Issue