mirror of
https://github.com/amtoaer/bili-sync.git
synced 2026-08-28 03:28:05 +08:00
chore: 修复新的 clippy warnings (#467)
This commit is contained in:
@@ -56,11 +56,12 @@ impl VideoSource for collection::Model {
|
|||||||
latest_row_at: &chrono::DateTime<Utc>,
|
latest_row_at: &chrono::DateTime<Utc>,
|
||||||
) -> Option<VideoInfo> {
|
) -> Option<VideoInfo> {
|
||||||
// 由于 collection 的视频无固定时间顺序,should_take 无法提前中断拉取,因此 should_filter 环节需要进行额外过滤
|
// 由于 collection 的视频无固定时间顺序,should_take 无法提前中断拉取,因此 should_filter 环节需要进行额外过滤
|
||||||
if let Ok(video_info) = video_info {
|
if let Ok(video_info) = video_info
|
||||||
if video_info.release_datetime() > latest_row_at {
|
&& video_info.release_datetime() > latest_row_at
|
||||||
return Some(video_info);
|
{
|
||||||
}
|
return Some(video_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,11 +55,11 @@ ORDER BY
|
|||||||
))
|
))
|
||||||
.all(&db),
|
.all(&db),
|
||||||
)?;
|
)?;
|
||||||
return Ok(ApiResponse::ok(DashBoardResponse {
|
Ok(ApiResponse::ok(DashBoardResponse {
|
||||||
enabled_favorites,
|
enabled_favorites,
|
||||||
enabled_collections,
|
enabled_collections,
|
||||||
enabled_submissions,
|
enabled_submissions,
|
||||||
enable_watch_later: enabled_watch_later > 0,
|
enable_watch_later: enabled_watch_later > 0,
|
||||||
videos_by_day,
|
videos_by_day,
|
||||||
}));
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,17 +43,16 @@ pub async fn auth(mut headers: HeaderMap, request: Request, next: Next) -> Resul
|
|||||||
{
|
{
|
||||||
return Ok(next.run(request).await);
|
return Ok(next.run(request).await);
|
||||||
}
|
}
|
||||||
if let Some(protocol) = headers.remove("Sec-WebSocket-Protocol") {
|
if let Some(protocol) = headers.remove("Sec-WebSocket-Protocol")
|
||||||
if protocol
|
&& protocol
|
||||||
.to_str()
|
.to_str()
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|s| BASE64_URL_SAFE_NO_PAD.decode(s).ok())
|
.and_then(|s| BASE64_URL_SAFE_NO_PAD.decode(s).ok())
|
||||||
.is_some_and(|s| s == token.as_bytes())
|
.is_some_and(|s| s == token.as_bytes())
|
||||||
{
|
{
|
||||||
let mut resp = next.run(request).await;
|
let mut resp = next.run(request).await;
|
||||||
resp.headers_mut().insert("Sec-WebSocket-Protocol", protocol);
|
resp.headers_mut().insert("Sec-WebSocket-Protocol", protocol);
|
||||||
return Ok(resp);
|
return Ok(resp);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(ApiResponse::<()>::unauthorized("auth token does not match").into_response())
|
Ok(ApiResponse::<()>::unauthorized("auth token does not match").into_response())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ impl WebSocketHandler {
|
|||||||
let rx = log_writer_clone.sender.subscribe();
|
let rx = log_writer_clone.sender.subscribe();
|
||||||
let log_stream = futures::stream::iter(history_logs.into_iter())
|
let log_stream = futures::stream::iter(history_logs.into_iter())
|
||||||
.chain(BroadcastStream::new(rx).filter_map(async |msg| msg.ok()))
|
.chain(BroadcastStream::new(rx).filter_map(async |msg| msg.ok()))
|
||||||
.map(|msg| ServerEvent::Logs(msg));
|
.map(ServerEvent::Logs);
|
||||||
pin!(log_stream);
|
pin!(log_stream);
|
||||||
while let Some(event) = log_stream.next().await {
|
while let Some(event) = log_stream.next().await {
|
||||||
if let Err(e) = tx_clone.send(event).await {
|
if let Err(e) = tx_clone.send(event).await {
|
||||||
@@ -133,8 +133,8 @@ impl WebSocketHandler {
|
|||||||
if task_handle.as_ref().is_none_or(|h: &JoinHandle<()>| h.is_finished()) {
|
if task_handle.as_ref().is_none_or(|h: &JoinHandle<()>| h.is_finished()) {
|
||||||
let tx_clone = tx.clone();
|
let tx_clone = tx.clone();
|
||||||
task_handle = Some(tokio::spawn(async move {
|
task_handle = Some(tokio::spawn(async move {
|
||||||
let mut stream = WatchStream::new(TASK_STATUS_NOTIFIER.subscribe())
|
let mut stream =
|
||||||
.map(|status| ServerEvent::Tasks(status));
|
WatchStream::new(TASK_STATUS_NOTIFIER.subscribe()).map(ServerEvent::Tasks);
|
||||||
while let Some(event) = stream.next().await {
|
while let Some(event) = stream.next().await {
|
||||||
if let Err(e) = tx_clone.send(event).await {
|
if let Err(e) = tx_clone.send(event).await {
|
||||||
error!("Failed to send task status: {:?}", e);
|
error!("Failed to send task status: {:?}", e);
|
||||||
@@ -179,7 +179,7 @@ impl WebSocketHandler {
|
|||||||
// 添加订阅者
|
// 添加订阅者
|
||||||
async fn add_sysinfo_subscriber(&self, uuid: Uuid, sender: tokio::sync::mpsc::Sender<ServerEvent>) {
|
async fn add_sysinfo_subscriber(&self, uuid: Uuid, sender: tokio::sync::mpsc::Sender<ServerEvent>) {
|
||||||
self.sysinfo_subscribers.insert(uuid, sender);
|
self.sysinfo_subscribers.insert(uuid, sender);
|
||||||
if self.sysinfo_subscribers.len() > 0
|
if !self.sysinfo_subscribers.is_empty()
|
||||||
&& self
|
&& self
|
||||||
.sysinfo_handles
|
.sysinfo_handles
|
||||||
.read()
|
.read()
|
||||||
@@ -235,10 +235,10 @@ impl WebSocketHandler {
|
|||||||
|
|
||||||
async fn remove_sysinfo_subscriber(&self, uuid: Uuid) {
|
async fn remove_sysinfo_subscriber(&self, uuid: Uuid) {
|
||||||
self.sysinfo_subscribers.remove(&uuid);
|
self.sysinfo_subscribers.remove(&uuid);
|
||||||
if self.sysinfo_subscribers.is_empty() {
|
if self.sysinfo_subscribers.is_empty()
|
||||||
if let Some(handle) = self.sysinfo_handles.write().take() {
|
&& let Some(handle) = self.sysinfo_handles.write().take()
|
||||||
handle.abort();
|
{
|
||||||
}
|
handle.abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -263,39 +263,37 @@ impl PageAnalyzer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !filter_option.no_hires {
|
if !filter_option.no_hires
|
||||||
if let Some(flac) = self.info.pointer_mut("/dash/flac/audio") {
|
&& let Some(flac) = self.info.pointer_mut("/dash/flac/audio")
|
||||||
let (Some(url), Some(quality)) = (flac["baseUrl"].as_str(), flac["id"].as_u64()) else {
|
{
|
||||||
bail!("invalid flac stream");
|
let (Some(url), Some(quality)) = (flac["baseUrl"].as_str(), flac["id"].as_u64()) else {
|
||||||
};
|
bail!("invalid flac stream");
|
||||||
let quality = AudioQuality::from_repr(quality as usize).context("invalid flac stream quality")?;
|
};
|
||||||
if quality >= filter_option.audio_min_quality && quality <= filter_option.audio_max_quality {
|
let quality = AudioQuality::from_repr(quality as usize).context("invalid flac stream quality")?;
|
||||||
streams.push(Stream::DashAudio {
|
if quality >= filter_option.audio_min_quality && quality <= filter_option.audio_max_quality {
|
||||||
url: url.to_string(),
|
streams.push(Stream::DashAudio {
|
||||||
backup_url: serde_json::from_value(flac["backupUrl"].take()).unwrap_or_default(),
|
url: url.to_string(),
|
||||||
quality,
|
backup_url: serde_json::from_value(flac["backupUrl"].take()).unwrap_or_default(),
|
||||||
});
|
quality,
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !filter_option.no_dolby_audio {
|
if !filter_option.no_dolby_audio
|
||||||
if let Some(dolby_audio) = self
|
&& let Some(dolby_audio) = self
|
||||||
.info
|
.info
|
||||||
.pointer_mut("/dash/dolby/audio/0")
|
.pointer_mut("/dash/dolby/audio/0")
|
||||||
.and_then(|a| a.as_object_mut())
|
.and_then(|a| a.as_object_mut())
|
||||||
{
|
{
|
||||||
let (Some(url), Some(quality)) = (dolby_audio["baseUrl"].as_str(), dolby_audio["id"].as_u64()) else {
|
let (Some(url), Some(quality)) = (dolby_audio["baseUrl"].as_str(), dolby_audio["id"].as_u64()) else {
|
||||||
bail!("invalid dolby audio stream");
|
bail!("invalid dolby audio stream");
|
||||||
};
|
};
|
||||||
let quality =
|
let quality = AudioQuality::from_repr(quality as usize).context("invalid dolby audio stream quality")?;
|
||||||
AudioQuality::from_repr(quality as usize).context("invalid dolby audio stream quality")?;
|
if quality >= filter_option.audio_min_quality && quality <= filter_option.audio_max_quality {
|
||||||
if quality >= filter_option.audio_min_quality && quality <= filter_option.audio_max_quality {
|
streams.push(Stream::DashAudio {
|
||||||
streams.push(Stream::DashAudio {
|
url: url.to_string(),
|
||||||
url: url.to_string(),
|
backup_url: serde_json::from_value(dolby_audio["backupUrl"].take()).unwrap_or_default(),
|
||||||
backup_url: serde_json::from_value(dolby_audio["backupUrl"].take()).unwrap_or_default(),
|
quality,
|
||||||
quality,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(streams)
|
Ok(streams)
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ impl Downloader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.with_context(|| format!("failed to download file"))
|
res.context("failed to download file")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn merge(&self, video_path: &Path, audio_path: &Path, output_path: &Path) -> Result<()> {
|
pub async fn merge(&self, video_path: &Path, audio_path: &Path, output_path: &Path) -> Result<()> {
|
||||||
|
|||||||
@@ -42,10 +42,10 @@ impl From<Result<ExecutionStatus>> for ExecutionStatus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 未包裹的 reqwest::Error
|
// 未包裹的 reqwest::Error
|
||||||
if let Some(error) = cause.downcast_ref::<reqwest::Error>() {
|
if let Some(error) = cause.downcast_ref::<reqwest::Error>()
|
||||||
if is_ignored_reqwest_error(error) {
|
&& is_ignored_reqwest_error(error)
|
||||||
return ExecutionStatus::Ignored(err);
|
{
|
||||||
}
|
return ExecutionStatus::Ignored(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExecutionStatus::Failed(err)
|
ExecutionStatus::Failed(err)
|
||||||
|
|||||||
@@ -53,13 +53,13 @@ async fn frontend_files(request: Request) -> impl IntoResponse {
|
|||||||
(header::CACHE_CONTROL, "no-cache"),
|
(header::CACHE_CONTROL, "no-cache"),
|
||||||
(header::ETAG, &content.hash()),
|
(header::ETAG, &content.hash()),
|
||||||
];
|
];
|
||||||
if let Some(if_none_match) = request.headers().get(header::IF_NONE_MATCH) {
|
if let Some(if_none_match) = request.headers().get(header::IF_NONE_MATCH)
|
||||||
if let Ok(client_etag) = if_none_match.to_str() {
|
&& let Ok(client_etag) = if_none_match.to_str()
|
||||||
if client_etag == content.hash() {
|
&& client_etag == content.hash()
|
||||||
return (StatusCode::NOT_MODIFIED, default_headers).into_response();
|
{
|
||||||
}
|
return (StatusCode::NOT_MODIFIED, default_headers).into_response();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if request.method() == axum::http::Method::HEAD {
|
if request.method() == axum::http::Method::HEAD {
|
||||||
return (StatusCode::OK, default_headers).into_response();
|
return (StatusCode::OK, default_headers).into_response();
|
||||||
}
|
}
|
||||||
@@ -74,20 +74,20 @@ async fn frontend_files(request: Request) -> impl IntoResponse {
|
|||||||
.map(|s| s.split(',').map(str::trim).collect::<HashSet<_>>())
|
.map(|s| s.split(',').map(str::trim).collect::<HashSet<_>>())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
for (encoding, data) in [("br", content.data_br()), ("gzip", content.data_gzip())] {
|
for (encoding, data) in [("br", content.data_br()), ("gzip", content.data_gzip())] {
|
||||||
if accepted_encodings.contains(encoding) {
|
if accepted_encodings.contains(encoding)
|
||||||
if let Some(data) = data {
|
&& let Some(data) = data
|
||||||
return (
|
{
|
||||||
StatusCode::OK,
|
return (
|
||||||
[
|
StatusCode::OK,
|
||||||
(header::CONTENT_TYPE, content_type),
|
[
|
||||||
(header::CACHE_CONTROL, "no-cache"),
|
(header::CONTENT_TYPE, content_type),
|
||||||
(header::ETAG, &content.hash()),
|
(header::CACHE_CONTROL, "no-cache"),
|
||||||
(header::CONTENT_ENCODING, encoding),
|
(header::ETAG, &content.hash()),
|
||||||
],
|
(header::CONTENT_ENCODING, encoding),
|
||||||
data,
|
],
|
||||||
)
|
data,
|
||||||
.into_response();
|
)
|
||||||
}
|
.into_response();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -52,14 +52,14 @@ impl FieldEvaluatable for RuleTarget {
|
|||||||
/// 修改模型后进行评估,此时能访问的是未保存的 activeModel,就地使用 activeModel 评估
|
/// 修改模型后进行评估,此时能访问的是未保存的 activeModel,就地使用 activeModel 评估
|
||||||
fn evaluate(&self, video: &video::ActiveModel, pages: &[page::ActiveModel]) -> bool {
|
fn evaluate(&self, video: &video::ActiveModel, pages: &[page::ActiveModel]) -> bool {
|
||||||
match self {
|
match self {
|
||||||
RuleTarget::Title(cond) => video.name.try_as_ref().is_some_and(|title| cond.evaluate(&title)),
|
RuleTarget::Title(cond) => video.name.try_as_ref().is_some_and(|title| cond.evaluate(title)),
|
||||||
// 目前的所有条件都是分别针对全体标签进行 any 评估的,例如 Prefix("a") && Suffix("b") 意味着 any(tag.Prefix("a")) && any(tag.Suffix("b")) 而非 any(tag.Prefix("a") && tag.Suffix("b"))
|
// 目前的所有条件都是分别针对全体标签进行 any 评估的,例如 Prefix("a") && Suffix("b") 意味着 any(tag.Prefix("a")) && any(tag.Suffix("b")) 而非 any(tag.Prefix("a") && tag.Suffix("b"))
|
||||||
// 这可能不满足用户预期,但应该问题不大,如果真有很多人用复杂标签筛选再单独改
|
// 这可能不满足用户预期,但应该问题不大,如果真有很多人用复杂标签筛选再单独改
|
||||||
RuleTarget::Tags(cond) => video
|
RuleTarget::Tags(cond) => video
|
||||||
.tags
|
.tags
|
||||||
.try_as_ref()
|
.try_as_ref()
|
||||||
.and_then(|t| t.as_ref())
|
.and_then(|t| t.as_ref())
|
||||||
.is_some_and(|tags| tags.0.iter().any(|tag| cond.evaluate(&tag))),
|
.is_some_and(|tags| tags.0.iter().any(|tag| cond.evaluate(tag))),
|
||||||
RuleTarget::FavTime(cond) => video
|
RuleTarget::FavTime(cond) => video
|
||||||
.favtime
|
.favtime
|
||||||
.try_as_ref()
|
.try_as_ref()
|
||||||
@@ -84,7 +84,7 @@ impl FieldEvaluatable for RuleTarget {
|
|||||||
RuleTarget::Tags(cond) => video
|
RuleTarget::Tags(cond) => video
|
||||||
.tags
|
.tags
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.is_some_and(|tags| tags.0.iter().any(|tag| cond.evaluate(&tag))),
|
.is_some_and(|tags| tags.0.iter().any(|tag| cond.evaluate(tag))),
|
||||||
RuleTarget::FavTime(cond) => cond.evaluate(&video.favtime.and_utc().with_timezone(&Local).naive_local()),
|
RuleTarget::FavTime(cond) => cond.evaluate(&video.favtime.and_utc().with_timezone(&Local).naive_local()),
|
||||||
RuleTarget::PubTime(cond) => cond.evaluate(&video.pubtime.and_utc().with_timezone(&Local).naive_local()),
|
RuleTarget::PubTime(cond) => cond.evaluate(&video.pubtime.and_utc().with_timezone(&Local).naive_local()),
|
||||||
RuleTarget::PageCount(cond) => cond.evaluate(pages.len()),
|
RuleTarget::PageCount(cond) => cond.evaluate(pages.len()),
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crate::config::VersionedConfig;
|
|||||||
|
|
||||||
pub static TASK_STATUS_NOTIFIER: LazyLock<TaskStatusNotifier> = LazyLock::new(TaskStatusNotifier::new);
|
pub static TASK_STATUS_NOTIFIER: LazyLock<TaskStatusNotifier> = LazyLock::new(TaskStatusNotifier::new);
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize, Default)]
|
||||||
pub struct TaskStatus {
|
pub struct TaskStatus {
|
||||||
is_running: bool,
|
is_running: bool,
|
||||||
last_run: Option<chrono::DateTime<chrono::Local>>,
|
last_run: Option<chrono::DateTime<chrono::Local>>,
|
||||||
@@ -21,17 +21,6 @@ pub struct TaskStatusNotifier {
|
|||||||
rx: tokio::sync::watch::Receiver<Arc<TaskStatus>>,
|
rx: tokio::sync::watch::Receiver<Arc<TaskStatus>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TaskStatus {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
is_running: false,
|
|
||||||
last_run: None,
|
|
||||||
last_finish: None,
|
|
||||||
next_run: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TaskStatusNotifier {
|
impl TaskStatusNotifier {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let (tx, rx) = tokio::sync::watch::channel(Arc::new(TaskStatus::default()));
|
let (tx, rx) = tokio::sync::watch::channel(Arc::new(TaskStatus::default()));
|
||||||
@@ -55,7 +44,7 @@ impl TaskStatusNotifier {
|
|||||||
|
|
||||||
pub fn finish_running(&self, _lock: MutexGuard<()>) {
|
pub fn finish_running(&self, _lock: MutexGuard<()>) {
|
||||||
let last_status = self.tx.borrow();
|
let last_status = self.tx.borrow();
|
||||||
let last_run = last_status.last_run.clone();
|
let last_run = last_status.last_run;
|
||||||
drop(last_status);
|
drop(last_status);
|
||||||
let config = VersionedConfig::get().load();
|
let config = VersionedConfig::get().load();
|
||||||
let now = chrono::Local::now();
|
let now = chrono::Local::now();
|
||||||
|
|||||||
@@ -296,10 +296,10 @@ pub async fn download_video_pages(
|
|||||||
error!("处理视频「{}」{}失败: {:#}", &video_model.name, task_name, e)
|
error!("处理视频「{}」{}失败: {:#}", &video_model.name, task_name, e)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if let ExecutionStatus::Failed(e) = results.into_iter().nth(4).context("page download result not found")? {
|
if let ExecutionStatus::Failed(e) = results.into_iter().nth(4).context("page download result not found")?
|
||||||
if e.downcast_ref::<DownloadAbortError>().is_some() {
|
&& e.downcast_ref::<DownloadAbortError>().is_some()
|
||||||
return Err(e);
|
{
|
||||||
}
|
return Err(e);
|
||||||
}
|
}
|
||||||
let mut video_active_model: video::ActiveModel = video_model.into();
|
let mut video_active_model: video::ActiveModel = video_model.into();
|
||||||
video_active_model.download_status = Set(status.into());
|
video_active_model.download_status = Set(status.into());
|
||||||
@@ -488,10 +488,10 @@ pub async fn download_page(
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
// 如果下载视频时触发风控,直接返回 DownloadAbortError
|
// 如果下载视频时触发风控,直接返回 DownloadAbortError
|
||||||
if let ExecutionStatus::Failed(e) = results.into_iter().nth(1).context("video download result not found")? {
|
if let ExecutionStatus::Failed(e) = results.into_iter().nth(1).context("video download result not found")?
|
||||||
if let Ok(BiliError::RiskControlOccurred) = e.downcast::<BiliError>() {
|
&& let Ok(BiliError::RiskControlOccurred) = e.downcast::<BiliError>()
|
||||||
bail!(DownloadAbortError());
|
{
|
||||||
}
|
bail!(DownloadAbortError());
|
||||||
}
|
}
|
||||||
let mut page_active_model: page::ActiveModel = page_model.into();
|
let mut page_active_model: page::ActiveModel = page_model.into();
|
||||||
page_active_model.download_status = Set(status.into());
|
page_active_model.download_status = Set(status.into());
|
||||||
|
|||||||
@@ -108,11 +108,11 @@ where
|
|||||||
{
|
{
|
||||||
let pattern = String::deserialize(deserializer)?;
|
let pattern = String::deserialize(deserializer)?;
|
||||||
// 反序列化时预编译 regex,优化性能
|
// 反序列化时预编译 regex,优化性能
|
||||||
let regex = regex::Regex::new(&pattern).map_err(|e| serde::de::Error::custom(e))?;
|
let regex = regex::Regex::new(&pattern).map_err(serde::de::Error::custom)?;
|
||||||
Ok((pattern, regex))
|
Ok((pattern, regex))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_regex<S>(pattern: &String, _regex: ®ex::Regex, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize_regex<S>(pattern: &str, _regex: ®ex::Regex, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user