summaryrefslogblamecommitdiff
path: root/src/db.rs
blob: 86e697e0c5d12b2a76ace8769611112b329304d6 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                
 
                         
 
                                          
 
      
                                                                                                                            
 
                                                             
 
                                                  
                                             
 



                                                                    
 
          

 
                                                                                         
                                                  


                                                     
 



                                                              
 


                                                        

     








                                                                                             
    














                                                                                

 



                                                                                       
                                                  
                                             
 
                                                               
 
          

 


                                                                                                                                                                                                 
 
                                                  
                                             
 
    


                                                                                                                                                                     

 
                                                                                                              
                                                  
                                                     
 




                                                                                           
 





                                                        
                                                                                   
                             


     
 


                                                                                                                
 

                                                                                                

 
 






                                                                                                                   


                                                  
 






                                                               
 
                                                                    
 
               
 


                                                                    
 



                                                                                                                  
 




                                                                                                                  

 
                                                                                                                
      

















                                                                                                              

                     

 
 



                                                                                                                                   
                                                  
                                             
 



                                                                                                                                                                  
 
 

                                                                                       







                                                                    

          


                                                                                  
      

















                                                                                    

                           

 
                                                                                                  
      

















                                                                                                               

                           

 
                                                                                      
      

















                                                                                                                  

                                                                                           

 

                                                                                                                                                                





                                                                                                                                                                    

          

 

          

                                                                                                                        





                                                                                                          

          


                                                                                          
      

















                                                                                                            

                           

 
        

                                                                                       





                                                                                           

          

 
                                                                                       
      


















                                                                                    

                     
 
 

                                                                                             





                                                                                          

          

 

                                                                                



                                                                          

          

 

                                                                                  















                                                                                                       

                           

 

                                                                        


                                                  










                                                                                 

 

                                                                                                                            












                                                                       

          
 
use std::io::{Error, ErrorKind};

use rusqlite::Connection;

use crate::{Modloader, config::Cfg, List};

//MODS
pub fn mods_insert(config: Cfg, id: String, name: String, versions: Vec<String>) -> Result<(), Box<dyn std::error::Error>> {

    println!("Inserting mod {}({}) into database", name, id);

    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    connection.execute(
        "INSERT INTO mods (id, name, versions) VALUES (?1, ?2, ?3)",
        [id, name.replace('\'', ""), versions.join("|")]
    )?;

    Ok(())
}

pub fn mods_get_all_ids(config: Cfg) -> Result<Vec<String>, Box<dyn std::error::Error>> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data).unwrap();
    
    let mut mods: Vec<String> = Vec::new();

    let mut stmt = connection.prepare("SELECT id FROM mods")?;
    let id_iter = stmt.query_map([], |row| {
        row.get::<usize, String>(0)
    })?;

    for id in id_iter {
        println!("Found id {:?}", id.as_ref().unwrap());
        mods.push(id?);
    }

    match mods.is_empty() {
        true => Err(Box::new(Error::new(ErrorKind::NotFound, "NO_MODS"))),
        false => Ok(mods),
    }
}

pub fn mods_get_id(config: Cfg, name: String) -> Result<String, Box<dyn std::error::Error>> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;
    
    let mut mod_id = String::new();
    let mut stmt = connection.prepare("SELECT id FROM mods WHERE name = ?")?;
    let id_iter = stmt.query_map([name], |row| {
        row.get::<usize, String>(0)
    })?;

    for id in id_iter {
        println!("Found id {:?}", id.as_ref().unwrap());
        mod_id = id?;
    };

    match mod_id.is_empty() {
        true => Err(Box::new(Error::new(ErrorKind::NotFound, "MOD_NOT_FOUND"))),
        false => Ok(mod_id),
    }
}

pub fn mods_remove(config: Cfg, id: String) -> Result<(), Box<dyn std::error::Error>> {

    println!("Removing mod {} from database", id);

    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    connection.execute("DELETE FROM mods WHERE id = ?", [id])?;

    Ok(())
}

