mirror of
https://github.com/yuhkix/wuwa-downloader.git
synced 2025-06-04 08:53:41 +00:00
Add URL logging to urls.txt during size calculation phase
This commit is contained in:
parent
7bd0b77bd0
commit
808f929e62
5 changed files with 148 additions and 130 deletions
42
.gitignore
vendored
42
.gitignore
vendored
|
@ -1,22 +1,22 @@
|
||||||
# Generated by Cargo
|
# Generated by Cargo
|
||||||
# will have compiled files and executables
|
# will have compiled files and executables
|
||||||
debug/
|
debug/
|
||||||
target/
|
target/
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
# These are backup files generated by rustfmt
|
# These are backup files generated by rustfmt
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
|
||||||
# Error / Debug Logging
|
# Error / Debug Logging
|
||||||
*.log
|
*.log
|
||||||
|
|
||||||
# MSVC Windows builds of rustc generate these, which store debugging information
|
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||||
*.pdb
|
*.pdb
|
||||||
|
|
||||||
|
|
||||||
# RustRover
|
# RustRover
|
||||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
#.idea/
|
#.idea/
|
42
LICENSE
42
LICENSE
|
@ -1,21 +1,21 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2025 Yuhki
|
Copyright (c) 2025 Yuhki
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
154
README.md
154
README.md
|
@ -1,77 +1,77 @@
|
||||||
# 🌊 Wuthering Waves Downloader
|
# 🌊 Wuthering Waves Downloader
|
||||||
|
|
||||||
*A high-performance, reliable downloader for Wuthering Waves with multi-CDN support and verification*
|
*A high-performance, reliable downloader for Wuthering Waves with multi-CDN support and verification*
|
||||||
|
|
||||||
> Feel free to open Pull requests if you want to contribute with improvements!
|
> Feel free to open Pull requests if you want to contribute with improvements!
|
||||||
|
|
||||||
[](https://www.rust-lang.org/)
|
[](https://www.rust-lang.org/)
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
|
|
||||||
## 📦 Requirements
|
## 📦 Requirements
|
||||||
- **Rust nightly toolchain** - 1.87.0-nightly or newer
|
- **Rust nightly toolchain** - 1.87.0-nightly or newer
|
||||||
- **Windows** - for full console feature support
|
- **Windows** - for full console feature support
|
||||||
|
|
||||||
### 🛠️ Installation & Usage
|
### 🛠️ Installation & Usage
|
||||||
- **Install the nightly toolchain:**
|
- **Install the nightly toolchain:**
|
||||||
```bash
|
```bash
|
||||||
rustup toolchain install nightly
|
rustup toolchain install nightly
|
||||||
rustup default nightly
|
rustup default nightly
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Clone the repository:**
|
- **Clone the repository:**
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/yuhkix/wuwa-downloader.git
|
git clone https://github.com/yuhkix/wuwa-downloader.git
|
||||||
cd wuwa-downloader
|
cd wuwa-downloader
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Build the project:**
|
- **Build the project:**
|
||||||
```bash
|
```bash
|
||||||
cargo build --release
|
cargo build --release
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🌟 Key Features
|
## 🌟 Key Features
|
||||||
|
|
||||||
### 🚀 Download Management
|
### 🚀 Download Management
|
||||||
- **Multi-CDN Fallback** - Automatically tries all available CDN mirrors
|
- **Multi-CDN Fallback** - Automatically tries all available CDN mirrors
|
||||||
|
|
||||||
- **Version Selection** - Interactive menu for Live/Beta versions
|
- **Version Selection** - Interactive menu for Live/Beta versions
|
||||||
|
|
||||||
- **Verified Downloads** - MD5 checksum validation for every file
|
- **Verified Downloads** - MD5 checksum validation for every file
|
||||||
|
|
||||||
- **Smart Retry Logic** - 3 retry attempts per CDN with timeout protection
|
- **Smart Retry Logic** - 3 retry attempts per CDN with timeout protection
|
||||||
|
|
||||||
- **GZIP Support** - Handles compressed responses efficiently
|
- **GZIP Support** - Handles compressed responses efficiently
|
||||||
|
|
||||||
### 🛡️ Reliability
|
### 🛡️ Reliability
|
||||||
- **Atomic Operations** - Thread-safe progress tracking
|
- **Atomic Operations** - Thread-safe progress tracking
|
||||||
|
|
||||||
- **Graceful Interrupt** - CTRL-C handling with summary display
|
- **Graceful Interrupt** - CTRL-C handling with summary display
|
||||||
|
|
||||||
- **Comprehensive Logging** - Detailed error logging with timestamps
|
- **Comprehensive Logging** - Detailed error logging with timestamps
|
||||||
|
|
||||||
- **Validation Failures** - Auto-removes files with checksum mismatches
|
- **Validation Failures** - Auto-removes files with checksum mismatches
|
||||||
|
|
||||||
### 📂 File Management
|
### 📂 File Management
|
||||||
- **Smart Path Handling** - Cross-platform path support
|
- **Smart Path Handling** - Cross-platform path support
|
||||||
|
|
||||||
- **Auto-directory Creation** - Builds full directory trees as needed
|
- **Auto-directory Creation** - Builds full directory trees as needed
|
||||||
|
|
||||||
- **Clean Failed Downloads** - Removes corrupted files automatically
|
- **Clean Failed Downloads** - Removes corrupted files automatically
|
||||||
|
|
||||||
### 💻 User Interface
|
### 💻 User Interface
|
||||||
- **Color-coded Output** - Clear visual feedback (success/warning/error)
|
- **Color-coded Output** - Clear visual feedback (success/warning/error)
|
||||||
|
|
||||||
- **Dynamic Title Updates** - Real-time progress in window title
|
- **Dynamic Title Updates** - Real-time progress in window title
|
||||||
|
|
||||||
- **Clean Progress Display** - Simplified download status without clutter
|
- **Clean Progress Display** - Simplified download status without clutter
|
||||||
|
|
||||||
- **Formatted Duration** - Clear elapsed time display (HH:MM:SS)
|
- **Formatted Duration** - Clear elapsed time display (HH:MM:SS)
|
||||||
|
|
||||||
### ⚙️ Technical Details
|
### ⚙️ Technical Details
|
||||||
- **Streaming Downloads** - Memory-efficient chunked transfers
|
- **Streaming Downloads** - Memory-efficient chunked transfers
|
||||||
|
|
||||||
- **HEAD Request Verification** - Pre-checks file availability
|
- **HEAD Request Verification** - Pre-checks file availability
|
||||||
|
|
||||||
- **Multi-threaded** - Safe concurrent progress tracking
|
- **Multi-threaded** - Safe concurrent progress tracking
|
||||||
|
|
||||||
- **Configurable Timeouts** - 30s for metadata, 10000s for downloads
|
- **Configurable Timeouts** - 30s for metadata, 10000s for downloads
|
||||||
|
|
16
build.rs
16
build.rs
|
@ -1,8 +1,8 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
{
|
{
|
||||||
let mut res = winres::WindowsResource::new();
|
let mut res = winres::WindowsResource::new();
|
||||||
res.set_icon("cartethyia.ico");
|
res.set_icon("cartethyia.ico");
|
||||||
res.compile().unwrap();
|
res.compile().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ use colored::Colorize;
|
||||||
use reqwest::blocking::Client;
|
use reqwest::blocking::Client;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::{self, File},
|
||||||
io,
|
io::{self, Write},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
thread,
|
thread,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
|
@ -37,6 +37,23 @@ pub fn bytes_to_human(bytes: u64) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn log_url(url: &str) {
|
||||||
|
let sanitized_url = if let Some(index) = url.find("://") {
|
||||||
|
let (scheme, rest) = url.split_at(index + 3);
|
||||||
|
format!("{}{}", scheme, rest.replace("//", "/"))
|
||||||
|
} else {
|
||||||
|
url.replace("//", "/")
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Ok(mut url_log) = fs::OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.append(true)
|
||||||
|
.open("urls.txt")
|
||||||
|
{
|
||||||
|
let _ = writeln!(url_log, "{}", sanitized_url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn calculate_total_size(resources: &[Value], client: &Client, config: &Config) -> u64 {
|
pub fn calculate_total_size(resources: &[Value], client: &Client, config: &Config) -> u64 {
|
||||||
let mut total_size = 0;
|
let mut total_size = 0;
|
||||||
let mut failed_urls = 0;
|
let mut failed_urls = 0;
|
||||||
|
@ -50,6 +67,7 @@ pub fn calculate_total_size(resources: &[Value], client: &Client, config: &Confi
|
||||||
|
|
||||||
for base_url in &config.zip_bases {
|
for base_url in &config.zip_bases {
|
||||||
let url = format!("{}/{}", base_url, dest);
|
let url = format!("{}/{}", base_url, dest);
|
||||||
|
log_url(&url);
|
||||||
match client.head(&url).send() {
|
match client.head(&url).send() {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
if let Some(len) = response.headers().get("content-length") {
|
if let Some(len) = response.headers().get("content-length") {
|
||||||
|
@ -189,7 +207,7 @@ pub fn start_title_thread(
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
let title = format!(
|
let _title = format!(
|
||||||
"Wuthering Waves Downloader - {}/{} files - Total Downloaded: {}{} - Speed: {}{} - Total ETA: {}",
|
"Wuthering Waves Downloader - {}/{} files - Total Downloaded: {}{} - Speed: {}{} - Total ETA: {}",
|
||||||
current_success,
|
current_success,
|
||||||
total_files,
|
total_files,
|
||||||
|
|
Loading…
Reference in a new issue