Skip to content

Commit

Permalink
Merge pull request #52 from aksiksi/latest
Browse files Browse the repository at this point in the history
Add support for only monitoring sessions for specific users
  • Loading branch information
p-hueber authored Oct 20, 2024
2 parents 9cfc5a1 + 1152205 commit 9369446
Show file tree
Hide file tree
Showing 7 changed files with 298 additions and 22 deletions.
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ FROM alpine:latest

ENV INTERVAL=900
ENV REMAINING_EPISODES=2
ENV USERS=

COPY --from=builder /app/target/release/prefetcharr /

Expand All @@ -21,4 +22,5 @@ CMD ["sh", "-c", "./prefetcharr \
--log-dir \"${LOG_DIR}\" \
--interval \"${INTERVAL}\" \
--remaining-episodes \"${REMAINING_EPISODES}\" \
--users \"${USERS}\" \
"]
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ services:
- INTERVAL=900
# The last <NUM> episodes trigger a search
- REMAINING_EPISODES=2
# Only monitor sessions for specific user IDs or names
- USERS=john,12345,alex
volumes:
- /path/to/log/dir:/log

Expand Down
8 changes: 7 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ struct Args {
/// The last <NUM> episodes trigger a search
#[arg(long, value_name = "NUM", default_value_t = 2)]
remaining_episodes: u8,
/// User IDs or names to monitor episodes for (default: empty/all users)
///
/// Each entry here is checked against the user's ID and name
#[arg(long, value_name = "USER", value_delimiter = ',', num_args = 0..)]
users: Vec<String>,
}

#[derive(Clone, Debug, ValueEnum)]
Expand Down Expand Up @@ -144,7 +149,8 @@ async fn run(args: Args) -> anyhow::Result<()> {
};

let seen = Seen::default();
let mut actor = process::Actor::new(rx, sonarr_client, seen, args.remaining_episodes);
let mut actor =
process::Actor::new(rx, sonarr_client, seen, args.remaining_episodes, args.users);

tokio::join!(watcher, actor.process());

Expand Down
2 changes: 2 additions & 0 deletions src/media_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ pub struct NowPlaying {
pub series: Series,
pub episode: i32,
pub season: i32,
pub user_id: String,
pub user_name: String,
}

