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

                
                                             
                               
  
 
      
            
                                                                               
                                                  
                                             
 
                       
                                                                 
                                                    
       
 
          

 
            


                                                      
                                                  
                                             
 
                                           
 
                                                              
                                                                         
 
                       
                       

     



                                                                     


     

                                        



                                            
            
   
                                                 
                                                           
                                         
                                             
 
                                   


                                                                             
                                                                             

                       
                     
     

                                  



                                                                       




                           

                                             



                                                                       


                           
         
     
 
                          
                                                                   
      

              

 




                      
            
                                                              
                                                  
                                             
 
                                             

                                                                         
                                                



                                         

        

                           




                                       
 



                                                                 


     
            
                                                       
                                                  
                                             
 
                                                               
 
          

 





                                      
            

                         
                    
                                  
                                                  

                                             
                        
                                                                      
     



                                             
                                
                    
          
                                                         


                                                             
                                      
                                                                            
       
                                            




                                         



                           


                                                
           
     
 



                                                              


     
          
            
                       
                 


                          
                                   


                       
                                                  
                                             
 
                                                 

                       

                                                                            







                                                   

          

 
            
                                                                              
                                                  
                                             
 
                                              

                                                                              
                                                                         
 
                       
                          
     
 


                           
                                                  


                   


     
            
                                                                              
                                                  
                                             
 
                       
                                                                   

                 
          

 
            
                                        
                 
                  

                   
                                                  
                                             
 
                                            
                                      

                                                                             
       

                                                                     
 
                         
                       
     
 



                                                            


     
            
                                                      
                 
                  
                                 
                                                  


                                                         
                                      
                                                                              
       
                                            



                                         



                        
                                                        
     
 
                            
                                                                  
      



                
            




                                    
                                                  
                                             

                                            
                                      
                                                                         



                                                                      

                         
                       
     
 



                                                            

     
 
            

                                            
                  
                       
                                                  
                                             
 
                                               
                             
                                                                             
                                                                         


                           
     
 
                            
                                                                  
      
 
                

 
            
                                                   
                 
                  
                                                                
                                                  


                                                         
                                      
                                                                          
       
                                            



                                         



                        
                                                        
     
 





                                                



                
            




                                
                                                  
                                             

                                      
                                      
                                                                               


                                                                    


                           
     



                   
            
                                
                 
                  




                            
                                                  
                                             
 
                                                                                                                                                                                                     
          

 
            
                                      
                 
                  


                             
                                                  
                                             
 





                                                                                
      


                       
                                                                           



                                    


          
            

                                      
                  

                   
                                                  
                                             

                                            
                                      
                                                                           



                                                                     


                         
     
 



                                                            


     
            
                                  
                 
                  
                                                      
                                                  
                                             

                                            

                                                                              
                                                                           


                           
                      
     
 





                                                


             
 
       
                                                 
            
                    




                           
              
                                                  
                                             
 

                                                    
                                                                   
       
                                                                                                                                                                                                                                                                          

          
 
 
            
                                                        
                                                  
                                             
 
                                                                 
                                                                 
          

 
            
                                                            
                                                  
                                             
 





                                       


                                                                                
 
                                                      




                                         
        
 

                        
                     
                                    






                                                  
                                                                 
     
 
            

 
            
                                                                             
                                                  
                                             
 



                                                       


          
            
                                                            
                                                  
                                             
 

                                                               
                                                                         
 
                       
                           
     
 



                                                   
     

 
        
            
                                                                      
                                                  
                                             
 



                                                                     
          

 
            
                                                             
                                                  
                                             
 
                                    

                                                                             
                                                                           
 

                           


                           
                                                                  
     
 
               

 
                
            
                                  
                 
                  


                                             
                                                  
                                             
 
                       

                                                                               

                       
          

 
            


                                             
                                                  
                                             
 



                                                                   
          
 
 
            



                                             
                                                  
                                             
 



                                                                   
          

 
            


                                                 
                                                  
                                             
 
                                            

                                                                           
                                                                          


                         
     
 





                                                
               

 
            
                       
                 


                 

                                             
                                                  
                                             
 
                                                                         
 
                          




                                                                         


                                          
          

 

                                     
                                             


                                                                
                                                                                                           
                                                                                                         
                                                                  

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

use rusqlite::Connection;

use crate::{
    config::Cfg,
    data::{list::List, modloader::Modloader},
    error::{EType, MLErr, MLE},
};

//MODS
/// # Errors
pub fn mods_insert(config: &Cfg, id: &str, slug: &str, name: &str) -> MLE<()> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    connection.execute(
        "INSERT INTO mods (id, slug, title) VALUES (?1, ?2, ?3)",
        [id, slug, name.replace('\'', "").as_str()],
    )?;

    Ok(())
}

