Compare commits
10 Commits
8c1b9b79d0
...
6b1ac35321
Author | SHA1 | Date |
---|---|---|
Paul van Tilburg | 6b1ac35321 | |
Paul van Tilburg | 3318736bbc | |
Paul van Tilburg | c40f85a313 | |
Paul van Tilburg | bf26bcf3b5 | |
Paul van Tilburg | f3c652e86a | |
Paul van Tilburg | b05390d9ad | |
Paul van Tilburg | bad0771897 | |
Paul van Tilburg | 66452cc96d | |
Paul van Tilburg | 32040f3b0f | |
Paul van Tilburg | bde6135f70 |
File diff suppressed because it is too large
Load Diff
|
@ -9,7 +9,7 @@ license = "MIT"
|
|||
|
||||
[dependencies]
|
||||
async-trait = "0.1.57"
|
||||
cached = { version = "0.38.0", features = ["async"] }
|
||||
cached = { version = "0.39.0", features = ["async"] }
|
||||
chrono = { version = "0.4.19", features = ["serde"] }
|
||||
enum_dispatch = "0.3.8"
|
||||
mime-db = "1.6.0"
|
||||
|
@ -20,7 +20,7 @@ rss = "2.0.1"
|
|||
thiserror = "1.0.31"
|
||||
url = { version = "2.2.2", features = ["serde"] }
|
||||
youtube_dl = { version = "0.7.0", features = ["tokio"] }
|
||||
ytextract = "0.11.0"
|
||||
ytextract = { version = "0.11.0", git = "https://github.com/paulvt/ytextract.git", branch = "fix-date-parsing-live" }
|
||||
|
||||
[package.metadata.deb]
|
||||
maintainer = "Paul van Tilburg <paul@luon.net>"
|
||||
|
|
|
@ -26,7 +26,7 @@ builds when you don't add `--release`.)
|
|||
### Configuration
|
||||
|
||||
For now, you will need to provide Rocket with configuration to tell it at which
|
||||
URL Podbringer is hosted. This needs to be done even if you are not using a
|
||||
public URL Podbringer is hosted. This needs to be done even if you are not using a
|
||||
reverse proxy, in which case you need to provide it with the proxied URL. You
|
||||
can also use the configuration to configure a different address and/or port.
|
||||
Just create a `Rocket.toml` file that contains (or copy `Rocket.toml.example`):
|
||||
|
@ -35,7 +35,7 @@ Just create a `Rocket.toml` file that contains (or copy `Rocket.toml.example`):
|
|||
[default]
|
||||
address = "0.0.0.0"
|
||||
port = 7062
|
||||
url = "https://my.domain.tld/podbringer"
|
||||
public_url = "https://my.domain.tld/podbringer"
|
||||
```
|
||||
|
||||
This will work independent of the type of build. For more about Rocket's
|
||||
|
@ -53,7 +53,7 @@ need to use for Podbringer is comprised of the following parts:
|
|||
```text
|
||||
https://my.domain.tld/podbringer/feed/mixcloud/myfavouriteband
|
||||
|------------------------------| |-------||--------------|
|
||||
The Podbringer location URL Service User @ service
|
||||
The Podbringer public URL Service User @ service
|
||||
```
|
||||
|
||||
### Feed item limit
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[default]
|
||||
address = "0.0.0.0"
|
||||
port = 7062
|
||||
url = "https://my.domain.tld/podbringer"
|
||||
public_url = "https://my.domain.tld/podbringer"
|
||||
|
|
|
@ -6,12 +6,13 @@ use std::path::{Path, PathBuf};
|
|||
|
||||
use async_trait::async_trait;
|
||||
use cached::proc_macro::cached;
|
||||
use chrono::Utc;
|
||||
use chrono::{DateTime, Utc};
|
||||
use reqwest::Url;
|
||||
use rocket::futures::StreamExt;
|
||||
use ytextract::playlist::video::{Error as YouTubeVideoError, Video as YouTubeVideo};
|
||||
use ytextract::playlist::video::{Error as YouTubeVideoError, Video as YouTubePlaylistVideo};
|
||||
use ytextract::{
|
||||
Channel as YouTubeChannel, Client, Playlist as YouTubePlaylist, Stream as YouTubeStream,
|
||||
Video as YouTubeVideo,
|
||||
};
|
||||
|
||||
use super::{Channel, Enclosure, Item};
|
||||
|
@ -187,12 +188,17 @@ impl From<YouTubeVideoWithStream> for Item {
|
|||
let mut link = Url::parse(VIDEO_BASE_URL).expect("valid URL");
|
||||
link.query_pairs_mut().append_pair("v", &id);
|
||||
let description = Some(format!("Taken from YouTube: {0}", link));
|
||||
let duration = Some(video.length().as_secs() as u32);
|
||||
let duration = Some(video.duration().as_secs() as u32);
|
||||
let image = video
|
||||
.thumbnails()
|
||||
.iter()
|
||||
.max_by_key(|tn| tn.width * tn.height)
|
||||
.map(|tn| tn.url.clone());
|
||||
let timestamp = video
|
||||
.date()
|
||||
.and_hms_opt(12, 0, 0)
|
||||
.expect("Invalid hour, minute and/or second");
|
||||
let updated_at = DateTime::from_utc(timestamp, Utc);
|
||||
|
||||
Item {
|
||||
title: video.title().to_string(),
|
||||
|
@ -204,7 +210,7 @@ impl From<YouTubeVideoWithStream> for Item {
|
|||
guid: id,
|
||||
keywords: Default::default(),
|
||||
image,
|
||||
updated_at: Utc::now(), // TODO: Get a decent timestamp somewhere?!
|
||||
updated_at,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -254,8 +260,8 @@ async fn fetch_channel_videos(
|
|||
let yt_videos_w_streams = yt_channel
|
||||
.uploads()
|
||||
.await?
|
||||
.take(limit)
|
||||
.filter_map(fetch_stream)
|
||||
.take(limit)
|
||||
.collect()
|
||||
.await;
|
||||
|
||||
|
@ -264,13 +270,14 @@ async fn fetch_channel_videos(
|
|||
|
||||
/// Fetches the stream and relevant metadata for a YouTube video result.
|
||||
///
|
||||
/// If there is a video retieving the metadata, the video is discarded/ignored.
|
||||
/// If there is a error retrieving the metadata, the video is discarded/ignored.
|
||||
/// If there are problems retrieving the streams or metadata, the video is also discarded.
|
||||
async fn fetch_stream(
|
||||
yt_video: Result<YouTubeVideo, YouTubeVideoError>,
|
||||
yt_video: Result<YouTubePlaylistVideo, YouTubeVideoError>,
|
||||
) -> Option<YouTubeVideoWithStream> {
|
||||
match yt_video {
|
||||
Ok(video) => {
|
||||
let video = video.upgrade().await.ok()?;
|
||||
let stream = video
|
||||
.streams()
|
||||
.await
|
||||
|
|
|
@ -28,7 +28,9 @@ pub(crate) fn construct(backend_id: &str, config: &Config, channel: Channel) ->
|
|||
.unwrap_or_default(),
|
||||
)
|
||||
.build();
|
||||
let mut last_build = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(0, 0), Utc);
|
||||
let unix_timestamp = NaiveDateTime::from_timestamp_opt(0, 0)
|
||||
.expect("Out-of-range seconds or invalid nanoseconds");
|
||||
let mut last_build = DateTime::from_utc(unix_timestamp, Utc);
|
||||
let generator = String::from(concat!(
|
||||
env!("CARGO_PKG_NAME"),
|
||||
" ",
|
||||
|
@ -92,7 +94,7 @@ fn construct_item(
|
|||
})
|
||||
.collect::<Vec<_>>();
|
||||
let url = uri!(
|
||||
Absolute::parse(&config.url).expect("valid URL"),
|
||||
Absolute::parse(&config.public_url).expect("valid URL"),
|
||||
crate::get_download(backend_id = backend_id, file = item.enclosure.file)
|
||||
);
|
||||
let enclosure = EnclosureBuilder::default()
|
||||
|
|
13
src/lib.rs
13
src/lib.rs
|
@ -5,7 +5,12 @@
|
|||
missing_debug_implementations,
|
||||
rust_2018_idioms,
|
||||
rustdoc::broken_intra_doc_links,
|
||||
trivial_numeric_casts
|
||||
trivial_numeric_casts,
|
||||
renamed_and_removed_lints,
|
||||
unsafe_code,
|
||||
unstable_features,
|
||||
unused_import_braces,
|
||||
unused_qualifications
|
||||
)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
|
@ -89,9 +94,9 @@ pub(crate) type Result<T, E = Error> = std::result::Result<T, E>;
|
|||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub(crate) struct Config {
|
||||
/// The URL at which the application is hosted or proxied from.
|
||||
/// The public URL at which the application is hosted or proxied from.
|
||||
#[serde(default)]
|
||||
url: String,
|
||||
public_url: String,
|
||||
}
|
||||
|
||||
/// A Rocket responder wrapper type for RSS feeds.
|
||||
|
@ -127,7 +132,7 @@ async fn get_feed(
|
|||
/// Returns a simple index page that explains the usage.
|
||||
#[get("/")]
|
||||
pub(crate) async fn get_index(config: &State<Config>) -> Template {
|
||||
Template::render("index", context! { url: &config.url })
|
||||
Template::render("index", context! { url: &config.public_url })
|
||||
}
|
||||
|
||||
/// Sets up Rocket.
|
||||
|
|
|
@ -5,7 +5,12 @@
|
|||
missing_debug_implementations,
|
||||
rust_2018_idioms,
|
||||
rustdoc::broken_intra_doc_links,
|
||||
trivial_numeric_casts
|
||||
trivial_numeric_casts,
|
||||
renamed_and_removed_lints,
|
||||
unsafe_code,
|
||||
unstable_features,
|
||||
unused_import_braces,
|
||||
unused_qualifications
|
||||
)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<pre>
|
||||
https://my.domain.tld/podbringer/feed/mixcloud/myfavouriteband
|
||||
|------------------------------| |-------||--------------|
|
||||
The Podbringer location URL Service User @ service
|
||||
The Podbringer public URL Service User @ service
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
|
|
Loading…
Reference in New Issue