//userlist
pub fn userlist_insert(config: Cfg, list_id: String, mod_id: String, current_version: String, applicable_versions: Vec<String>, current_link: String) -> Result<(), Box<dyn std::error::Error>> {
    println!("Inserting {} into current list({})", mod_id, list_id);

    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    
    connection.execute(format!("INSERT INTO {} VALUES (?1, ?2, ?3, ?4)", list_id).as_str(), [mod_id, current_version, applicable_versions.join("|"), current_link])?;

    Ok(())
}

pub fn userlist_get_all_ids(config: Cfg, list_id: String) -> Result<Vec<String>, Box<dyn std::error::Error>> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data).unwrap();

    let mut mod_ids: Vec<String> = Vec::new();
    let mut stmt = connection.prepare(format!("SELECT mod_id FROM {}", list_id).as_str())?;
    let id_iter = stmt.query_map([], |row| {
        row.get::<usize, String>(0)
    })?;

    for id in id_iter {
        println!("Found id {:?}", id.as_ref().unwrap());
        mod_ids.push(id?)
    };

    match mod_ids.is_empty() {
        true => Err(Box::new(std::io::Error::new(ErrorKind::NotFound, "NO_MODS"))),
        false => Ok(mod_ids),
    }
}


pub fn userlist_remove(config: Cfg, list_id: String, mod_id: String) -> Result<(), Box<dyn std::error::Error>> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    connection.execute(format!("DELETE FROM {} WHERE mod_id = ?", list_id).as_str(), [mod_id])?;
    Ok(())
}


#[derive(Debug, Clone)]
pub struct DBModlistVersions {
    pub mod_id: String,
    pub versions: String,
}

pub fn get_versions(config: Cfg, mods: Vec<String>) -> Result<Vec<DBModlistVersions>, Box<dyn std::error::Error>> {
    /*
    let data = format!("{}/data.db", config.data);
    let connection = sqlite::open(data).unwrap();

    let mut wherestr = String::from("WHERE");
    for (i, id) in mods.iter().enumerate() {
        let mut or = " OR";
        if i == mods.len() - 1 { or = ""  }
        println!("Pushing {}({}) | OR: '{}'", id, i, or);
        wherestr = format!("{} id = '{}'{}", wherestr, id, or);
    }

    let sql = format!("SELECT id, versions FROM mods {}", wherestr);

    dbg!(&sql);

    let mut versionmaps: Vec<DBModlistVersions> = Vec::new();
    //TODO catch sql errors better
    let mut cursor = connection.prepare(sql).unwrap().into_cursor();

    while let Some(Ok(row)) = cursor.next() {
        println!("{}: {}", row.get::<String, _>(0), row.get::<String, _>(1));
        versionmaps.push(DBModlistVersions { mod_id: row.get::<String, _>(0), versions: row.get::<String, _>(1) })
    };

    if versionmaps.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); };

    Ok(versionmaps)
    */
    Ok(vec![DBModlistVersions { mod_id: String::new(), versions: String::new() }])
}

pub fn get_list_version(config: Cfg, list: List, mod_id: String) -> Result<String, Box<dyn std::error::Error>> {
    /*
    let data = format!("{}/data.db", config.data);
    let connection = sqlite::open(data).unwrap();
    
    let sql = format!("SELECT applicable_versions FROM {} WHERE mod_id = '{}'", list.id, mod_id);

    //TODO catch sql errors better
    let mut version: String = String::new();
    connection.iterate(sql, |ver| {
        if ver.is_empty() { return false; };
        for &(_column, value) in ver.iter() {
            version = String::from(value.unwrap());
        }
        true
    }).unwrap();
    
    if version.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); };

    Ok(version)
    */
    Ok(String::new())
}


//lists
pub fn lists_insert(config: Cfg, id: String, mc_version: String, mod_loader: Modloader) -> Result<(), Box<dyn std::error::Error>> {
    println!("Creating list {}", id);

    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    connection.execute("INSERT INTO lists VALUES (?1, ?2, ?3)", [id.clone(), mc_version, mod_loader.stringify()])?;
    connection.execute(format!("CREATE TABLE {}( 'mod_id' TEXT, 'current_version' TEXT, 'applicable_versions' BLOB, 'current_download' TEXT)", id).as_str(), [])?;

    Ok(())
}

