mirror of
https://github.com/agersant/polaris
synced 2024-12-02 17:49:10 +00:00
Added DDNS broadcasting
This commit is contained in:
parent
aadbe34fd4
commit
3923229834
7 changed files with 148 additions and 7 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2,6 +2,7 @@
|
|||
name = "polaris"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"id3 0.1.10 (git+https://github.com/jameshurst/rust-id3)",
|
||||
"iron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (git+https://github.com/retep998/winapi-rs)",
|
||||
|
|
|
@ -7,6 +7,7 @@ authors = ["Antoine Gersant <antoine.gersant@lesforges.org>"]
|
|||
ui = []
|
||||
|
||||
[dependencies]
|
||||
hyper = "0.9.10"
|
||||
id3 = { git = "https://github.com/jameshurst/rust-id3" }
|
||||
iron = "0.4.0"
|
||||
mount = "0.2.1"
|
||||
|
|
|
@ -6,4 +6,9 @@ source = 'M:/Music/Genres/'
|
|||
|
||||
[[users]]
|
||||
name = 'agersant'
|
||||
password = 'test'
|
||||
password = 'test'
|
||||
|
||||
[ydns]
|
||||
host = 'your_hostname.ydns.eu'
|
||||
username = 'your_username'
|
||||
password = 'your_ydns_password'
|
||||
|
|
|
@ -202,7 +202,7 @@ pub enum CollectionFile {
|
|||
pub struct Collection {
|
||||
vfs: Vfs,
|
||||
users: Vec<User>,
|
||||
album_art_pattern: Regex,
|
||||
album_art_pattern: Option<Regex>,
|
||||
}
|
||||
|
||||
impl Collection {
|
||||
|
@ -210,7 +210,7 @@ impl Collection {
|
|||
Collection {
|
||||
vfs: Vfs::new(),
|
||||
users: Vec::new(),
|
||||
album_art_pattern: Regex::new("^Folder\\.png$").unwrap(),
|
||||
album_art_pattern: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,6 +294,11 @@ impl Collection {
|
|||
}
|
||||
|
||||
fn get_album_art(&self, real_path: &Path) -> Result<Option<PathBuf>, PError> {
|
||||
let pattern = match self.album_art_pattern {
|
||||
Some(ref p) => p,
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
||||
let mut real_dir = real_path;
|
||||
if real_dir.is_file() {
|
||||
real_dir = try!(real_dir.parent().ok_or(PError::AlbumArtSearchError));
|
||||
|
@ -311,7 +316,7 @@ impl Collection {
|
|||
None => return false,
|
||||
Some(r) => r,
|
||||
};
|
||||
self.album_art_pattern.is_match(file_name)
|
||||
pattern.is_match(file_name)
|
||||
});
|
||||
|
||||
match album_art {
|
||||
|
|
|
@ -6,6 +6,7 @@ use std::path;
|
|||
use toml;
|
||||
|
||||
use collection::User;
|
||||
use ddns::DDNSConfig;
|
||||
use vfs::MountDir;
|
||||
|
||||
const CONFIG_MOUNT_DIRS: &'static str = "mount_dirs";
|
||||
|
@ -15,6 +16,10 @@ const CONFIG_USERS: &'static str = "users";
|
|||
const CONFIG_USER_NAME: &'static str = "name";
|
||||
const CONFIG_USER_PASSWORD: &'static str = "password";
|
||||
const CONFIG_ALBUM_ART_PATTERN: &'static str = "album_art_pattern";
|
||||
const CONFIG_DDNS: &'static str = "ydns";
|
||||
const CONFIG_DDNS_HOST: &'static str = "host";
|
||||
const CONFIG_DDNS_USERNAME: &'static str = "username";
|
||||
const CONFIG_DDNS_PASSWORD: &'static str = "password";
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ConfigError {
|
||||
|
@ -24,6 +29,7 @@ pub enum ConfigError {
|
|||
AlbumArtPatternParseError,
|
||||
UsersParseError,
|
||||
MountDirsParseError,
|
||||
DDNSParseError,
|
||||
}
|
||||
|
||||
impl From<io::Error> for ConfigError {
|
||||
|
@ -41,7 +47,8 @@ impl From<regex::Error> for ConfigError {
|
|||
pub struct Config {
|
||||
pub mount_dirs: Vec<MountDir>,
|
||||
pub users: Vec<User>,
|
||||
pub album_art_pattern: regex::Regex,
|
||||
pub album_art_pattern: Option<regex::Regex>,
|
||||
pub ddns: Option<DDNSConfig>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
|
@ -55,12 +62,14 @@ impl Config {
|
|||
let mut config = Config {
|
||||
mount_dirs: Vec::new(),
|
||||
users: Vec::new(),
|
||||
album_art_pattern: regex::Regex::new("^Folder\\.png$").unwrap(),
|
||||
album_art_pattern: None,
|
||||
ddns: None,
|
||||
};
|
||||
|
||||
try!(config.parse_mount_points(&parsed_config));
|
||||
try!(config.parse_users(&parsed_config));
|
||||
try!(config.parse_album_art_pattern(&parsed_config));
|
||||
try!(config.parse_ddns(&parsed_config));
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
@ -74,7 +83,7 @@ impl Config {
|
|||
&toml::Value::String(ref s) => s,
|
||||
_ => return Err(ConfigError::AlbumArtPatternParseError),
|
||||
};
|
||||
self.album_art_pattern = try!(regex::Regex::new(pattern));
|
||||
self.album_art_pattern = Some(try!(regex::Regex::new(pattern)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -152,4 +161,30 @@ impl Config {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_ddns(&mut self, source: &toml::Table) -> Result<(), ConfigError> {
|
||||
let ddns = match source.get(CONFIG_DDNS) {
|
||||
Some(s) => s,
|
||||
None => return Ok(()),
|
||||
};
|
||||
let ddns = match ddns {
|
||||
&toml::Value::Table(ref a) => a,
|
||||
_ => return Err(ConfigError::DDNSParseError),
|
||||
};
|
||||
|
||||
let host = try!(ddns.get(CONFIG_DDNS_HOST).ok_or(ConfigError::DDNSParseError)).as_str();
|
||||
let username = try!(ddns.get(CONFIG_DDNS_USERNAME).ok_or(ConfigError::DDNSParseError)).as_str();
|
||||
let password = try!(ddns.get(CONFIG_DDNS_PASSWORD).ok_or(ConfigError::DDNSParseError)).as_str();
|
||||
|
||||
let host = try!(host.ok_or(ConfigError::DDNSParseError));
|
||||
let username = try!(username.ok_or(ConfigError::DDNSParseError));
|
||||
let password = try!(password.ok_or(ConfigError::DDNSParseError));
|
||||
|
||||
self.ddns = Some(DDNSConfig {
|
||||
host: host.to_owned(),
|
||||
username: username.to_owned(),
|
||||
password: password.to_owned(),
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
78
src/ddns.rs
Normal file
78
src/ddns.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
use hyper;
|
||||
use hyper::client::Client;
|
||||
use hyper::header::{Authorization, Basic };
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::thread;
|
||||
use std::time;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DDNSConfig {
|
||||
pub host: String,
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum DDNSError {
|
||||
IoError(io::Error),
|
||||
HyperError(hyper::Error),
|
||||
UpdateError(hyper::status::StatusCode),
|
||||
}
|
||||
|
||||
impl From<io::Error> for DDNSError {
|
||||
fn from(err: io::Error) -> DDNSError {
|
||||
DDNSError::IoError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<hyper::Error> for DDNSError {
|
||||
fn from(err: hyper::Error) -> DDNSError {
|
||||
DDNSError::HyperError(err)
|
||||
}
|
||||
}
|
||||
|
||||
const MY_IP_API_URL: &'static str = "http://api.ipify.org";
|
||||
const DDNS_UPDATE_URL: &'static str = "http://ydns.io/api/v1/update/";
|
||||
|
||||
fn get_my_ip() -> Result<String, DDNSError> {
|
||||
let client = Client::new();
|
||||
let mut res = try!(client.get(MY_IP_API_URL).send());
|
||||
let mut buf = String::new();
|
||||
try!(res.read_to_string(&mut buf));
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
fn update_my_ip(ip: &String, config: &DDNSConfig) -> Result<(), DDNSError> {
|
||||
let client = Client::new();
|
||||
let url = DDNS_UPDATE_URL;
|
||||
let host = &config.host;
|
||||
let full_url = format!("{}?host={}&ip={}", url, host, ip);
|
||||
let auth_header = Authorization(Basic {
|
||||
username: config.username.clone(),
|
||||
password: Some(config.password.to_owned())
|
||||
});
|
||||
|
||||
let res = try!(client.get(full_url.as_str()).header(auth_header).send());
|
||||
match res.status {
|
||||
hyper::status::StatusCode::Ok => Ok(()),
|
||||
s => Err(DDNSError::UpdateError(s)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(config: DDNSConfig) {
|
||||
loop {
|
||||
let my_ip_res = get_my_ip();
|
||||
if let Ok(my_ip) = my_ip_res {
|
||||
match update_my_ip(&my_ip, &config) {
|
||||
Err(e) => println!("Dynamic DNS Error: {:?}", e),
|
||||
Ok(_) => (),
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
println!("Dynamic DNS Error: could not retrieve our own IP address");
|
||||
}
|
||||
thread::sleep(time::Duration::from_secs(60 * 30));
|
||||
}
|
||||
}
|
16
src/main.rs
16
src/main.rs
|
@ -1,4 +1,5 @@
|
|||
extern crate core;
|
||||
extern crate hyper;
|
||||
extern crate id3;
|
||||
extern crate iron;
|
||||
extern crate mount;
|
||||
|
@ -32,15 +33,18 @@ use staticfile::Static;
|
|||
mod api;
|
||||
mod collection;
|
||||
mod config;
|
||||
mod ddns;
|
||||
mod error;
|
||||
mod ui;
|
||||
mod vfs;
|
||||
|
||||
fn main() {
|
||||
|
||||
// Parse config
|
||||
let config_file = Path::new("Polaris.toml");
|
||||
let config = config::Config::parse(&config_file).unwrap();
|
||||
|
||||
// Start server
|
||||
println!("Starting up server");
|
||||
let mut api_chain;
|
||||
{
|
||||
|
@ -64,6 +68,18 @@ fn main() {
|
|||
mount.mount("/", Static::new(Path::new("web")));
|
||||
let mut server = Iron::new(mount).http(("0.0.0.0", 5050)).unwrap();
|
||||
|
||||
// Start DDNS updates
|
||||
match config.ddns {
|
||||
Some(ref ddns_config) => {
|
||||
let ddns_config = ddns_config.clone();
|
||||
std::thread::spawn(|| {
|
||||
ddns::run(ddns_config);
|
||||
});
|
||||
},
|
||||
None => (),
|
||||
};
|
||||
|
||||
// Run UI
|
||||
ui::run();
|
||||
|
||||
println!("Shutting down server");
|
||||
|
|
Loading…
Reference in a new issue