pub trait MediaServer: Sized {
Expand Down
44 changes: 29 additions & 15 deletions src/media_server/embyfin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct Series {
#[serde(rename_all = "PascalCase")]
pub struct SessionInfo {
user_id: String,
user_name: String,
now_playing_item: Episode,
#[serde(flatten)]
other: serde_json::Value,
Expand Down Expand Up @@ -159,6 +160,8 @@ impl MediaServer for Client {
session: Self::Session,
) -> std::prelude::v1::Result<NowPlaying, Self::Error> {
let episode_num = session.now_playing_item.index_number;
let user_id = session.user_id.clone();
let user_name = session.user_name.clone();
let ids = Ids::from(session);

let series: Series = self.item(&ids.user, &ids.series).await?;
Expand All @@ -177,6 +180,8 @@ impl MediaServer for Client {
series,
episode: episode_num,
season: season_num,
user_id,
user_name,
};

Ok(now_playing)
Expand All @@ -197,7 +202,8 @@ mod test {
fn episode() -> serde_json::Value {
serde_json::json!(
[{
"UserId": "user",
"UserId": "08ba1929-681e-4b24-929b-9245852f65c0",
"UserName": "user",
"NowPlayingItem": {
"SeriesId": "a",
"SeasonId": "b",
Expand Down Expand Up @@ -226,14 +232,14 @@ mod test {

let season_mock = server
.mock_async(|when, then| {
when.path("/pathprefix/Users/user/Items/b");
when.path("/pathprefix/Users/08ba1929-681e-4b24-929b-9245852f65c0/Items/b");
then.json_body(serde_json::json!({"IndexNumber": 3}));
})
.await;

let series_mock = server
.mock_async(|when, then| {
when.path("/pathprefix/Users/user/Items/a");
when.path("/pathprefix/Users/08ba1929-681e-4b24-929b-9245852f65c0/Items/a");
then.json_body(series());
})
.await;
Expand All @@ -251,6 +257,8 @@ mod test {
series: Series::Tvdb(1234),
episode: 5,
season: 3,
user_id: "08ba1929-681e-4b24-929b-9245852f65c0".to_string(),
user_name: "user".to_string(),
});

assert_eq!(message, Some(message_expect));
Expand All @@ -273,15 +281,17 @@ mod test {
then.json_body(serde_json::json!(
[{ "invalid": "session" },
{
"UserId": "user",
"UserId": "08ba1929-681e-4b24-929b-9245852f65c0",
"UserName": "user",
"NowPlayingItem": {
"SeriesId": "invalid",
"SeasonId": "invalid",
"IndexNumber": 5
}
},
{
"UserId": "user",
"UserId": "08ba1929-681e-4b24-929b-9245852f65c0",
"UserName": "user",
"NowPlayingItem": {
"SeriesId": "a",
"SeasonId": "b",
Expand All @@ -294,14 +304,14 @@ mod test {

let season_mock = server
.mock_async(|when, then| {
when.path("/pathprefix/Users/user/Items/b");
when.path("/pathprefix/Users/08ba1929-681e-4b24-929b-9245852f65c0/Items/b");
then.json_body(serde_json::json!({"IndexNumber": 3}));
})
.await;

let series_mock = server
.mock_async(|when, then| {
when.path("/pathprefix/Users/user/Items/a");
when.path("/pathprefix/Users/08ba1929-681e-4b24-929b-9245852f65c0/Items/a");
then.json_body(series());
})
.await;
Expand All @@ -319,6 +329,8 @@ mod test {
series: Series::Tvdb(1234),
episode: 5,
season: 3,
user_id: "08ba1929-681e-4b24-929b-9245852f65c0".to_string(),
user_name: "user".to_string(),
});

assert_eq!(message, Some(message_expect));
Expand All @@ -344,14 +356,14 @@ mod test {

let season_mock = server
.mock_async(|when, then| {
when.path("/pathprefix/Users/user/Items/b");
when.path("/pathprefix/Users/08ba1929-681e-4b24-929b-9245852f65c0/Items/b");
then.json_body(serde_json::json!({"IndexNumber": 3}));
})
.await;

let series_mock = server
.mock_async(|when, then| {
when.path("/pathprefix/Users/user/Items/a");
when.path("/pathprefix/Users/08ba1929-681e-4b24-929b-9245852f65c0/Items/a");
then.json_body(serde_json::json!({
"Name": "Test Show",
"ProviderIds": { }
Expand All @@ -369,6 +381,8 @@ mod test {
series: Series::Title("Test Show".to_string()),
episode: 5,
season: 3,
user_id: "08ba1929-681e-4b24-929b-9245852f65c0".to_string(),
user_name: "user".to_string(),
});

assert_eq!(message, Some(message_expect));
Expand Down Expand Up @@ -399,14 +413,14 @@ mod test {

let _season_mock = server
.mock_async(|when, then| {
when.path("/pathprefix/Users/user/Items/b");
when.path("/pathprefix/Users/08ba1929-681e-4b24-929b-9245852f65c0/Items/b");
then.json_body(serde_json::json!({"IndexNumber": 3}));
})
.await;

let _series_mock = server
.mock_async(|when, then| {
when.path("/pathprefix/Users/user/Items/a");
when.path("/pathprefix/Users/08ba1929-681e-4b24-929b-9245852f65c0/Items/a");
then.json_body(series());
})
.await;
Expand Down Expand Up @@ -443,14 +457,14 @@ mod test {

let _season_mock = server
.mock_async(|when, then| {
when.path("/pathprefix/Users/user/Items/b");
when.path("/pathprefix/Users/08ba1929-681e-4b24-929b-9245852f65c0/Items/b");
then.json_body(serde_json::json!({"IndexNumber": 3}));
})
.await;

let _series_mock = server
.mock_async(|when, then| {
when.path("/pathprefix/Users/user/Items/a");
when.path("/pathprefix/Users/08ba1929-681e-4b24-929b-9245852f65c0/Items/a");
then.json_body(series());
})
.await;
Expand Down Expand Up @@ -485,14 +499,14 @@ mod test {

let _season_mock = server
.mock_async(|when, then| {
when.path("/pathprefix/Users/user/Items/b");
when.path("/pathprefix/Users/08ba1929-681e-4b24-929b-9245852f65c0/Items/b");
then.json_body(serde_json::json!({"IndexNumber": 3}));
})
.await;

let _series_mock = server
.mock_async(|when, then| {
when.path("/pathprefix/Users/user/Items/a");
when.path("/pathprefix/Users/08ba1929-681e-4b24-929b-9245852f65c0/Items/a");
then.json_body(series());
})
.await;
Expand Down
39 changes: 36 additions & 3 deletions src/media_server/plex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ use serde_json::Value;

use super::{MediaServer, NowPlaying};

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct User {
id: String,
title: String,
#[serde(flatten)]
_other: serde_json::Value,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Episode {
Expand All @@ -13,6 +22,7 @@ pub struct Episode {
index: i32,
parent_index: i32,
r#type: String,
user: User,
#[serde(flatten)]
_other: serde_json::Value,
}
Expand Down Expand Up @@ -113,6 +123,8 @@ impl MediaServer for Client {
series,
episode,
season,
user_id: session.user.id,
user_name: session.user.title,
})
}
}
Expand All @@ -137,7 +149,12 @@ mod test {
"grandparentKey": "path/to/series",
"index": 5,
"parentIndex": 3,
"type": "episode"
"type": "episode",
"user": {
"id": "1",
"title": "user",
"thumb": "ignore"
}
}]
}
}
Expand Down Expand Up @@ -187,6 +204,8 @@ mod test {
series: Series::Tvdb(1234),
episode: 5,
season: 3,
user_id: "1".to_string(),
user_name: "user".to_string(),
});

assert_eq!(message, Some(message_expect));
Expand Down Expand Up @@ -228,7 +247,12 @@ mod test {
"grandparentKey": "path/to/series",
"index": 5,
"parentIndex": 3,
"type": "episode"
"type": "episode",
"user": {
"id": "1",
"title": "user",
"thumb": "ignore"
}
}
]
}
Expand All @@ -253,6 +277,8 @@ mod test {
series: Series::Tvdb(1234),
episode: 5,
season: 3,
user_id: "1".to_string(),
user_name: "user".to_string(),
});

assert_eq!(message, Some(message_expect));
Expand Down Expand Up @@ -280,7 +306,12 @@ mod test {
"grandparentKey": "invalid",
"index": 5,
"parentIndex": 3,
"type": "episode"
"type": "episode",
"user": {
"id": "1",
"title": "user",
"thumb": "ignore"
}
}
]
}
Expand All @@ -305,6 +336,8 @@ mod test {
series: Series::Title("Test Show".to_string()),
episode: 5,
season: 3,
user_id: "1".to_string(),
user_name: "user".to_string(),
});

assert_eq!(message, Some(message_expect));
Expand Down
Loading

0 comments on commit 9369446

Please sign in to comment.