Using ureq to download files

I might just throw out the TempFile thing - should actually save them somewhere. As
I think it would likely be useful for testing too
This commit is contained in:
2025-08-13 20:22:49 +01:00
parent 6b4105ecd9
commit 906aaa1e59
5 changed files with 587 additions and 366 deletions

View File

@@ -1,8 +1,83 @@
use chrono::NaiveDate;
use serde::Deserialize;
use serde_json::Value;
use std::fs;
use std::io::{Read, Seek, SeekFrom, Write};
use tempfile::NamedTempFile;
use ureq;
use uuid::Uuid;
#[allow(dead_code)]
#[derive(Deserialize, Debug)]
struct ScryfallBulkData {
pub id: Uuid,
pub uri: String,
#[serde(rename = "type")]
pub stype: String,
pub name: String,
pub description: String,
pub download_uri: String,
pub updated_at: String,
pub content_type: String,
pub content_encoding: String,
}
#[allow(dead_code)]
#[derive(Deserialize, Debug)]
struct ScryfallBulk {
pub object: String,
pub has_more: bool,
pub data: Vec<ScryfallBulkData>,
}
#[derive(Deserialize, PartialEq, Debug)]
pub enum ScryfallBulkType {
#[serde(rename = "oracle_cards")]
OracleCards,
#[serde(rename = "unique_artwork")]
UniqueArtwork,
#[serde(rename = "default_cards")]
DefaultCards,
#[serde(rename = "all_cards")]
AllCards,
#[serde(rename = "rulings")]
Rulings,
}
const SCRYFALL_BULK_API: &str = "https://api.scryfall.com/bulk-data";
pub fn download_latest(
_stype: ScryfallBulkType,
mut dest_file: &NamedTempFile,
) -> Result<(), Box<dyn std::error::Error>> {
let bulk_body: ScryfallBulk = ureq::get(SCRYFALL_BULK_API)
.header("User-Agent", "Arthur's Card Finger Testing v0.1")
.header("Accept", "application/json")
.call()?
.body_mut()
.read_json::<ScryfallBulk>()?;
let mut download_uri = String::new();
for scryfall_bulk in bulk_body.data {
// TODO: Actually implement getting different types
if scryfall_bulk.stype == "oracle_cards" {
download_uri = scryfall_bulk.download_uri;
}
}
assert!(!download_uri.is_empty());
let cards_response = ureq::get(download_uri)
.header("User-Agent", "Arthur's Card Finger Testing v0.1")
.header("Accept", "application/json")
.call()?
.body_mut()
.with_config()
.limit(700 * 1024 * 1024)
.read_to_string()?;
write!(dest_file, "{}", cards_response)?;
Ok(())
}
// Info from here:
// https://scryfall.com/docs/api/cards
#[allow(dead_code)]
@@ -110,7 +185,6 @@ struct ScryfallCard {
pub watermark: Option<String>,
pub preview: Option<Preview>,
// These aren't in the Scryfall docs, but some cards do have 'em
pub foil: Option<bool>,
pub nonfoil: Option<bool>,
@@ -785,4 +859,14 @@ mod tests {
let ac = fs::read_to_string(f).unwrap();
let _ac: Vec<ScryfallCard> = serde_json::from_str(&ac).unwrap();
}
#[test]
#[ignore]
fn get_scryfall_bulk_page() {
let mut file = NamedTempFile::new().unwrap();
let _ = download_latest(ScryfallBulkType::OracleCards, &file);
let file_size = file.seek(SeekFrom::End(0)).unwrap();
assert!(file_size > 4092);
println!("File size: {}", file_size);
}
}

View File

@@ -0,0 +1,22 @@
use clap::Parser;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
#[arg(short, long)]
update: bool,
remainder: Vec<String>,
}
fn main() {
let mut args = Args::parse();
if args.update {
unimplemented!("Haven't implemented update yet");
}
let card_name = args.remainder;
if card_name.is_empty() {
panic!("You need to put some card text to search");
}
let search_string = card_name.join(" ");
dbg!(search_string);
}