Skip to content

Commit

Permalink
[XDDCC]: fix 列出回放地址但其实是直播地址的错误。
Browse files Browse the repository at this point in the history
添加相关的几个选项。
  • Loading branch information
learturely committed Jul 13, 2024
1 parent ac27fdf commit 343591e
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 33 deletions.
11 changes: 7 additions & 4 deletions src/cli/arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,21 +127,24 @@ pub enum MainCommand {
/// 获取特定账号下节课的直播信息,格式为以半角逗号隔开的字符串。
#[arg(short, long)]
accounts: Option<String>,
/// 覆盖默认行为至获取当前课的直播信息。
#[arg(short, long)]
this: bool,
/// 通过 `device_code` 获取直播信息。
#[arg(short, long)]
device_code: Option<String>,
/// 获取某节课的回放信息,格式为`周数/节数`
/// 获取回放信息,参数为 `live_id`, 默认获取整门课的
#[arg(short, long)]
id: Option<i64>,
/// 获取某门课中每节课的 `live_id`.
#[arg(short, long)]
just_id: bool,
/// 导出文件路径。可选提供。
#[arg(short, long)]
output: Option<PathBuf>,
/// 列出所有设备码。
#[arg(short, long)]
list: bool,
/// 获取直播信息时覆盖默认行为至获取当前课的直播信息,获取回放信息时指定只获取一节课的回放信息。
#[arg(short, long)]
this: bool,
// /// 网页播放器地址。
// #[arg(short, long)]
// web: bool,
Expand Down
107 changes: 107 additions & 0 deletions src/xddcc/lesson.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use std::{
collections::HashMap,
sync::{Arc, Mutex},
};

use cxsign::user::Session;
use indicatif::MultiProgress;
use serde::{Deserialize, Serialize};

use super::tools::{
arc_into_inner_error_handler, json_parsing_error_handler, mutex_into_inner_error_handler,
prog_init_error_handler, VideoPath,
};

#[derive(Deserialize, Serialize, Clone, Debug)]
struct Time_ {
time: i64,
}
#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct Lesson {
#[serde(rename = "startTime")]
start_time: Time_,
id: i64,
}

impl Lesson {
pub fn get_start_time(&self) -> i64 {
self.start_time.time
}
pub fn get_live_id(&self) -> i64 {
self.id
}
pub fn get_recording_url(
session: &Session,
live_id: i64,
) -> Result<VideoPath, Box<ureq::Error>> {
crate::xddcc::tools::get_recording_live_video_path(session, live_id)
}
pub fn get_all_lessons(session: &Session, live_id: i64) -> Result<Vec<i64>, Box<ureq::Error>> {
let mut lessons: Vec<Lesson> =
crate::xddcc::protocol::list_single_course(&session, live_id)?
.into_json()
.unwrap_or_else(json_parsing_error_handler);
lessons.sort_by_key(|l| l.get_start_time());
Ok(lessons.into_iter().map(|l| l.get_live_id()).collect())
}
pub fn get_recording_lives(
session: &Session,
live_id: i64,
multi: &MultiProgress,
) -> Result<HashMap<i64, VideoPath>, Box<ureq::Error>> {
let lessons: Vec<Lesson> = crate::xddcc::protocol::list_single_course(&session, live_id)?
.into_json()
.unwrap_or_else(json_parsing_error_handler);
let total = lessons.len();
let thread_count = total / 64;
let rest_count = total % 64;
let sty = indicatif::ProgressStyle::with_template(
"获取回放地址:[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}",
)
.unwrap_or_else(prog_init_error_handler);
let pb = multi.add(indicatif::ProgressBar::new(total as u64));
pb.set_style(sty);
let pb = Arc::new(Mutex::new(pb));
let pathes = Arc::new(Mutex::new(HashMap::new()));
let mut handles = Vec::new();
for block in 0..64 {
let ref_ = if block < rest_count {
((thread_count + 1) * block)..((thread_count + 1) * (block + 1))
} else {
(thread_count * block + rest_count)..(thread_count * (block + 1) + rest_count)
};
let session = (*session).clone();
let pathes = Arc::clone(&pathes);
let pb = Arc::clone(&pb);
let mut lessons_ = vec![];
for lesson in &lessons[ref_] {
lessons_.push(lesson.clone())
}
let handle = std::thread::spawn(move || {
for lesson in lessons_ {
if let Some(path) =
Lesson::get_recording_url(&session, lesson.get_live_id()).ok()
{
pathes.lock().unwrap().insert(lesson.get_start_time(), path);
}
pb.lock().unwrap().inc(1);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
let pathes = Arc::into_inner(pathes)
.unwrap_or_else(arc_into_inner_error_handler)
.into_inner()
.unwrap_or_else(mutex_into_inner_error_handler);
let pb = Arc::into_inner(pb)
.unwrap_or_else(arc_into_inner_error_handler)
.into_inner()
.unwrap_or_else(mutex_into_inner_error_handler);
pb.finish_with_message("获取回放地址完成。");
multi.remove(&pb);
Ok(pathes)
}
}
2 changes: 1 addition & 1 deletion src/xddcc/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use ureq::{Agent, Response};

static GET_VIEW_URL_HLS: &str = "http://newesxidian.chaoxing.com/live/getViewUrlHls";
pub fn get_view_url_hls(agent: &Agent, live_id: i64) -> Result<Response, Box<ureq::Error>> {
let url = format!("{GET_VIEW_URL_HLS}?liveId={live_id}&status=1&jie=&isStudent=");
let url = format!("{GET_VIEW_URL_HLS}?liveId={live_id}&status=2&jie=&isStudent=");
Ok(agent.get(&url).call()?)
}
static LIST_STUDENT_COURSE_LIVE_PAGE: &str =
Expand Down
29 changes: 1 addition & 28 deletions src/xddcc/room.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ impl Room {
pub fn get_live_video_path(&self, session: &Session) -> Result<VideoPath, Box<ureq::Error>> {
crate::xddcc::tools::get_live_video_path(session, &self.device_code)
}
pub fn get_recording_url(&self, session: &Session) -> Result<VideoPath, Box<ureq::Error>> {
crate::xddcc::tools::get_recording_live_video_path(session, self.id)
}

// pub fn get_live_video_path(&self, session: &Session) -> VideoPath {
// crate::tools::get_live_video_path(session, &self.device_code)
// }
Expand Down Expand Up @@ -70,31 +68,6 @@ impl Room {
.into_inner()
.unwrap_or_else(mutex_into_inner_error_handler)
}
pub fn get_recording_lives(
session: &Session,
live_id: i64,
multi: &MultiProgress,
) -> Result<HashMap<i64, VideoPath>, Box<ureq::Error>> {
let rooms: Vec<Room> = crate::xddcc::protocol::list_single_course(&session, live_id)?
.into_json()
.unwrap_or_else(json_parsing_error_handler);
let total = rooms.len();
let sty = indicatif::ProgressStyle::with_template(
"获取回放地址:[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}",
)
.unwrap_or_else(prog_init_error_handler);
let pb = multi.add(indicatif::ProgressBar::new(total as u64));
pb.set_style(sty);
let pathes = rooms.into_iter().filter_map(|room| {
let path = room.get_live_video_path(session).ok().map(|p| (room.id, p));
pb.inc(1);
path
});
let pathes = pathes.collect();
pb.finish_with_message("获取回放地址完成。");
multi.remove(&pb);
Ok(pathes)
}
pub fn get_all_live_id(
sessions: &[&Session],
id_map: Arc<Mutex<HashMap<String, i64>>>,
Expand Down

0 comments on commit 343591e

Please sign in to comment.