pub fn remove_list(config: Cfg, id: String) -> Result<(), Box<dyn std::error::Error>> {
    /*
    let data = format!("{}/data.db", config.data);
    let connection = sqlite::open(data).unwrap();

    let sql_list = format!("DELETE FROM lists WHERE id = '{}'", id);
    let sql_table = format!("DROP TABLE '{}'", id);
    let sql = format!("{};{};", sql_list, sql_table);

    connection.execute(sql)
    */
    Ok(())
}

pub fn get_lists(config: Cfg) -> Result<Vec<String>, Box<dyn std::error::Error>> {
    /*
    let data = format!("{}/data.db", config.data);
    let connection = sqlite::open(data).unwrap();

    let sql = "SELECT id FROM lists";
    
    let mut list: Vec<String> = Vec::new();
    //TODO catch sql errors better
    connection.iterate(sql, |ids| {
        if ids.is_empty() { return false; };
        for &(_column, value) in ids.iter() {
            list.push(String::from(value.unwrap()));
        }
        true
    }).unwrap();
    match list.is_empty() {
        true => Err(Box::new(std::io::Error::new(ErrorKind::NotFound, "NO_LISTS"))),
        false => Ok(list),
    }
    */
    Ok(vec![String::new()])
}

pub fn get_current_versions(config: Cfg, list: List) -> Result<Vec<String>, Box<std::io::Error>> {
    /*
    let data = format!("{}/data.db", config.data);
    let connection = sqlite::open(data).unwrap();

    let sql = format!("SELECT current_version FROM {}", list.id);

    dbg!(&sql);

    let mut versions: Vec<String> = Vec::new();
    //TODO catch sql errors better
    let mut cursor = connection.prepare(sql).unwrap().into_cursor();

    while let Some(Ok(row)) = cursor.next() {
        versions.push(row.get::<String, _>(0));
    };

    if versions.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); };

    Ok(versions)
    */
    Ok(vec![String::new()])
}

pub fn get_list(config: Cfg, id: String) -> Result<List, Box<dyn std::error::Error>> {
    /*
    let data = format!("{}/data.db", config.data);
    let connection = sqlite::open(data).unwrap();

    let sql = format!("SELECT mc_version, modloader FROM lists WHERE id = '{}'", id);
    
    let mut list = vec![];
    //TODO catch sql errors better
    connection.iterate(sql, |ids| {
        if ids.is_empty() { return false; };
        for &(_column, value) in ids.iter() {
            list.push(String::from(value.unwrap()));
        }
        true
    }).unwrap();

    if list.len() != 2 { return Err(Box::new(std::io::Error::new(ErrorKind::InvalidData, "LIST_MISSING_DATA"))) };
    
    Ok(List { id, mc_version: String::from(&list[0]), modloader: get_modloader(String::from(&list[1]))? })
    */
    Ok(List { id: String::new(), mc_version: String::new(), modloader: Modloader::Fabric })
}

pub fn change_list_versions(config: Cfg, list: List, current_version: String, versions: Vec<String>, mod_id: String) -> Result<(), Box<dyn std::error::Error>> {
    /*
    let data = format!("{}/data.db", config.data);
    let connection = sqlite::open(data).unwrap();

    let sql = format!("UPDATE {} SET current_version = '{}', applicable_versions = '{}' WHERE mod_id = '{}'", list.id, current_version, versions.join("|"), mod_id);

    connection.execute(sql)
    */
    Ok(())
}

//DOWNLOAD

pub fn insert_dl_link(config: Cfg, list: List, mod_id: String, link: String) -> Result<(), Box<dyn std::error::Error>> {
    /*
    let data = format!("{}/data.db", config.data);
    let connection = sqlite::open(data).unwrap();

    let sql = format!("UPDATE {} SET current_download = '{}' WHERE mod_id = '{}'", list.id, link, mod_id);

    connection.execute(sql)
    */
    Ok(())
}

