Skip to content

Commit

Permalink
fix: rework pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
lostb1t committed Aug 13, 2023
1 parent 272addc commit 70a990d
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 66 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ docker-run:


run:
REPLEX_REDIRECT_STREAMS=0 REPLEX_DISABLE_RELATED=1 REPLEX_DISABLE_LEAF_COUNT=0 REPLEX_DISABLE_USER_STATE=1 REPLEX_ENABLE_CONSOLE=0 REPLEX_CACHE_TTL=0 REPLEX_HOST=https://46-4-30-217.01b0839de64b49138531cab1bf32f7c2.plex.direct:42405 RUST_LOG="info,replex=info" cargo watch -x run
REPLEX_INCLUDE_WATCHED=0 REPLEX_REDIRECT_STREAMS=0 REPLEX_DISABLE_RELATED=1 REPLEX_DISABLE_LEAF_COUNT=0 REPLEX_DISABLE_USER_STATE=1 REPLEX_ENABLE_CONSOLE=0 REPLEX_CACHE_TTL=0 REPLEX_HOST=https://46-4-30-217.01b0839de64b49138531cab1bf32f7c2.plex.direct:42405 RUST_LOG="info,replex=info" cargo watch -x run

# run:
# REPLEX_ENABLE_CONSOLE=0 REPLEX_CACHE_TTL=0 REPLEX_HOST=https://46-4-30-217.01b0839de64b49138531cab1bf32f7c2.plex.direct:42405 RUST_LOG="info" cargo run
Expand Down
3 changes: 3 additions & 0 deletions src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ pub struct MetaData {
#[yaserde(attribute)]
#[serde(skip_serializing_if = "Option::is_none")]
pub index: Option<u32>,
#[yaserde(attribute)]
#[serde(skip_serializing_if = "Option::is_none")]
pub subtype: Option<String>,
#[yaserde(attribute, rename = "parentYear")]
#[serde(skip_serializing_if = "Option::is_none")]
pub parent_year: Option<i32>,
Expand Down
68 changes: 54 additions & 14 deletions src/plex_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ impl PlexClient {

// we want guids for banners
path = format!("{}&includeGuids=1", path);
// dbg!(&path);

let resp = self.get(path).await.unwrap();
let container: MediaContainerWrapper<MediaContainer> =
Expand All @@ -154,41 +155,80 @@ impl PlexClient {
id: u32,
offset: i32,
limit: i32,
original_limit: i32
original_limit: i32,
) -> anyhow::Result<MediaContainerWrapper<MediaContainer>> {
let config: Config = Config::figment().extract().unwrap();
let mut c = self
.get_collection_children(id, Some(offset), Some(limit))
.await?;

// dbg!(limit);
// dbg!(c.media_container.children_mut())
if !config.include_watched {
// dbg!(c.media_container.children_mut().len());
c.media_container.children_mut().retain(|x| !x.is_watched());

// dbg!(c.media_container.children_mut().len());
// dbg!("-----");

let children_lenght = c.media_container.children_mut().len() as i32;
let total_size = c.media_container.total_size.unwrap();
if children_lenght < original_limit
&& total_size > offset + limit && offset < total_size
&& total_size > offset + limit
&& offset < total_size
{
// load more
return self.load_collection_children_recursive(
id,
offset,
limit + 10,
original_limit
).await;
return self
.load_collection_children_recursive(
id,
offset,
limit + 10,
original_limit,
)
.await;
}
}
Ok(c)
}


pub async fn get_collection(
&self,
id: i32,
) -> Result<MediaContainerWrapper<MediaContainer>> {
let res = self
.get(format!("/library/collections/{}", id))
.await?;
let res = self.get(format!("/library/collections/{}", id)).await?;

if res.status() == 404 {
return Err(salvo::http::StatusError::not_found().into());
}

let container: MediaContainerWrapper<MediaContainer> =
from_reqwest_response(res).await.unwrap();
Ok(container)
}

// theres actually a global endpoint https://plex.sjoerdarendsen.dev/library/all?show.collection=2042780&collection=2042780&X-Plex-Container-Start=0&X-Plex-Container-Size=72
pub async fn get_collection_total_size_unwatched(
&self,
section_id: i32,
collection_index: i32,
r#type: String,
) -> Result<MediaContainerWrapper<MediaContainer>> {
let mut path = format!("/library/sections/{}/all?X-Plex-Container-Start=0&X-Plex-Container-Size=0", section_id);
// dbg!(&path);

if r#type == "show" {
path = format!(
"{}&show.unwatchedLeaves=1&show.collection={}",
path, collection_index
);
}

if r#type == "movie" {
path = format!(
"{}&movie.unwatched=1&movie.collection={}",
path, collection_index
);
}
// dbg!(&path);
let res = self.get(path).await?;

if res.status() == 404 {
return Err(salvo::http::StatusError::not_found().into());
Expand Down
17 changes: 4 additions & 13 deletions src/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,6 @@ pub async fn get_hubs_promoted(
}
}


let upstream_res = plex_client.request(req).await?;
match upstream_res.status() {
reqwest::StatusCode::OK => (),
Expand All @@ -267,17 +266,6 @@ pub async fn get_hubs_promoted(

let mut container: MediaContainerWrapper<MediaContainer> =
from_reqwest_response(upstream_res).await?;
// match from_reqwest_response(upstream_res).await
// if upstream_res.status() == 500
// let mut container: MediaContainerWrapper<MediaContainer> =
// match from_reqwest_response(upstream_res).await {
// Ok(r) => r,
// Err(error) => {
// tracing::error!(error = ?error, uri = ?req.uri(), "Failed to get plex response");
// res.status_code(StatusCode::INTERNAL_SERVER_ERROR);
// return Ok(())
// }
// };
container.content_type = content_type;

TransformBuilder::new(plex_client, params.clone())
Expand All @@ -290,6 +278,7 @@ pub async fn get_hubs_promoted(
.with_transform(HubKeyTransform)
.apply_to(&mut container)
.await;

res.render(container);
Ok(())
}
Expand Down Expand Up @@ -348,7 +337,7 @@ pub async fn get_collections_children(
req: &mut Request,
_depot: &mut Depot,
res: &mut Response,
) {
) -> Result<(), anyhow::Error> {
let params: PlexParams = req.extract().await.unwrap();
let collection_ids = req.param::<String>("ids").unwrap();
let collection_ids: Vec<u32> = collection_ids
Expand Down Expand Up @@ -391,7 +380,9 @@ pub async fn get_collections_children(
.with_transform(UserStateTransform)
.apply_to(&mut container)
.await;

res.render(container); // TODO: FIx XML
Ok(())
}

#[handler]
Expand Down
173 changes: 135 additions & 38 deletions src/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use futures_util::{
stream::{FuturesOrdered, FuturesUnordered},
StreamExt,
};
use std::collections::HashMap;
use itertools::Itertools;
use lazy_static::__Deref;
use std::sync::Arc;
Expand Down Expand Up @@ -402,29 +403,143 @@ impl Transform for LibraryMixTransform {
) {
let config: Config = Config::figment().extract().unwrap();
let mut children: Vec<MetaData> = vec![];
let mut total_size: i32 = 0;
let collection_ids_len = self.collection_ids.clone().len() as i32;
let collection_offset =
(self.offset as f32 / collection_ids_len as f32).ceil() as i32;
let collection_limit =
(self.limit as f32 / collection_ids_len as f32).ceil() as i32;
let mut total_size_children_unfiltered: i32 = 0;
let mut total_size = 0;
let mut collections_total_sizes: HashMap<u32, i32> = HashMap::with_capacity(collection_ids_len as usize);

for id in self.collection_ids.clone() {
let mut c = plex_client.clone().get_cached(
plex_client.load_collection_children_recursive(
id,
self.offset,
collection_limit,
collection_limit,
),
format!(
"collection:{}:{}:{}",
id, self.offset, collection_limit
),
).await.unwrap();

total_size += c.media_container.total_size.unwrap();
// We need this for the total count. In theory it shouldnt have mattered.
// But IOS doesnt listen to changes in total size. Picks it from the first request.
// Which results in a loop
if !config.include_watched {
let mut collection = plex_client
.clone()
.get_cached(
plex_client.get_collection(id as i32),
format!("get_collection:{}", id),
)
.await
.unwrap();

let collection_metadata =
collection.media_container.children_mut()[0].clone();
let library_items = plex_client
.clone()
.get_cached(
plex_client.get_collection_total_size_unwatched(
collection
.media_container
.library_section_id
.unwrap() as i32,
collection_metadata.index.unwrap() as i32,
collection_metadata.subtype.unwrap(),
),
format!(
"get_collection_total_size_unwatched:{}:{}",
collection
.media_container
.library_section_id
.unwrap() as i32,
id
),
)
.await
.unwrap();
collections_total_sizes.insert(id, library_items.media_container.total_size.unwrap());
total_size += library_items.media_container.total_size.unwrap();
} else {
let c = plex_client
.clone()
.get_cached(
plex_client.get_collection_children(
id,
Some(0),
Some(0),
),
format!(
"get_collection_children:{}:{}:{}",
id, 0, 0
),
)
.await
.unwrap();
collections_total_sizes.insert(id, c.media_container.total_size.unwrap());
total_size += c.media_container.total_size.unwrap();
}
}

for id in self.collection_ids.clone() {
let percentage = {
let mut b = 0;
for s in collections_total_sizes.clone().into_iter() {
b += s.1;
}
let size = collections_total_sizes.get(&id);
// b / size
// dbg!(&b);
// dbg!(&size);
let x = ((size.unwrap() * 100 / b * 100) / 100) as f32;
x / 100.00
};
// dbg!(percentage);
let mut c = plex_client
.clone()
.get_cached(
plex_client.load_collection_children_recursive(
id,
(self.offset as f32 * percentage).ceil() as i32,
(self.limit as f32 * percentage).ceil() as i32,
(self.limit as f32 * percentage).ceil() as i32,
),
format!(
"load_collection_children_recursive:{}:{}:{}",
id, self.offset, self.limit
),
)
.await
.unwrap();

// if !config.include_watched {
// // We need this for the total count. In theory it shouldnt have mattered.
// // But IOS doesnt listen to changes in total size. Picks it from the first request.
// // Which results in a loop
// let mut collection = plex_client
// .clone()
// .get_cached(
// plex_client.get_collection(id as i32),
// format!("collection:{}", id),
// )
// .await
// .unwrap();

// let collection_metadata =
// collection.media_container.children_mut()[0].clone();
// let library_items = plex_client
// .clone()
// .get_cached(
// plex_client.get_collection_total_size(
// collection
// .media_container
// .library_section_id
// .unwrap() as i32,
// collection_metadata.index.unwrap() as i32,
// collection_metadata.subtype.unwrap(),
// ),
// format!(
// "library_items:{}:{}",
// collection
// .media_container
// .library_section_id
// .unwrap() as i32,
// id
// ),
// )
// .await
// .unwrap();
// total_size += library_items.media_container.total_size.unwrap();
// } else {
// total_size += c.media_container.total_size.unwrap();
// }

match children.is_empty() {
false => {
Expand All @@ -436,28 +551,10 @@ impl Transform for LibraryMixTransform {
true => children.append(&mut c.media_container.children()),
}
}
//dbg!(total_size);
let children_count = children.len() as i32;

// we dont know the total size because we filter stuff. We might already be at the end of the line
if children_count < self.limit {
// dbg!("yup");
// dbg!(children_count);
// dbg!(total_size);
// dbg!("------");
// total_size = self.limit + children_count;
total_size = self.offset + children_count;
//total_size = self.offset + children_count;
//dbg!(total_size);
}
// dbg!(self.limit);

//item.children_mut().truncate(self.limit as usize);
item.total_size = Some(total_size);
// always metadata library
children.truncate(self.limit as usize);
item.metadata = children;
item.size = Some(self.limit);
}
}

Expand Down

0 comments on commit 70a990d

Please sign in to comment.