133 lines
3.1 KiB
Rust
133 lines
3.1 KiB
Rust
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
|
|
|
extern crate serial;
|
|
|
|
use reqwest::Client;
|
|
use serde::Deserialize;
|
|
use serial::prelude::*;
|
|
use std::io;
|
|
use std::str::from_utf8;
|
|
use std::time::Duration;
|
|
|
|
#[derive(Debug)]
|
|
struct BookData {
|
|
title: String,
|
|
authors: Vec<String>,
|
|
thumbnail: String,
|
|
description: String,
|
|
}
|
|
|
|
#[allow(unused)]
|
|
#[derive(Debug, Deserialize)]
|
|
struct BookRoot {
|
|
items: Vec<Item>,
|
|
}
|
|
|
|
#[allow(unused, non_snake_case)]
|
|
#[derive(Debug, Deserialize)]
|
|
struct Item {
|
|
volumeInfo: VolumeInfo,
|
|
}
|
|
|
|
#[allow(unused, non_snake_case)]
|
|
#[derive(Debug, Deserialize)]
|
|
struct VolumeInfo {
|
|
title: String,
|
|
authors: Option<Vec<String>>,
|
|
description: Option<String>,
|
|
imageLinks: Option<ImageLinks>,
|
|
}
|
|
|
|
#[allow(unused, non_snake_case)]
|
|
#[derive(Debug, Deserialize)]
|
|
struct ImageLinks {
|
|
thumbnail: Option<String>,
|
|
smallThumbnail: Option<String>,
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
booklooker_lib::run();
|
|
let mut port = serial::open("/dev/ttyACM0").unwrap();
|
|
interact(&mut port).await.unwrap();
|
|
}
|
|
|
|
async fn interact<T: SerialPort>(port: &mut T) -> io::Result<()> {
|
|
port.reconfigure(&|settings| {
|
|
settings.set_baud_rate(serial::Baud9600)?;
|
|
settings.set_char_size(serial::Bits8);
|
|
settings.set_parity(serial::ParityNone);
|
|
settings.set_stop_bits(serial::Stop1);
|
|
settings.set_flow_control(serial::FlowNone);
|
|
Ok(())
|
|
})?;
|
|
|
|
port.set_timeout(Duration::from_millis(1000000000))?;
|
|
loop {
|
|
let buf: &mut [u8; 14] = &mut [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
port.read_exact(buf).unwrap();
|
|
let barcode_id = from_utf8(buf).unwrap();
|
|
println!("{}", &barcode_id);
|
|
if barcode_id.starts_with("978") {
|
|
get_book_data(barcode_id.to_string()).await;
|
|
}
|
|
}
|
|
}
|
|
|
|
async fn get_book_data(isbn: String) {
|
|
let lookup_url = format!(
|
|
"https://www.googleapis.com/books/v1/volumes?q=isbn:{}",
|
|
isbn
|
|
);
|
|
let cleint = Client::new();
|
|
let book_data = cleint
|
|
.get(lookup_url)
|
|
.send()
|
|
.await
|
|
.unwrap()
|
|
.json::<BookRoot>()
|
|
.await
|
|
.unwrap();
|
|
let book_metadata: Vec<BookData> = book_data.items.into_iter().map(BookData::from).collect();
|
|
println!("{}", &book_metadata[0]);
|
|
}
|
|
|
|
impl From<Item> for BookData {
|
|
fn from(item: Item) -> Self {
|
|
let info = item.volumeInfo;
|
|
BookData {
|
|
title: info.title,
|
|
authors: info.authors.unwrap_or_default(),
|
|
description: info.description.as_deref().unwrap_or("").to_string(),
|
|
thumbnail: info
|
|
.imageLinks
|
|
.as_ref()
|
|
.and_then(|links| links.thumbnail.as_deref())
|
|
.unwrap_or("")
|
|
.to_string(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for BookData {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(
|
|
f,
|
|
"Title: {}\nAuthors: {}\nDescription: {}\nThumbnail: {}",
|
|
self.title,
|
|
if self.authors.is_empty() {
|
|
"Unknown".to_string()
|
|
} else {
|
|
self.authors.join(", ")
|
|
},
|
|
if self.description.is_empty() {
|
|
"No description available".to_string()
|
|
} else {
|
|
self.description.clone()
|
|
},
|
|
self.thumbnail
|
|
)
|
|
}
|
|
}
|