pub fn get_dl_links(config: Cfg, list: List) -> Result<Vec<String>, Box<std::io::Error>> {
    /*
    let data = format!("{}/data.db", config.data);
    let connection = sqlite::open(data).unwrap();

    let sql = format!("SELECT current_download FROM {}", list.id);

    dbg!(&sql);

    let mut links: Vec<String> = Vec::new();
    //TODO catch sql errors better
    let mut cursor = connection.prepare(sql).unwrap().into_cursor();

    while let Some(Ok(row)) = cursor.next() {
        links.push(row.get::<String, _>(0));
    };

    if links.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); };

    Ok(links)
    */
    Ok(vec![String::new()])
}

//config
pub fn change_list(config: Cfg, id: String) -> Result<(), Box<dyn std::error::Error>> {
    /*
    let data = format!("{}/data.db", config.data);
    let connection = sqlite::open(data).unwrap();

    let sql = format!("UPDATE user_config SET value = '{}' WHERE id = 'current_list'", id);

    connection.execute(sql)
    */
    Ok(())
}

pub fn get_current_list_id(config: Cfg) -> Result<String, Box<dyn std::error::Error>> {
    /*
    let data = format!("{}/data.db", config.data);
    let connection = sqlite::open(data).unwrap();

    let sql = "SELECT id FROM lists";
    
    let mut list: String = String::new();
    //TODO catch sql errors better
    connection.iterate(sql, |ids| {
        if ids.is_empty() { return false; };
        for &(_column, value) in ids.iter() {
            list = String::from(value.unwrap());
        }
        true
    }).unwrap();
    if list.is_empty() {
        get_lists(config)?;
        panic!("current list field should never be empty if there are other lists");
    };
    Ok(list)
    */
    Ok(String::new())
}

pub fn update_dbversion(config: Cfg, ver: String) -> Result<(), Box<dyn std::error::Error>> {
    /*
    let data = format!("{}/data.db", config.data);
    let connection = sqlite::open(data).unwrap();

    let sql = format!("UPDATE user_config SET value = '{}' WHERE id = 'db_version'", ver);

    connection.execute(sql)
    */
    Ok(())
}

pub fn create_dbversion(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
    /*
    let data = format!("{}/data.db", config.data);
    let connection = sqlite::open(data).unwrap();
    let sql = "INSERT INTO 'user_config' VALUES ( 'db_version', '0.2' );";
    connection.execute(sql)
    */
    Ok(())
}

pub fn user_dbversion(config: Cfg) -> Result<String, Box<dyn std::error::Error>> {
    /*
    let data = format!("{}/data.db", config.data);
    let connection = sqlite::open(data).unwrap();

    let sql = "SELECT db_version FROM user_config";
    
    let mut ver: String = String::new();
    //TODO catch sql errors better
    connection.iterate(sql, |ids| {
        if ids.is_empty() { return false; };
        for &(_column, value) in ids.iter() {
            ver = String::from(value.unwrap());
        }
        true
    })?;
    if ver.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_DBVERSION"))); };
    Ok(ver)
    */
    Ok(String::from("0.2"))
}

pub fn db_setup(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
    
    println!("Initiating database");

    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    connection.execute_batch(
        "CREATE TABLE 'user_config' ( 'id' TEXT, 'value' TEXT );
         CREATE TABLE 'mods' ( 'id' TEXT, 'name' TEXT, 'versions' TEXT );
         CREATE TABLE 'lists' ( 'id' TEXT, 'mc_version' TEXT, 'modloader' TEXT );
         INSERT INTO 'user_config' VALUES ( 'db_version', '0.2' );
         INSERT INTO 'user_config' VALUES ( 'current_list', '...' )",
    )?;
    
    Ok(())
}

pub fn insert_column(config: Cfg, table: String, column: String, c_type: String) -> Result<(), Box<dyn std::error::Error>> {
    /*
    let data = format!("{}/data.db", config.data);
    let connection = sqlite::open(data).unwrap();

    let ct = match c_type {
        sqlite::Type::Null => "NULL",
        sqlite::Type::Float => "FLOAT",
        sqlite::Type::Binary => "BINARY",
        sqlite::Type::String => "TEXT",
        sqlite::Type::Integer => "INT",
    };

    let sql = format!("ALTER TABLE {} ADD '{}' {}", table, column, ct);
    connection.execute(sql)
    */
    Ok(())
}