Skip to content

Commit

Permalink
show progress indicator
Browse files Browse the repository at this point in the history
  • Loading branch information
rot1024 committed Oct 11, 2021
1 parent 4b06166 commit dd1d981
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 37 deletions.
28 changes: 24 additions & 4 deletions src/nicodo/channel.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::{Result, Session};
use lazy_static::lazy_static;
use regex::Regex;
use scraper::{Html, Selector};

pub struct Video {
Expand Down Expand Up @@ -30,14 +31,33 @@ impl Session {
.select(&SELECTOR)
.filter_map(|n| {
if let (Some(id), Some(title)) = (n.value().attr("href"), n.value().attr("title")) {
Some(Video {
id: id.replace("https://www.nicovideo.jp/watch/", ""),
title: title.to_string(),
})
if !video_rejected(title) {
Some(Video {
id: id.replace("https://www.nicovideo.jp/watch/", ""),
title: title.to_string(),
})
} else {
None
}
} else {
None
}
})
.collect::<Vec<_>>())
}
}

fn video_rejected(title: &str) -> bool {
lazy_static! {
static ref REG: Regex = Regex::new("「.*」").unwrap();
}
REG.replace(title, "").contains("PV")
}

#[test]
fn test_video_rejected() {
assert!(!video_rejected("normal"));
assert!(!video_rejected("第1話 「PVを撮影した」"));
assert!(video_rejected("hogehoge PV"));
assert!(video_rejected("hogehoge PV 第2弾"));
}
41 changes: 28 additions & 13 deletions src/nicodo/comment.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use super::{
comment_body::{get_body, Options},
Error, Info, Result, Session, Wayback,
Info, Result, Session, Wayback,
};
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::{collections::HashMap, time::Duration};

const API_ENDPOINT: &'static str = "https://nvcomment.nicovideo.jp/legacy/api.json";

Expand Down Expand Up @@ -38,8 +38,16 @@ pub struct Comment {
pub mail: Option<String>,
}

#[derive(Debug)]
pub struct Context<'a> {
pub wayback: Option<NaiveDateTime>,
pub total: usize,
pub progress: usize,
pub comments: &'a [Comment],
}