/// # Errors
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)?;

    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 {
        mods.push(id?);
    }

    if mods.is_empty() {
        Err(Box::new(Error::new(ErrorKind::NotFound, "NO_MODS_ALL")))
    } else {
        Ok(mods)
    }
}

/// Get mod id based on the slug or name
/// # Arguments
///
///* `data` - file directory of the database
///* `slug` - Slug or Name of a mod
///
/// # Errors
///
/// Will return `MLError` when no mod id is found
pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> {
    let data = format!("{data}/data.db");
    let connection = Connection::open(data)?;

    let mut mod_id = String::new();

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

    for id in id_iter {
        mod_id = id?;
    }
    //get from id if no slug found
    if mod_id.is_empty() {
        let mut stmt =
            connection.prepare("SELECT id FROM mods WHERE id = ?")?;
        let id_iter =
            stmt.query_map([slug], |row| row.get::<usize, String>(0))?;

        for id in id_iter {
            mod_id = id?;
        }
    }
    //get from title if no id found from slug
    if mod_id.is_empty() {
        let mut stmt =
            connection.prepare("SELECT id FROM mods WHERE title = ?")?;
        let id_iter =
            stmt.query_map([slug], |row| row.get::<usize, String>(0))?;

        for id in id_iter {
            mod_id = id?;
        }
    }

    if mod_id.is_empty() {
        return Err(MLErr::new(EType::DBError, "GI_MOD_NOT_FOUND"));
    };

    Ok(mod_id)
}

pub struct ModInfo {
    pub slug: String,
    pub title: String,
}

/// # Errors
pub fn mods_get_info(config: &Cfg, id: &str) -> MLE<ModInfo> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    let mut mod_info: Option<ModInfo> = None;
    let mut stmt =
        connection.prepare("SELECT title, slug FROM mods WHERE id = ?")?;
    let name_iter = stmt.query_map([id], |row| {
        Ok(vec![
            row.get::<usize, String>(0)?,
            row.get::<usize, String>(1)?,
        ])
    })?;

    for info in name_iter {
        let i = info?;
        mod_info = Some(ModInfo {
            title: String::from(&i[0]),
            slug: String::from(&i[1]),
        });
    }

    if mod_info.is_none() {
        Err(MLErr::new(EType::DBError, "GN_MOD_NOT_FOUND"))
    } else {
        Ok(mod_info.ok_or(MLErr::new(EType::Other, "mod_info"))?)
    }
}

/// # Errors
pub fn mods_remove(config: &Cfg, id: &str) -> MLE<()> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

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

    Ok(())
}

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

/// # Errors
pub fn mods_get_versions(
    config: &Cfg,
    mods: &[String],
) -> MLE<Vec<DBModlistVersions>> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    if mods.is_empty() {
        return Err(MLErr::new(EType::ArgumentError, "MODS_NO_INPUT"));
    }

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

    let mut versionmaps: Vec<DBModlistVersions> = Vec::new();
    let mut stmt = connection.prepare(
        format!("SELECT id, versions, title FROM mods {wherestr}").as_str(),
    )?;
    let id_iter = stmt.query_map([], |row| {
        Ok(vec![
            row.get::<usize, String>(0)?,
            row.get::<usize, String>(1)?,
            row.get::<usize, String>(2)?,
        ])
    })?;

    for ver in id_iter {
        let version = ver?;
        versionmaps.push(DBModlistVersions {
            mod_id: String::from(&version[0]),
            versions: String::from(&version[1]),
        });
    }

    if versionmaps.is_empty() {
        Err(MLErr::new(EType::DBError, "MODS_MODS_NOT_FOUND"))
    } else {
        Ok(versionmaps)
    }
}

//userlist
/// # Errors
pub fn userlist_insert(
    config: &Cfg,
    list_id: &str,
    mod_id: &str,
    current_version: &str,
    applicable_versions: &[String],
    current_link: &str,
    set_version: bool,
) -> MLE<()> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    let sv = if set_version { "1" } else { "0" };

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

    Ok(())
}

/// # Errors
pub fn userlist_get_all_ids(config: &Cfg, list_id: &str) -> MLE<Vec<String>> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    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 {
        mod_ids.push(id?);
    }

    if mod_ids.is_empty() {
        Err(MLErr::new(
            EType::DBError,
            &format!("NO_MODS_USERLIST{list_id}"),
        ))
    } else {
        Ok(mod_ids)
    }
}

/// # Errors
pub fn userlist_remove(config: &Cfg, list_id: &str, mod_id: &str) -> MLE<()> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

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

