initial commit
This commit is contained in:
commit
4e60216b8e
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target
|
1551
Cargo.lock
generated
Normal file
1551
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "printer-api"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
escpos = { version = "0.6.2", features = ["full"] }
|
||||
graphql_client = { version = "0.13.0", features = ["graphql_query_derive" , "reqwest-blocking"] }
|
||||
reqwest = { version = "0.11.24", features = ["json", "blocking"] }
|
||||
serde = "1.0.196"
|
7
gql/GetItem.graphql
Normal file
7
gql/GetItem.graphql
Normal file
@ -0,0 +1,7 @@
|
||||
query GetItem($index: String!) {
|
||||
magicItem(index: $index){
|
||||
name,
|
||||
rarity,
|
||||
desc
|
||||
}
|
||||
}
|
19
gql/GetSpell.graphql
Normal file
19
gql/GetSpell.graphql
Normal file
@ -0,0 +1,19 @@
|
||||
query GetSpell($index: String!){
|
||||
spell(index: $index){
|
||||
name,
|
||||
level,
|
||||
school {
|
||||
name
|
||||
}
|
||||
desc,
|
||||
components,
|
||||
duration,
|
||||
ritual,
|
||||
range,
|
||||
casting_time,
|
||||
area_of_effect {
|
||||
size
|
||||
type
|
||||
}
|
||||
}
|
||||
}
|
1446
gql/schema.graphql
Normal file
1446
gql/schema.graphql
Normal file
File diff suppressed because it is too large
Load Diff
142
src/api_client.rs
Normal file
142
src/api_client.rs
Normal file
@ -0,0 +1,142 @@
|
||||
use crate::types::{Item, Spell};
|
||||
use graphql_client::{GraphQLQuery, QueryBody, Response};
|
||||
use std::error::Error;
|
||||
|
||||
// https://studio.apollographql.com/sandbox?endpoint=https%3A%2F%2Fwww.dnd5eapi.co%2Fgraphql
|
||||
|
||||
#[derive(GraphQLQuery)]
|
||||
#[graphql(
|
||||
schema_path = "gql/schema.graphql",
|
||||
query_path = "gql/GetSpell.graphql",
|
||||
response_derives = "Debug"
|
||||
)]
|
||||
struct GetSpell;
|
||||
|
||||
#[derive(GraphQLQuery)]
|
||||
#[graphql(
|
||||
schema_path = "gql/schema.graphql",
|
||||
query_path = "gql/GetItem.graphql",
|
||||
response_derives = "Debug"
|
||||
)]
|
||||
struct GetItem;
|
||||
|
||||
fn perform_request<Q>(
|
||||
request_body: QueryBody<Q::Variables>,
|
||||
) -> Result<Response<Q::ResponseData>, Box<dyn Error>>
|
||||
where
|
||||
Q: GraphQLQuery,
|
||||
{
|
||||
let client = reqwest::blocking::Client::new();
|
||||
|
||||
let res = client
|
||||
.post("https://www.dnd5eapi.co/graphql")
|
||||
.json(&request_body)
|
||||
.send()?;
|
||||
let response_body: Response<Q::ResponseData> = res.json()?;
|
||||
|
||||
return Ok(response_body);
|
||||
}
|
||||
|
||||
fn spell_component_to_string(c: &get_spell::SpellComponent) -> String {
|
||||
match c {
|
||||
get_spell::SpellComponent::M => String::from("M"),
|
||||
get_spell::SpellComponent::V => String::from("V"),
|
||||
get_spell::SpellComponent::S => String::from("S"),
|
||||
get_spell::SpellComponent::Other(s) => String::from(s),
|
||||
}
|
||||
}
|
||||
|
||||
fn rarity_to_string(r: &get_item::MagicItemRarity) -> String {
|
||||
match r {
|
||||
get_item::MagicItemRarity::ARTIFACT => String::from("ARTIFACT"),
|
||||
get_item::MagicItemRarity::LEGENDARY => String::from("LEGENDARY"),
|
||||
get_item::MagicItemRarity::VERY_RARE => String::from("VERY_RARE"),
|
||||
get_item::MagicItemRarity::RARE => String::from("RARE"),
|
||||
get_item::MagicItemRarity::UNCOMMON => String::from("UNCOMMON"),
|
||||
get_item::MagicItemRarity::COMMON => String::from("COMMON"),
|
||||
get_item::MagicItemRarity::VARIES => String::from("VARIES"),
|
||||
get_item::MagicItemRarity::Other(s) => String::from(s),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_spell(index: &str) -> Result<Spell, Box<dyn Error>> {
|
||||
let vars = get_spell::Variables {
|
||||
index: index.into(),
|
||||
};
|
||||
|
||||
let body = GetSpell::build_query(vars);
|
||||
|
||||
let res = perform_request::<GetSpell>(body)?;
|
||||
|
||||
match res.data {
|
||||
Some(data) => match data.spell {
|
||||
Some(spell) => {
|
||||
let rtn = Spell {
|
||||
name: spell.name,
|
||||
level: spell.level,
|
||||
school: spell.school.name,
|
||||
range: spell.range,
|
||||
desc: spell.desc.join(" "),
|
||||
components: match spell.components {
|
||||
Some(components) => {
|
||||
Some(components
|
||||
.iter()
|
||||
.flatten()
|
||||
.map(spell_component_to_string)
|
||||
.collect::<Vec<String>>().join(" ")
|
||||
)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
duration: spell.duration,
|
||||
ritual: spell.ritual,
|
||||
casting_time: spell.casting_time,
|
||||
};
|
||||
|
||||
return Ok(rtn);
|
||||
}
|
||||
|
||||
_ => {
|
||||
return Err(Box::from("Spell not found"));
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
return Err(Box::from("Spell not found"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_item(index: &str) -> Result<Item, Box<dyn Error>>{
|
||||
let vars = get_item::Variables {
|
||||
index: index.into(),
|
||||
};
|
||||
|
||||
let body = GetItem::build_query(vars);
|
||||
|
||||
let res = perform_request::<GetItem>(body)?;
|
||||
|
||||
match res.data {
|
||||
Some(data) => {
|
||||
match data.magic_item {
|
||||
Some(item) => {
|
||||
let rtn = Item{
|
||||
name: item.name,
|
||||
rarity: rarity_to_string(&item.rarity),
|
||||
desc: item.desc.join(" ")
|
||||
};
|
||||
|
||||
return Ok(rtn);
|
||||
}
|
||||
|
||||
None => {
|
||||
return Err(Box::from("Item not found"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None => {
|
||||
return Err(Box::from("Item not found"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
35
src/main.rs
Normal file
35
src/main.rs
Normal file
@ -0,0 +1,35 @@
|
||||
use std::path::Path;
|
||||
|
||||
mod print;
|
||||
mod api_client;
|
||||
mod types;
|
||||
|
||||
use escpos::{driver::{ConsoleDriver, FileDriver}, errors::PrinterError, printer::Printer, utils::Protocol};
|
||||
|
||||
// https://www.dnd5eapi.co/graphql
|
||||
|
||||
fn run() -> Result<(),PrinterError> {
|
||||
// let driver = FileDriver::open(Path::new("/dev/usb/lp0")).unwrap();
|
||||
let driver = ConsoleDriver::open(true);
|
||||
let mut printer = Printer::new(driver, Protocol::default());
|
||||
|
||||
printer.init()?;
|
||||
|
||||
print::print_test_page(&mut printer)?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn main(){
|
||||
let spell = api_client::get_spell("eldritch-blast").unwrap();
|
||||
|
||||
let driver = FileDriver::open(Path::new("/dev/usb/lp0")).unwrap();
|
||||
let mut printer = Printer::new(driver, Protocol::default());
|
||||
|
||||
printer.init().unwrap();
|
||||
|
||||
print::print_spell(&mut printer, &spell).unwrap();
|
||||
|
||||
|
||||
println!("{:?}",spell);
|
||||
}
|
129
src/print.rs
Normal file
129
src/print.rs
Normal file
@ -0,0 +1,129 @@
|
||||
use escpos::{driver::Driver, errors::PrinterError, printer::Printer, utils::JustifyMode};
|
||||
|
||||
use crate::types::Spell;
|
||||
|
||||
const WIDTH: usize = 32;
|
||||
|
||||
pub fn print_test_page<D: Driver>(printer: &mut Printer<D>) -> Result<(), PrinterError> {
|
||||
printer
|
||||
.writeln("---Printer Test Page---")?
|
||||
.bold(true)?
|
||||
.writeln("This text should be bold.")?
|
||||
.bold(false)?
|
||||
.underline(escpos::utils::UnderlineMode::Single)?
|
||||
.writeln("This text should be single underline.")?
|
||||
.underline(escpos::utils::UnderlineMode::Double)?
|
||||
.writeln("This text should be double underline.")?
|
||||
.underline(escpos::utils::UnderlineMode::None)?
|
||||
.double_strike(true)?
|
||||
.writeln("This text should be double striked.")?
|
||||
.double_strike(true)?
|
||||
.writeln("Text alignment")?
|
||||
.justify(JustifyMode::CENTER)?
|
||||
.writeln("CENTER")?
|
||||
.justify(JustifyMode::RIGHT)?
|
||||
.writeln("RIGHT")?
|
||||
.justify(JustifyMode::LEFT)?
|
||||
.size(1, 1)?
|
||||
.writeln("size 1")?
|
||||
.size(5, 5)?
|
||||
.writeln("size 5")?
|
||||
.reset_size()?
|
||||
.font(escpos::utils::Font::A)?
|
||||
.write("Font A ")?
|
||||
.font(escpos::utils::Font::B)?
|
||||
.write("Font B ")?
|
||||
.font(escpos::utils::Font::C)?
|
||||
.writeln("Font C")?
|
||||
.font(escpos::utils::Font::A)?
|
||||
.flip(true)?
|
||||
.writeln("Fliped")?
|
||||
.flip(false)?
|
||||
.line_spacing(8)?
|
||||
.writeln("Line")?
|
||||
.writeln("Spacing")?
|
||||
.reset_line_spacing()?
|
||||
.upside_down(true)?
|
||||
.writeln("Upside down")?
|
||||
.upside_down(false)?
|
||||
// Barcodes
|
||||
.writeln("EAN-13 (978020137962)")?
|
||||
.ean13("978020137962")?
|
||||
.writeln("EAN-8 (9031101)")?
|
||||
.ean8("9031101")?
|
||||
.writeln("UPC-A")?
|
||||
.upca("72527273070")?
|
||||
.writeln("CODE-39")?
|
||||
.code39("1234")?
|
||||
.writeln("CODABAR")?
|
||||
.writeln("1234")?
|
||||
.writeln("ITF")?
|
||||
.itf("1234")?
|
||||
// 2D Codes
|
||||
.writeln("QR Code")?
|
||||
.qrcode("Hello world")?
|
||||
.writeln("2D GS1 DataBar")?
|
||||
.gs1_databar_2d("1234567890123")?
|
||||
.writeln("pdf417")?
|
||||
.pdf417("Hello world")?
|
||||
.writeln("Maxi code")?
|
||||
.maxi_code("Hello world")?
|
||||
.writeln("Data matrix")?
|
||||
.data_matrix("Hello world")?
|
||||
.writeln("aztec")?
|
||||
.aztec("Hello world")?
|
||||
// Image
|
||||
.writeln("raster image")?
|
||||
// .bit_image("./rust-logo-small.png")?
|
||||
.print()?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn left_right_print<D: Driver>(printer: &mut Printer<D>,left: &str, right: &str ) -> Result<(), PrinterError> {
|
||||
printer
|
||||
.write(left)?
|
||||
.write(&".".repeat(WIDTH - left.len() - right.len()))?
|
||||
.writeln(right)?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pub fn print_spell<D: Driver>(printer: &mut Printer<D>, spell: &Spell) -> Result<(), PrinterError> {
|
||||
printer
|
||||
.size(4, 4)?
|
||||
.writeln(&spell.name)?
|
||||
.reset_size()?
|
||||
.line_spacing(1)?;
|
||||
|
||||
if spell.level > 0 {
|
||||
if spell.ritual {
|
||||
printer.writeln(&format!("Lvl. {} {} (ritual)", spell.level, spell.school))?;
|
||||
}else{
|
||||
printer.writeln(&format!("Lvl. {} {}", spell.level, spell.school))?;
|
||||
}
|
||||
} else {
|
||||
printer.writeln(&format!("{} cantrip", spell.school))?;
|
||||
}
|
||||
|
||||
printer.feed()?;
|
||||
|
||||
match &spell.components {
|
||||
Some(comp) => {
|
||||
left_right_print(printer, "Components:", &comp)?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
left_right_print(printer, "Casting time:", &spell.casting_time)?;
|
||||
left_right_print(printer, "Range:", &spell.range)?;
|
||||
left_right_print(printer, "Duration:", &spell.duration)?;
|
||||
|
||||
printer
|
||||
.reset_line_spacing()?
|
||||
.write(&spell.desc)?
|
||||
.feeds(3)?
|
||||
.print()?;
|
||||
|
||||
return Ok(());
|
||||
}
|
18
src/types.rs
Normal file
18
src/types.rs
Normal file
@ -0,0 +1,18 @@
|
||||
#[derive(Debug)]
|
||||
pub struct Spell{
|
||||
pub name: String,
|
||||
pub level: i64,
|
||||
pub range: String,
|
||||
pub school: String,
|
||||
pub desc: String,
|
||||
pub components: Option<String>,
|
||||
pub duration: String,
|
||||
pub ritual: bool,
|
||||
pub casting_time: String,
|
||||
}
|
||||
|
||||
pub struct Item {
|
||||
pub name: String,
|
||||
pub rarity: String,
|
||||
pub desc: String,
|
||||
}
|
Loading…
Reference in New Issue
Block a user