impl Session {
pub async fn get_comments<F: Fn(Option<NaiveDateTime>)>(
pub async fn get_comments<F: Fn(Context)>(
&self,
info: &Info,
wayback: &Wayback,
Expand All @@ -50,17 +58,18 @@ impl Session {

let mut comments: HashMap<usize, Comment> = HashMap::new();

for wayback in wayback.iter() {
on_progress(wayback);
let wayback_iter = wayback.iter();
let wayback_len = wayback_iter.len();

for (index, current) in wayback_iter.enumerate() {
let (body, _counter_rs, _counter_ps) = get_body(Options {
info,
threadkey: &threadkey,
waybackkey: &waybackkey,
force_184: &force_184,
counter_rs: 0,
counter_ps: 0,
wayback,
wayback: current,
});

let res = reqwest::Client::new()
Expand All @@ -74,7 +83,8 @@ impl Session {
.json::<Vec<Element>>()
.await?;

res.into_iter()
let current_comments = res
.into_iter()
.filter_map(|e| e.chat)
.filter(|c| c.content.is_some())
.map(|c| Comment {
Expand All @@ -86,13 +96,18 @@ impl Session {
content: c.content.unwrap(),
mail: c.mail,
})
.for_each(|c| {
comments.insert(c.no, c);
})
}
.collect::<Vec<_>>();

if comments.len() == 0 {
return Err(Error::NoComments);
on_progress(Context {
wayback: current,
total: wayback_len,
progress: index,
comments: &current_comments,
});

current_comments.into_iter().for_each(|c| {
comments.insert(c.no, c);
});
}

let mut comments: Vec<_> = comments.into_iter().map(|(_, c)| c).collect();
Expand Down
54 changes: 54 additions & 0 deletions src/nicodo/comment_wayback.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::convert::TryInto;

use chrono::{Duration, NaiveDateTime};

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -92,6 +94,25 @@ impl Iterator for WaybackIter {
}
}

impl ExactSizeIterator for WaybackIter {
fn len(&self) -> usize {
match self.wayback {
Wayback::Latest => 1,
Wayback::DateTime(_) => 1,
Wayback::Period {
start,
end,
interval,
include_latest,
} => ((end - start).num_milliseconds() / interval.num_milliseconds()
+ 1
+ if include_latest { 1 } else { 0 })
.try_into()
.unwrap(),
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -209,4 +230,37 @@ mod tests {
.into_iter();
assert_eq!(iter.next(), None);
}

#[test]
fn test_len() {
assert_eq!(Wayback::Latest.into_iter().len(), 1);
assert_eq!(
Wayback::DateTime(NaiveDateTime::from_str("2019-11-03T00:00:00").unwrap())
.into_iter()
.len(),
1
);
assert_eq!(
Wayback::Period {
start: NaiveDateTime::from_str("2019-11-03T00:00:00").unwrap(),
end: NaiveDateTime::from_str("2019-11-10T00:00:00").unwrap(),
interval: Duration::days(1),
include_latest: false,
}
.into_iter()
.len(),
8
);
assert_eq!(
Wayback::Period {
start: NaiveDateTime::from_str("2019-11-03T00:00:00").unwrap(),
end: NaiveDateTime::from_str("2019-11-10T00:00:00").unwrap(),
interval: Duration::days(1),
include_latest: true,
}
.into_iter()
.len(),
9
);
}
}
2 changes: 0 additions & 2 deletions src/nicodo/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ pub enum Error {
NotAuthorized,
#[error("serialization error")]
Serialization,
#[error("no comments found")]
NoComments,
}

impl From<reqwest::Error> for Error {
Expand Down
62 changes: 44 additions & 18 deletions src/process.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::id::Id;
use crate::{datetime, error};
use chrono::NaiveDateTime;
use std::{borrow::Cow, path::Path, str::FromStr};
use std::{borrow::Cow, convert::TryInto, path::Path, str::FromStr};
use tokio::task::spawn_blocking;

const DISPLAY_DATETIME_FORMAT: &str = "%Y-%m-%d %H:%M:%S";
Expand Down Expand Up @@ -133,28 +133,48 @@ async fn process_video(id: &str, opts: &Options) -> error::Result<()> {
};
}

let progress = if !opts.quiet {
Some(
indicatif::ProgressBar::new(0).with_style(
indicatif::ProgressStyle::default_bar()
.template("{spinner} {wide_bar} {pos}/{len} {msg}"),
),
)
} else {
None
};
let comments = opts
.session
.get_comments(&info, &wayback, |p| {
if opts.quiet {
return;
}
if let Some(dt) = p {
eprintln!(
"Fetching comments at {}",
dt.format(DISPLAY_DATETIME_FORMAT)
);
} else {
eprintln!("Fetching latest comments");
.get_comments(&info, &wayback, |ctx| {
if let Some(p) = progress.as_ref() {
if let Some(dt) = ctx.wayback {
p.set_length(ctx.total.try_into().unwrap());
p.set_position((ctx.progress + 1).try_into().unwrap());
p.set_message(format!(
"{} ({})",
dt.format(DISPLAY_DATETIME_FORMAT),
ctx.comments.len()
));
} else {
p.set_message(format!("latest ({})", ctx.comments.len()));
}
}
})
.await?;

if !opts.quiet {
eprintln!("Writing comments to the file");
if let Some(p) = progress.as_ref() {
p.finish_and_clear();
}

let comments_len = comments.len();
if comments_len == 0 {
if !opts.quiet {
eprintln!("No comments fetched");
}
return Ok(());
}

let dest = Path::new(&opts.output).join(format!(
let filename = format!(
"{}{}.{}",
info.video.title,
match wayback {
Expand All @@ -175,8 +195,8 @@ async fn process_video(id: &str, opts: &Options) -> error::Result<()> {
_ => "".to_string(),
},
opts.format.ext(),
));

);
let dest = Path::new(&opts.output).join(&filename);
let format = opts.format.clone();

spawn_blocking(move || -> crate::error::Result<()> {
Expand All @@ -193,5 +213,11 @@ async fn process_video(id: &str, opts: &Options) -> error::Result<()> {
Ok(())
})
.await
.map_err(|e| error::Error::Error(Box::new(e)))?
.map_err(|e| error::Error::Error(Box::new(e)))??;

if !opts.quiet {
eprintln!("Writing {} comments to \"{}\"", comments_len, filename);
}

Ok(())
}

0 comments on commit dd1d981

Please sign in to comment.