Updated icarus-model #33

Merged
kdeng00 merged 28 commits from migrate_song_model into master 2025-03-24 19:34:38 -04:00
16 changed files with 303 additions and 458 deletions
+4 -3
View File
@@ -20,19 +20,20 @@ jobs:
run: rustup install 1.85.0 && rustup default 1.85.0 run: rustup install 1.85.0 && rustup default 1.85.0
- name: Debug secret - name: Debug secret
run: echo "${{ secrets.GITLAB_TOKEN }}" | head -c 10 ; echo "..." run: echo "${{ secrets.MYREPO_TOKEN }}" | head -c 10 ; echo "..."
- name: Build - name: Build
run: | run: |
mkdir -p ~/.ssh mkdir -p ~/.ssh
echo "$EXTREPO_KEY" > ~/.ssh/gitlab_deploy_key echo "$EXTREPO_KEY" > ~/.ssh/gitlab_deploy_key
chmod 600 ~/.ssh/gitlab_deploy_key chmod 600 ~/.ssh/gitlab_deploy_key
ssh-keyscan gitlab.com >> ~/.ssh/known_hosts ssh-keyscan git.kundeng.us ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLl/OZiKVDxwnyvMxa+rjKvDpKqTxH1GWuGuDPLmENGQMbTVulajZWr9x8Q1cotoJiHZkt7DA5vczcjB/4lwgWA= >> ~/.ssh/known_hosts
eval $(ssh-agent -s) eval $(ssh-agent -s)
ssh-add -v ~/.ssh/gitlab_deploy_key ssh-add -v ~/.ssh/gitlab_deploy_key
cargo build --release cargo build --release
env: env:
EXTREPO_KEY: ${{ secrets.GITLAB_TOKEN }} EXTREPO_KEY: ${{ secrets.MYREPO_TOKEN }}
- name: Run tests - name: Run tests
run: cargo test --verbose run: cargo test --verbose
+1 -1
View File
@@ -16,4 +16,4 @@ serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140" serde_json = "1.0.140"
tokio = { version = "1.44.0", features = ["full"] } tokio = { version = "1.44.0", features = ["full"] }
tokio-util = { version = "0.7.13", features = ["codec"] } tokio-util = { version = "0.7.13", features = ["codec"] }
icarus-models = { git = "ssh://git@gitlab.com/kdeng00/icarus-models.git", tag = "v0.1.7" } icarus-models = { git = "ssh://git@git.kundeng.us/phoenix/icarus-models.git", tag = "v0.1.14" }
+165 -192
View File
@@ -8,7 +8,6 @@ use serde::{Deserialize, Serialize};
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
use crate::managers; use crate::managers;
use crate::models::song::Album;
use crate::models::{self}; use crate::models::{self};
use crate::parsers; use crate::parsers;
use crate::syncers; use crate::syncers;
@@ -29,10 +28,6 @@ enum ActionValues {
None, None,
} }
enum _RetrieveTypes {
Songs,
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
enum En { enum En {
ImageFile, ImageFile,
@@ -41,24 +36,36 @@ enum En {
Other, Other,
} }
impl Album { pub fn retrieve_song(
pub fn _print_info(&self) { album: &icarus_models::album::collection::Album,
println!("Album: {}", self.title); track: i32,
println!("Album Artist: {}", self.album_artist); disc: i32,
println!("Genre: {}", self.genre); directory: &String,
println!("Year: {}", self.year); filename: &String,
println!("Track Count: {}", self.track_count); ) -> Result<icarus_models::song::Song> {
println!("Disc Count: {}\n", self.disc_count);
}
pub fn retrieve_song(&self, track: i32, disc: i32) -> Result<models::song::Song> {
let mut found = false; let mut found = false;
let mut song = models::song::Song::default(); let mut song = icarus_models::song::Song::default();
for song_i in &album.tracks {
if song_i.track == track && song_i.disc == disc {
let track = song_i.clone();
song.album = album.title.clone();
song.album_artist = album.artist.clone();
song.artist = track.artist.clone();
song.audio_type = String::from(icarus_models::constants::DEFAULTMUSICEXTENSION);
song.disc = track.disc.clone();
song.disc_count = album.disc_count.clone();
song.duration = track.duration as i32;
song.genre = album.genre.clone();
song.title = track.title.clone();
song.year = album.year.clone();
song.track = track.track.clone();
song.track_count = album.track_count.clone();
song.directory = directory.clone();
song.filename = filename.clone();
for song_i in &self.songs {
if song_i.track.unwrap() == track && song_i.disc.unwrap() == disc {
song = song_i.clone();
found = true; found = true;
break;
} }
} }
@@ -70,7 +77,6 @@ impl Album {
std::io::ErrorKind::NotFound, std::io::ErrorKind::NotFound,
"Song not found", "Song not found",
)); ));
}
} }
impl CommitManager { impl CommitManager {
@@ -110,15 +116,17 @@ impl CommitManager {
} }
fn map_actions(&self) -> HashMap<String, ActionValues> { fn map_actions(&self) -> HashMap<String, ActionValues> {
let mut actions: HashMap<String, ActionValues> = HashMap::new(); let actions: HashMap<String, ActionValues> = HashMap::from([
actions.insert("download".to_string(), ActionValues::DownloadAct); ("download".to_string(), ActionValues::DownloadAct),
actions.insert("upload".to_string(), ActionValues::UploadAct); ("download".to_string(), ActionValues::DownloadAct),
actions.insert( ("upload".to_string(), ActionValues::UploadAct),
(
"upload-meta".to_string(), "upload-meta".to_string(),
ActionValues::UploadSongWithMetadata, ActionValues::UploadSongWithMetadata,
); ),
actions.insert("retrieve".to_string(), ActionValues::RetrieveAct); ("retrieve".to_string(), ActionValues::RetrieveAct),
actions.insert("delete".to_string(), ActionValues::DeleteAct); ("delete".to_string(), ActionValues::DeleteAct),
]);
return actions; return actions;
} }
@@ -135,14 +143,14 @@ impl CommitManager {
println!("Deleting song"); println!("Deleting song");
let mut song = models::song::Song::default(); let mut song = icarus_models::song::Song::default();
for arg in &self.ica_action.flags { for arg in &self.ica_action.flags {
let flag = &arg.flag; let flag = &arg.flag;
let value = &arg.value; let value = &arg.value;
if flag == "-D" { if flag == "-D" {
song.id = Some(value.parse::<i32>().unwrap()); song.id = value.parse::<i32>().unwrap();
} }
} }
@@ -165,7 +173,7 @@ impl CommitManager {
fn download_song(&self) { fn download_song(&self) {
println!("Deleting song"); println!("Deleting song");
let dwn = self.ica_action.retrieve_flag_value(&String::from("-b")); let dwn = self.ica_action.retrieve_flag_value(&String::from("-b"));
let num: i32 = dwn.parse::<i32>().unwrap(); let id: i32 = dwn.parse::<i32>().unwrap();
let mut prsr = parsers::api_parser::APIParser { let mut prsr = parsers::api_parser::APIParser {
api: models::api::API::default(), api: models::api::API::default(),
@@ -178,27 +186,27 @@ impl CommitManager {
println!("Message: {}", token.message); println!("Message: {}", token.message);
let mut dwn_loader = syncers::download::Download { api: api.clone() }; let mut dwn_loader = syncers::download::Download { api: api.clone() };
let mut song = models::song::Song::default(); let mut song = icarus_models::song::Song::default();
song.id = Some(num); song.id = id;
let result_fut = dwn_loader.download_song(&token, &song); let result_fut = dwn_loader.download_song(&token, &song);
let result = Runtime::new().unwrap().block_on(result_fut); match Runtime::new().unwrap().block_on(result_fut) {
match result {
Ok(o) => { Ok(o) => {
println!("Success"); println!("Success");
let mut filename = String::from("audio"); let filename =
filename += icarus_models::constants::WAV_EXTENSION; String::from("audio") + icarus_models::constants::DEFAULTMUSICEXTENSION;
let data = o.as_bytes(); let data = o.as_bytes();
let mut file = std::fs::File::create(filename).expect("Failed to save"); let mut file = std::fs::File::create(filename).expect("Failed to save");
file.write_all(&data).expect("ff"); file.write_all(&data)
.expect("Failed to save downloaded song");
} }
Err(er) => { Err(er) => {
println!("Error {:?}", er); println!("Error {:?}", er);
match er { match er {
syncers::download::MyError::Request(r) => { syncers::download::MyError::Request(error) => {
println!("Error {:?}", r) println!("Error: {:?}", error);
} }
syncers::download::MyError::Other(ot) => { syncers::download::MyError::Other(ss) => {
println!("Error {:?}", ot) println!("Error: {:?}", ss);
} }
} }
} }
@@ -206,7 +214,7 @@ impl CommitManager {
} }
fn retrieve_object(&self) { fn retrieve_object(&self) {
println!("Deleting song"); println!("Retrieving song");
let rt = self.ica_action.retrieve_flag_value(&String::from("-rt")); let rt = self.ica_action.retrieve_flag_value(&String::from("-rt"));
if rt != "songs" { if rt != "songs" {
@@ -224,11 +232,13 @@ impl CommitManager {
let mut repo = syncers::retrieve_records::RetrieveRecords { api: api.clone() }; let mut repo = syncers::retrieve_records::RetrieveRecords { api: api.clone() };
let result_fut = repo.get_all_songs(&token); let result_fut = repo.get_all_songs(&token);
let result = Runtime::new().unwrap().block_on(result_fut); match Runtime::new().unwrap().block_on(result_fut) {
match result {
Ok(o) => { Ok(o) => {
for son in o { for song in o {
son.print_info(); println!("Title: {:?}", song.title);
println!("Artist: {:?}", song.artist);
println!("Album: {:?}", song.album);
println!("Year: {:?}", song.year);
} }
} }
Err(er) => { Err(er) => {
@@ -315,6 +325,8 @@ impl CommitManager {
let api = prsr.retrieve_api(); let api = prsr.retrieve_api();
let token = self.parse_token(&api); let token = self.parse_token(&api);
println!("Token: {:?}", token.token);
let song_file = std::path::Path::new(&songpath); let song_file = std::path::Path::new(&songpath);
if !song_file.exists() { if !song_file.exists() {
@@ -322,52 +334,43 @@ impl CommitManager {
panic!("Error"); panic!("Error");
} }
let mut cover_art = models::song::CoverArt::default(); let mut cover_art = icarus_models::coverart::CoverArt {
let mut song = models::song::Song::default(); id: 0,
title: String::new(),
path: String::new(),
data: Vec::new(),
};
let mut song = icarus_models::song::Song::default();
let mut filenames = Vec::new(); let mut filenames = Vec::new();
let mut fp = String::new(); let file_name = std::ffi::OsString::from(&song_file.file_name().unwrap());
let mut dir = String::new();
let entry = &song_file;
let file_name = std::ffi::OsString::from(entry.file_name().unwrap());
println!("file name: {:?}", file_name);
match self.find_file_extension(&file_name) { match self.find_file_extension(&file_name) {
En::ImageFile => {} En::ImageFile => {}
En::MetadataFile => {} En::MetadataFile => {}
En::SongFile => { En::SongFile => match utilities::string::o_to_string(&file_name) {
let fname = self.o_to_string(&file_name);
match fname {
Ok(s) => { Ok(s) => {
println!("file name: {:?}", file_name);
filenames.push(s.clone()); filenames.push(s.clone());
fp = s.clone(); song.filename = s.clone();
dir = song_file.parent().unwrap().display().to_string(); song.directory = song_file.parent().unwrap().display().to_string();
song.filename = Some(s.clone());
song.directory = Some(dir.clone());
self.initialize_disc_and_track(&mut song); self.initialize_disc_and_track(&mut song);
} }
Err(er) => println!("Error: {:?}", er), Err(er) => println!("Error: {:?}", er),
} },
}
_ => {} _ => {}
} }
cover_art.path = Some(cover_path.clone()); cover_art.path = cover_path.clone();
let album = self.retrieve_metadata(&meta_path); let album = self.retrieve_metadata(&meta_path);
let trck = i32::from_str(track_id).unwrap(); let trck = i32::from_str(track_id).unwrap();
let mut s = album.retrieve_song(trck, 1).unwrap(); let mut s = retrieve_song(&album, trck, 1, &song.directory, &song.filename).unwrap();
s.filename = Some(fp); println!("Directory: {:?}", s.directory);
s.directory = Some(dir); println!("Filename: {:?}", s.filename);
s.genre = Some(album.genre.clone()); println!("Path: {:?}", s.song_path());
s.year = Some(album.year.clone()); s.data = s.to_data().unwrap();
s.album = Some(album.title.clone());
s.data = Some(s.to_data().unwrap());
cover_art.data = Some(cover_art.to_data().unwrap()); cover_art.data = cover_art.to_data().unwrap();
let mut up = syncers::upload::Upload::default(); let mut up = syncers::upload::Upload::default();
let host = self.ica_action.retrieve_flag_value(&String::from("-h")); let host = self.ica_action.retrieve_flag_value(&String::from("-h"));
@@ -379,13 +382,63 @@ impl CommitManager {
match &tken { match &tken {
Ok(o) => { Ok(o) => {
println!("Successfully sent {:?}", o); println!("Successfully sent {:?}", o);
Ok(())
} }
Err(er) => { Err(er) => {
println!("Some error {:?}", er); println!("Some error {:?}", er);
Err(std::io::Error::new(
std::io::ErrorKind::Other,
er.to_string(),
))
}
} }
} }
Ok(()) fn get_songs(
&self,
metadata_path: &String,
source_directory: &String,
) -> Result<Vec<icarus_models::song::Song>> {
match icarus_models::album::collection::parse_album(metadata_path) {
Ok(albums) => {
let mut songs: Vec<icarus_models::song::Song> = Vec::new();
for track in &albums.tracks {
let filename = if track.track < 10 {
"track0".to_owned()
+ &track.track.to_string()
+ icarus_models::constants::DEFAULTMUSICEXTENSION
} else {
"track".to_owned()
+ &track.track.to_string()
+ icarus_models::constants::DEFAULTMUSICEXTENSION
};
songs.push(icarus_models::song::Song {
id: -1,
title: track.title.clone(),
artist: track.artist.clone(),
disc: track.disc.clone(),
track: track.track.clone(),
duration: track.duration.clone() as i32,
year: albums.year.clone(),
album_artist: albums.artist.clone(),
genre: albums.genre.clone(),
disc_count: albums.disc_count.clone(),
track_count: albums.track_count.clone(),
album: albums.title.clone(),
audio_type: String::from("FLAC"),
directory: source_directory.clone(),
filename: filename,
user_id: -1,
data: Vec::new(),
date_created: String::new(),
});
}
Ok(songs)
}
Err(_) => Ok(Vec::new()),
}
} }
fn multi_target_upload(&mut self, sourcepath: &String) -> std::io::Result<()> { fn multi_target_upload(&mut self, sourcepath: &String) -> std::io::Result<()> {
@@ -403,8 +456,12 @@ impl CommitManager {
panic!("Directory does not exist"); panic!("Directory does not exist");
} }
let mut cover_art = models::song::CoverArt::default(); let mut cover_art = icarus_models::coverart::CoverArt {
let mut songs: Vec<models::song::Song> = Vec::new(); id: 0,
title: String::new(),
path: String::new(),
data: Vec::new(),
};
let mut filenames: Vec<String> = Vec::new(); let mut filenames: Vec<String> = Vec::new();
let mut metadatapath: String = String::new(); let mut metadatapath: String = String::new();
@@ -423,130 +480,55 @@ impl CommitManager {
match self.find_file_extension(&file_name) { match self.find_file_extension(&file_name) {
En::ImageFile => { En::ImageFile => {
let directory_part = sourcepath.clone(); let directory_part = sourcepath.clone();
let fname = self.o_to_string(&file_name); let fname = utilities::string::o_to_string(&file_name);
let fullpath = directory_part + "/" + &fname.unwrap(); let fullpath = directory_part + "/" + &fname.unwrap();
cover_art.path = Some(fullpath); cover_art.path = fullpath;
} }
En::MetadataFile => { En::MetadataFile => {
let directory_part = sourcepath.clone(); let directory_part = sourcepath.clone();
let fname = self.o_to_string(&file_name); let fname = utilities::string::o_to_string(&file_name);
metadatapath = directory_part + "/" + &fname.unwrap(); metadatapath = directory_part + "/" + &fname.unwrap();
} }
En::SongFile => {
let mut song = models::song::Song::default();
let fname = self.o_to_string(&file_name);
match fname {
Ok(s) => {
filenames.push(s.clone());
song.filename = Some(s.clone());
song.directory = Some(sourcepath.clone());
song.data = Some(song.to_data().unwrap());
self.initialize_disc_and_track(&mut song);
}
Err(er) => println!("Error: {:?}", er),
}
songs.push(song)
}
_ => {} _ => {}
} }
} }
filenames.sort(); filenames.sort();
let songs = self.get_songs(&metadatapath, &sourcepath);
let mut album = self.retrieve_metadata(&metadatapath); let album = self.retrieve_metadata(&metadatapath);
self.song_parsing(&mut album, &sourcepath, &filenames);
let mut up = syncers::upload::Upload::default(); let mut up = syncers::upload::Upload::default();
let host = self.ica_action.retrieve_flag_value(&String::from("-h")); let host = self.ica_action.retrieve_flag_value(&String::from("-h"));
up.set_api(&host); up.set_api(&host);
cover_art.data = Some(cover_art.to_data().unwrap()); cover_art.data = cover_art.to_data().unwrap();
println!(""); println!("");
for sng in &mut album.songs { match songs {
match sng.data { Ok(sngs) => {
Some(_) => {} for song in sngs {
None => { println!("Title: {:?}", song.title);
sng.data = Some(sng.to_data().unwrap()); println!("Path: {:?}", song.song_path());
let res = up.upload_song_with_metadata(&token, &song, &cover_art, &album);
match Runtime::new().unwrap().block_on(res) {
Ok(o) => {
println!("Response: {:?}", o);
}
Err(err) => {
println!("Error: {:?}", err);
} }
}; };
} }
for song in &album.songs {
// Upload each song
println!("Sending song...");
let res = up.upload_song_with_metadata(&token, &song, &cover_art, &album);
let tken = Runtime::new().unwrap().block_on(res);
match &tken {
Ok(o) => {
println!("Successfully sent {:?}", o);
} }
Err(er) => { Err(error) => {
println!("Some error {:?}", er); println!("Error: {:?}", error);
} }
} }
println!("");
}
Ok(()) Ok(())
} }
// Makes sure the elements in album.songs is populated
fn song_parsing(
&self,
album: &mut models::song::Album,
directory: &String,
filenames: &Vec<String>,
) {
// Apply directory
for song in &mut album.songs {
let dir = &song.directory;
match dir {
Some(s) => println!("{}", s),
None => {
song.directory = Some(directory.clone());
}
}
}
// Apply filename
let mut index = 0;
for song in &mut album.songs {
let filename = filenames[index].clone();
song.filename = Some(filename);
index += 1;
}
for song in &mut album.songs {
match &mut song.album {
Some(_) => {}
None => {
song.album = Some(album.title.clone());
}
}
match &mut song.genre {
Some(_) => {}
None => {
song.genre = Some(album.genre.clone());
}
}
match &mut song.year {
Some(_) => {}
None => {
song.year = Some(album.year.clone());
}
}
}
}
fn find_file_extension(&self, file_name: &std::ffi::OsString) -> En { fn find_file_extension(&self, file_name: &std::ffi::OsString) -> En {
let file_name_str = Some(file_name.clone().into_string()); let file_name_str = Some(file_name.clone().into_string());
@@ -588,23 +570,14 @@ impl CommitManager {
return En::Other; return En::Other;
} }
fn o_to_string(&self, val: &std::ffi::OsString) -> Result<std::string::String> {
let res = val.clone().into_string();
return match res {
Ok(sss) => Ok(sss),
Err(_) => Ok(String::from("Error")),
};
}
// Standards // Standards
// * track01.cdda.wav - Disc 1, Track 1 // * track01.cdda.wav - Disc 1, Track 1
// * track02d02.cdda.wav - Disc 2, Track 2 // * track02d02.cdda.wav - Disc 2, Track 2
fn initialize_disc_and_track(&mut self, song: &mut models::song::Song) { fn initialize_disc_and_track(&mut self, song: &mut icarus_models::song::Song) {
let mut disc = 1; let mut disc = 1;
let mut track = 1; let mut track = 1;
let mut mode = 0; let mut mode = 0;
let filename = let filename = &song.filename;
&<std::option::Option<std::string::String> as Clone>::clone(&song.filename).unwrap();
let trd = filename.contains("trackd"); let trd = filename.contains("trackd");
let tr = filename.contains("track"); let tr = filename.contains("track");
@@ -688,11 +661,11 @@ impl CommitManager {
_ => println!(""), _ => println!(""),
} }
song.disc = Some(disc); song.disc = disc;
song.track = Some(track); song.track = track;
} }
fn _parse_disc_and_track(&self, song: &mut models::song::Song, track_id: &String) { fn _parse_disc_and_track(&self, song: &mut icarus_models::song::Song, track_id: &String) {
let sep = |_a: &char, _b: &char| -> bool { let sep = |_a: &char, _b: &char| -> bool {
return false; return false;
}; };
@@ -714,11 +687,11 @@ impl CommitManager {
d_str.push(c); d_str.push(c);
} }
song.disc = Some(d_str.parse::<i32>().unwrap()); song.disc = d_str.parse::<i32>().unwrap();
song.track = Some(t_str.parse::<i32>().unwrap()); song.track = t_str.parse::<i32>().unwrap();
} else { } else {
if utilities::checks::Checks::is_numeric(track_id) { if utilities::checks::Checks::is_numeric(track_id) {
song.track = Some(track_id.parse::<i32>().unwrap()); song.track = track_id.parse::<i32>().unwrap();
} }
} }
} }
@@ -732,7 +705,7 @@ impl CommitManager {
return false; return false;
} }
fn retrieve_metadata(&self, path: &String) -> Album { fn retrieve_metadata(&self, path: &String) -> icarus_models::album::collection::Album {
let content = self.retrieve_file_content(&path); let content = self.retrieve_file_content(&path);
let val = content.unwrap(); let val = content.unwrap();
-1
View File
@@ -1,5 +1,4 @@
pub mod api; pub mod api;
pub mod flags; pub mod flags;
pub mod icarus_action; pub mod icarus_action;
pub mod song;
pub mod upload_form; pub mod upload_form;
-179
View File
@@ -1,179 +0,0 @@
use std::default::Default;
use std::io::Read;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Song {
#[serde(alias = "id")]
pub id: Option<i32>,
pub title: Option<String>,
pub artist: Option<String>,
pub album: Option<String>,
pub album_artist: Option<String>,
pub genre: Option<String>,
pub year: Option<i32>,
pub duration: Option<f64>,
pub track: Option<i32>,
pub disc: Option<i32>,
pub disc_count: Option<i32>,
pub track_count: Option<i32>,
pub date_created: Option<String>,
pub filename: Option<String>,
pub user_id: Option<i32>,
pub data: Option<Vec<u8>>,
pub directory: Option<String>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Album {
#[serde(alias = "album")]
pub title: String,
pub album_artist: String,
pub genre: String,
pub year: i32,
pub track_count: i32,
pub disc_count: i32,
#[serde(alias = "tracks")]
pub songs: Vec<Song>,
}
impl Default for Album {
fn default() -> Self {
Album {
title: String::new(),
album_artist: String::new(),
genre: String::new(),
year: 0,
track_count: 0,
disc_count: 0,
songs: Vec::new(),
}
}
}
impl Default for Song {
fn default() -> Self {
Song {
id: None,
title: None,
artist: None,
album: None,
album_artist: None,
genre: None,
year: None,
duration: None,
track: None,
disc: None,
disc_count: None,
track_count: None,
date_created: None,
filename: None,
user_id: None,
data: None,
directory: None,
}
}
}
impl Song {
pub fn print_info(&self) {
println!("Title: {:?}", self.title);
println!("Artist: {:?}", self.artist);
}
pub fn song_path(&self) -> String {
let directory =
&<std::option::Option<std::string::String> as Clone>::clone(&self.directory).unwrap();
let mut buffer: String = directory.to_string();
let count = buffer.len();
if buffer.chars().nth(count - 1) != Some('/') {
buffer += "/";
}
let filename =
&<std::option::Option<std::string::String> as Clone>::clone(&self.filename).unwrap();
buffer += filename;
return buffer;
}
pub fn to_data(&self) -> Result<Vec<u8>, std::io::Error> {
let path = self.song_path();
println!("Converting song to data");
println!("Path: {:?}", path);
let mut file = std::fs::File::open(path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
if buffer.len() == 0 {
println!("Why is it empty?");
}
Ok(buffer)
}
// if 1 - wav, if 0 - mp3, anything else defaults to wav
pub fn _generate_filename_from_track(&mut self, i_type: i32) -> i32 {
let mut filename: String = String::new();
if self.track.unwrap() < 10 {
filename += "0";
}
filename += &self.track.unwrap().to_string();
if i_type == 0 {
filename += icarus_models::constants::MPTHREE_EXTENSION;
} else {
filename += icarus_models::constants::WAV_EXTENSION;
}
self.filename = Some(filename);
return 0;
}
pub fn _to_metadata_json(&self) -> Result<String, serde_json::Error> {
return serde_json::to_string_pretty(&self);
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct CoverArt {
pub id: Option<i32>,
pub title: Option<String>,
pub path: Option<String>,
pub data: Option<Vec<u8>>,
}
impl Default for CoverArt {
fn default() -> Self {
CoverArt {
id: None,
title: None,
path: None,
data: None,
}
}
}
impl CoverArt {
pub fn to_data(&self) -> Result<Vec<u8>, std::io::Error> {
let mut path: String = String::new();
match &self.path {
Some(val) => {
path = String::from(val);
}
None => {
();
}
}
let mut file = std::fs::File::open(path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
Ok(buffer)
}
}
+6 -6
View File
@@ -21,8 +21,8 @@ impl Delete {
pub async fn delete_song( pub async fn delete_song(
&mut self, &mut self,
token: &icarus_models::token::AccessToken, token: &icarus_models::token::AccessToken,
song: &models::song::Song, song: &icarus_models::song::Song,
) -> Result<models::song::Song, std::io::Error> { ) -> Result<icarus_models::song::Song, std::io::Error> {
self.api.endpoint = "song/data/delete".to_owned(); self.api.endpoint = "song/data/delete".to_owned();
let url = self.retrieve_url(&song); let url = self.retrieve_url(&song);
let client = reqwest::Client::builder().build().unwrap(); let client = reqwest::Client::builder().build().unwrap();
@@ -33,12 +33,12 @@ impl Delete {
.send() .send()
.await .await
.unwrap(); .unwrap();
let mut sng = models::song::Song::default(); let mut sng = icarus_models::song::Song::default();
match response.status() { match response.status() {
reqwest::StatusCode::OK => { reqwest::StatusCode::OK => {
println!("Success!"); println!("Success!");
let s = response.json::<models::song::Song>().await; let s = response.json::<icarus_models::song::Song>().await;
match s { match s {
// //
Ok(parsed) => { Ok(parsed) => {
@@ -57,7 +57,7 @@ impl Delete {
return Ok(sng); return Ok(sng);
} }
fn retrieve_url(&self, song: &models::song::Song) -> String { fn retrieve_url(&self, song: &icarus_models::song::Song) -> String {
let api = &self.api; let api = &self.api;
let mut url: String = String::from(&api.url); let mut url: String = String::from(&api.url);
url += &String::from("api/"); url += &String::from("api/");
@@ -65,7 +65,7 @@ impl Delete {
url += &String::from("/"); url += &String::from("/");
url += &String::from(&api.endpoint); url += &String::from(&api.endpoint);
url += &String::from("/"); url += &String::from("/");
url += &song.id.unwrap().to_string(); url += &song.id.to_string();
return url; return url;
} }
+5 -7
View File
@@ -24,7 +24,7 @@ impl Download {
pub async fn download_song( pub async fn download_song(
&mut self, &mut self,
token: &icarus_models::token::AccessToken, token: &icarus_models::token::AccessToken,
song: &models::song::Song, song: &icarus_models::song::Song,
) -> Result<String, MyError> { ) -> Result<String, MyError> {
self.api.endpoint = String::from("song/data/download"); self.api.endpoint = String::from("song/data/download");
let url = self.retrieve_url(&song); let url = self.retrieve_url(&song);
@@ -44,8 +44,7 @@ impl Download {
.await; .await;
match response { match response {
Ok(rep) => { Ok(rep) => match rep.status() {
match rep.status() {
reqwest::StatusCode::OK => { reqwest::StatusCode::OK => {
let data = rep.text(); let data = rep.text();
match data.await { match data.await {
@@ -63,8 +62,7 @@ impl Download {
other => { other => {
panic!("Uh oh! Something unexpected happened: {:?}", other); panic!("Uh oh! Something unexpected happened: {:?}", other);
} }
} },
}
Err(er) => { Err(er) => {
return Err(MyError::Request(er)); return Err(MyError::Request(er));
} }
@@ -73,7 +71,7 @@ impl Download {
return Err(MyError::Other(String::from("Error downloading"))); return Err(MyError::Other(String::from("Error downloading")));
} }
fn retrieve_url(&self, song: &models::song::Song) -> String { fn retrieve_url(&self, song: &icarus_models::song::Song) -> String {
let api = &self.api; let api = &self.api;
let mut url: String = String::from(&api.url); let mut url: String = String::from(&api.url);
url += &String::from("api/"); url += &String::from("api/");
@@ -81,7 +79,7 @@ impl Download {
url += &String::from("/"); url += &String::from("/");
url += &String::from(&api.endpoint); url += &String::from(&api.endpoint);
url += &String::from("/"); url += &String::from("/");
url += &song.id.unwrap().to_string(); url += &song.id.to_string();
return url; return url;
} }
+3 -3
View File
@@ -19,9 +19,9 @@ impl RetrieveRecords {
pub async fn get_all_songs( pub async fn get_all_songs(
&mut self, &mut self,
token: &icarus_models::token::AccessToken, token: &icarus_models::token::AccessToken,
) -> Result<Vec<models::song::Song>, Error> { ) -> Result<Vec<icarus_models::song::Song>, Error> {
self.api.endpoint = String::from("song"); self.api.endpoint = String::from("song");
let mut songs: Vec<models::song::Song> = Vec::new(); let mut songs: Vec<icarus_models::song::Song> = Vec::new();
let url = self.retrieve_url(); let url = self.retrieve_url();
let access_token = token.bearer_token(); let access_token = token.bearer_token();
@@ -46,7 +46,7 @@ impl RetrieveRecords {
match response.status() { match response.status() {
reqwest::StatusCode::OK => { reqwest::StatusCode::OK => {
// on success, parse our JSON to an APIResponse // on success, parse our JSON to an APIResponse
let s = response.json::<Vec<models::song::Song>>().await; let s = response.json::<Vec<icarus_models::song::Song>>().await;
match s { match s {
// //
Ok(parsed) => { Ok(parsed) => {
+42 -31
View File
@@ -3,7 +3,6 @@ use std::default::Default;
use http::HeaderMap; use http::HeaderMap;
use http::HeaderValue; use http::HeaderValue;
use reqwest; use reqwest;
use reqwest::multipart::Form;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::models; use crate::models;
@@ -47,14 +46,13 @@ impl Upload {
pub async fn upload_song_with_metadata( pub async fn upload_song_with_metadata(
&mut self, &mut self,
token: &icarus_models::token::AccessToken, token: &icarus_models::token::AccessToken,
song: &models::song::Song, song: &icarus_models::song::Song,
cover: &models::song::CoverArt, cover: &icarus_models::coverart::CoverArt,
album: &models::song::Album, album: &icarus_models::album::collection::Album,
) -> Result<reqwest::Response, std::io::Error> { ) -> Result<reqwest::Response, reqwest::Error> {
self.api.endpoint = String::from("song/data/upload/with/data"); self.api.endpoint = String::from("song/data/upload/with/data");
let url = self.retrieve_url(); let url = self.retrieve_url();
let mut new_song = self.initialize_song(&song, &album); let new_song = self.initialize_song(&song, &album);
new_song.songpath = song.song_path();
let access_token = token.bearer_token(); let access_token = token.bearer_token();
if url.is_empty() { if url.is_empty() {
@@ -63,6 +61,7 @@ impl Upload {
println!("Url: {}", url); println!("Url: {}", url);
println!("Token: {}", access_token); println!("Token: {}", access_token);
println!("Path: {:?}", new_song.songpath);
let mut headers = reqwest::header::HeaderMap::new(); let mut headers = reqwest::header::HeaderMap::new();
headers.insert( headers.insert(
@@ -73,18 +72,20 @@ impl Upload {
let form = self.init_form(&new_song, &cover); let form = self.init_form(&new_song, &cover);
let client = reqwest::Client::builder().build().unwrap(); let client = reqwest::Client::builder().build().unwrap();
let response = client match client
.post(url) .post(url)
.headers(headers) .headers(headers)
.multipart(form) .multipart(form)
.send() .send()
.await; .await
let response_text = response.unwrap(); {
Ok(r) => {
println!("Something was sent"); return Ok(r);
println!("{:?}", response_text); }
Err(err) => {
return Ok(response_text); return Err(err);
}
}
} }
fn _initialize_form( fn _initialize_form(
@@ -92,7 +93,7 @@ impl Upload {
song_raw_data: Vec<u8>, song_raw_data: Vec<u8>,
cover_raw_data: Vec<u8>, cover_raw_data: Vec<u8>,
song_detail: String, song_detail: String,
) -> Form { ) -> reqwest::multipart::Form {
let mut headers = HeaderMap::new(); let mut headers = HeaderMap::new();
headers.insert( headers.insert(
http::header::CONTENT_TYPE, http::header::CONTENT_TYPE,
@@ -109,9 +110,9 @@ impl Upload {
let cover = reqwest::multipart::Part::bytes(cover_raw_data).headers(headers_i); let cover = reqwest::multipart::Part::bytes(cover_raw_data).headers(headers_i);
let mut song_filename = String::from("audio"); let mut song_filename = String::from("audio");
song_filename += icarus_models::constants::WAV_EXTENSION; song_filename += icarus_models::constants::WAVEXTENSION;
let mut cover_filename = String::from("cover"); let mut cover_filename = String::from("cover");
cover_filename += icarus_models::constants::JPG_EXTENSION; cover_filename += icarus_models::constants::JPGEXTENSION;
return reqwest::multipart::Form::new() return reqwest::multipart::Form::new()
.part("cover", cover.file_name(cover_filename)) .part("cover", cover.file_name(cover_filename))
@@ -119,17 +120,22 @@ impl Upload {
.part("file", file.file_name(song_filename)); .part("file", file.file_name(song_filename));
} }
fn init_form(&self, song: &Song, cover: &models::song::CoverArt) -> reqwest::multipart::Form { fn init_form(
&self,
song: &Song,
cover: &icarus_models::coverart::CoverArt,
) -> reqwest::multipart::Form {
let songpath = song.songpath.clone(); let songpath = song.songpath.clone();
let coverpath = cover.path.clone().unwrap(); let coverpath = cover.path.clone();
println!("Cover path: {:?}", coverpath);
let song_detail = song.to_metadata_json().unwrap(); let song_detail = song.to_metadata_json().unwrap();
println!("\n{}\n", song_detail); println!("\n{}\n", song_detail);
let mut song_filename = String::from("audio"); let mut song_filename = String::from("audio");
song_filename += icarus_models::constants::WAV_EXTENSION; song_filename += icarus_models::constants::DEFAULTMUSICEXTENSION;
let mut cover_filename = String::from("cover"); let mut cover_filename = String::from("cover");
cover_filename += icarus_models::constants::JPG_EXTENSION; cover_filename += icarus_models::constants::JPGEXTENSION;
let form = reqwest::multipart::Form::new() let form = reqwest::multipart::Form::new()
.part( .part(
@@ -172,23 +178,28 @@ impl Upload {
return url; return url;
} }
fn initialize_song(&self, song: &models::song::Song, album: &models::song::Album) -> Song { fn initialize_song(
let dur = song.duration.clone().unwrap(); &self,
song: &icarus_models::song::Song,
album: &icarus_models::album::collection::Album,
) -> Song {
let dur = song.duration.clone();
println!("Duration: {}", dur); println!("Duration: {}", dur);
return Song { return Song {
title: String::from(&song.title.clone().unwrap()), title: String::from(&song.title.clone()),
album: album.title.clone(), album: album.title.clone(),
artist: String::from(&song.artist.clone().unwrap().clone()), artist: String::from(&song.artist.clone().clone()),
album_artist: album.album_artist.clone(), album_artist: album.artist.clone(),
year: album.year.clone(), year: album.year.clone(),
genre: album.genre.clone(), genre: album.genre.clone(),
duration: f64::round(dur) as i32, // duration: f64::round(dur) as i32,
track: (song.track.clone().unwrap()), duration: dur,
track: (song.track.clone()),
track_count: album.track_count.clone(), track_count: album.track_count.clone(),
disc: song.disc.clone().unwrap(), disc: song.disc.clone(),
disc_count: album.disc_count.clone(), disc_count: album.disc_count.clone(),
songpath: String::new(), songpath: song.directory.clone() + "/" + &song.filename.clone(),
}; };
} }
} }
+1
View File
@@ -1 +1,2 @@
pub mod checks; pub mod checks;
pub mod string;
+10
View File
@@ -0,0 +1,10 @@
pub fn o_to_string(val: &std::ffi::OsString) -> Result<std::string::String, std::io::Error> {
match val.clone().into_string() {
Ok(value) => Ok(value),
Err(_) => Err(std::io::Error::new(
std::io::ErrorKind::Other,
String::from("Error"),
)),
}
}
+31
View File
@@ -0,0 +1,31 @@
{
"album": "Sample Tracks 2",
"album_artist": "KD",
"genre": "Country",
"year": 2025,
"track_count": 3,
"disc_count": 1,
"tracks": [
{
"title": "Uh huh",
"artist": "KD",
"disc": 1,
"track": 1,
"duration": 32
},
{
"title": "Bold and brash",
"artist": "KD",
"disc": 1,
"track": 2,
"duration": 37
},
{
"title": "How does this work?",
"artist": "KD",
"disc": 1,
"track": 3,
"duration": 46
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.