/// # Errors
pub fn userlist_get_applicable_versions(
    config: &Cfg,
    list_id: &str,
    mod_id: String,
) -> MLE<String> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

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

    for ver in ver_iter {
        version = ver?;
    }

    if version.is_empty() {
        Err(MLErr::new(EType::DBError, "GAV_MOD_NOT_FOUND"))
    } else {
        Ok(version)
    }
}

/// # Errors
pub fn userlist_get_all_applicable_versions_with_mods(
    config: &Cfg,
    list_id: &str,
) -> MLE<Vec<(String, String)>> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

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

    for ver in id_iter {
        let out = ver?;
        versions.push((out[0].clone(), out[1].clone()));
    }

    if versions.is_empty() {
        return Err(MLErr::new(EType::DBError, "NO_MODS_ON_LIST"));
    };

    Ok(versions)
}

/// # Errors
pub fn userlist_get_current_version(
    config: &Cfg,
    list_id: &str,
    mod_id: &str,
) -> MLE<String> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

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

    for ver in ver_iter {
        version = ver?;
    }

    if version.is_empty() {
        Err(MLErr::new(EType::DBError, "GCV_MOD_NOT_FOUND"))
    } else {
        Ok(version)
    }
}

/// # Errors
pub fn userlist_get_all_current_version_ids(
    config: &Cfg,
    list_id: &str,
) -> MLE<Vec<String>> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

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

    for id in id_iter {
        versions.push(id?);
    }

    if versions.is_empty() {
        return Err(MLErr::new(EType::DBError, "NO_MODS_ON_LIST"));
    };

    Ok(versions)
}

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

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

    for ver in id_iter {
        let out = ver?;
        versions.push((out[0].clone(), out[1].clone()));
    }

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

    Ok(versions)
}

/// # Errors
pub fn userlist_get_set_version(
    config: &Cfg,
    list_id: &str,
    mod_id: &str,
) -> MLE<bool> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    let mut set_version: bool = false;
    let mut stmt = connection.prepare(
        format!("SELECT set_version FROM {list_id} WHERE mod_id = ?").as_str(),
    )?;
    let ver_iter =
        stmt.query_map([&mod_id], |row| row.get::<usize, bool>(0))?;

    for ver in ver_iter {
        set_version = ver?;
    }

    Ok(set_version)
}

/// # Errors
pub fn userlist_change_versions(
    config: &Cfg,
    list_id: &str,
    current_version: String,
    versions: String,
    link: String,
    mod_id: String,
) -> MLE<()> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    connection.execute(format!("UPDATE {list_id} SET current_version = ?1, applicable_versions = ?2, current_download = ?3 WHERE mod_id = ?4").as_str(), [current_version, versions, link, mod_id])?;
    Ok(())
}

/// # Errors
pub fn userlist_add_disabled_versions(
    config: &Cfg,
    list_id: &str,
    disabled_version: String,
    mod_id: String,
) -> MLE<()> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    let currently_disabled_versions =
        userlist_get_disabled_versions(config, list_id, String::from(&mod_id))?;
    let disabled_versions = if currently_disabled_versions == "NONE" {
        disabled_version
    } else {
        format!("{currently_disabled_versions}|{disabled_version}")
    };

    connection.execute(
        format!(
            "UPDATE {list_id} SET disabled_versions = ?1 WHERE mod_id = ?2"
        )
        .as_str(),
        [disabled_versions, mod_id],
    )?;
    Ok(())
}

/// # Errors
pub fn userlist_get_disabled_versions(
    config: &Cfg,
    list_id: &str,
    mod_id: String,
) -> MLE<String> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

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

    for ver in ver_iter {
        version = ver?;
    }

    if version.is_empty() {
        Err(MLErr::new(EType::DBError, "GDV_MOD_NOT_FOUND"))
    } else {
        Ok(version)
    }
}

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

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

    for link in link_iter {
        let l = link?;
        links.push(l);
    }

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

    Ok(links)
}

//lists
///Inserts into lists table and creates new table
/// # Errors
pub fn lists_insert(
    config: &Cfg,
    id: &str,
    mc_version: &str,
    mod_loader: &Modloader,
    download_folder: &str,
) -> MLE<()> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    connection.execute(
        "INSERT INTO lists VALUES (?1, ?2, ?3, ?4)",
        [id, mc_version, &mod_loader.to_string(), download_folder],
    )?;
    connection.execute(format!("CREATE TABLE {id}( 'mod_id' TEXT, 'current_version' TEXT, 'applicable_versions' BLOB, 'current_download' TEXT, 'disabled_versions' TEXT DEFAULT 'NONE', 'set_version' INTEGER, CONSTRAINT {id}_PK PRIMARY KEY (mod_id) )").as_str(), [])?;

    Ok(())
}

/// # Errors
pub fn lists_remove(config: &Cfg, id: &str) -> MLE<()> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    connection.execute("DELETE FROM lists WHERE id = ?", [&id])?;
    connection.execute(format!("DROP TABLE {id}").as_str(), [])?;
    Ok(())
}

/// # Errors
pub fn lists_get(config: &Cfg, list_id: &str) -> MLE<List> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    let mut list = List {
        id: String::new(),
        mc_version: String::new(),
        modloader: Modloader::Fabric,
        download_folder: String::new(),
    };
    let mut stmt = connection.prepare(
        "SELECT mc_version, modloader, download_folder FROM lists WHERE id = ?",
    )?;

    let list_iter = stmt.query_map([&list_id], |row| {
        Ok(vec![
            row.get::<usize, String>(0)?,
            row.get::<usize, String>(1)?,
            row.get::<usize, String>(2)?,
        ])
    })?;

    for l in list_iter {
        let li = l?;
        list = List {
            id: list_id.to_string(),
            mc_version: String::from(&li[0]),
            modloader: Modloader::from(&li[1])?,
            download_folder: String::from(&li[2]),
        };
    }

    if list.id.is_empty() {
        return Err(MLErr::new(EType::DBError, "LIST_NOT_FOUND"));
    }

    Ok(list)
}

/// # Errors
pub fn lists_version(config: &Cfg, list_id: &str, version: &str) -> MLE<()> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    connection.execute(
        "UPDATE lists SET mc_version = ? WHERE id = ?",
        [version, list_id],
    )?;
    Ok(())
}

/// # Errors
pub fn lists_get_all_ids(config: &Cfg) -> MLE<Vec<String>> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

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

    for id in id_iter {
        list_ids.push(id?);
    }

    if list_ids.is_empty() {
        Err(MLErr::new(EType::DBError, "NO_LISTS"))
    } else {
        Ok(list_ids)
    }
}

//config
/// # Errors
pub fn config_change_current_list(config: &Cfg, id: &str) -> MLE<()> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    connection.execute(
        "UPDATE user_config SET value = ? WHERE id = 'current_list'",
        [id],
    )?;
    Ok(())
}

/// # Errors
pub fn config_get_current_list(config: &Cfg) -> MLE<String> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    let mut list_id = String::new();
    let mut stmt = connection
        .prepare("SELECT value FROM user_config WHERE id = 'current_list'")?;
    let list_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?;

    for list in list_iter {
        list_id = list?;
    }

    if list_id.is_empty() {
        return Err(MLErr::new(EType::DBError, "NO_CURRENT_LIST"));
    }

    Ok(list_id)
}

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

    connection.execute(
        format!("UPDATE {list_id} SET current_download = ?1 WHERE mod_id = ?2")
            .as_str(),
        [link, mod_id],
    )?;
    Ok(())
}

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

    connection.execute(
        "INSERT INTO 'user_config' VALUES ( 'db_version', '0.2' )",
        (),
    )?;
    Ok(())
}

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

    connection.execute(
        "UPDATE user_config SET value = ? WHERE id = 'db_version'",
        [ver],
    )?;
    Ok(())
}

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

    let mut version: String = String::new();
    let mut stmt = connection
        .prepare("SELECT value FROM user_config WHERE id = 'db_version'")?;
    let ver_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?;

    for ver in ver_iter {
        version = ver?;
    }

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

/// # Errors
pub fn s_insert_column(
    config: &Cfg,
    table: &str,
    column: &str,
    c_type: &str,
    default: Option<String>,
) -> Result<(), Box<dyn std::error::Error>> {
    let data = format!("{}/data.db", config.data);
    let connection = Connection::open(data)?;

    let mut sql = format!("ALTER TABLE {table} ADD '{column}' {c_type}");

    if default.is_some() {
        sql = format!(
            "{} DEFAULT {}",
            sql,
            default.ok_or(MLErr::new(EType::Other, "errornous default"))?
        );
    }

    connection.execute(sql.as_str(), ())?;
    Ok(())
}

/// # Errors
pub fn setup(path: &str) -> MLE<()> {
    let connection = Connection::open(path)?;

    connection.execute_batch(
        "CREATE TABLE 'user_config' ( 'id' TEXT, 'value' TEXT );
         CREATE TABLE 'mods' ( 'id' TEXT, 'slug' TEXT, 'title' TEXT, CONSTRAINT mods_PK PRIMARY KEY (id) );
         CREATE TABLE 'lists' ( 'id' TEXT, 'mc_version' TEXT, 'modloader' TEXT, 'download_folder' TEXT );
         INSERT INTO 'user_config' VALUES ( 'db_version', '0.5' );
         INSERT INTO 'user_config' VALUES ( 'current_list', '...' )",
    )?;

    Ok(())
}