summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/commands/download.rs4
-rw-r--r--src/commands/list.rs27
-rw-r--r--src/commands/modification.rs2
-rw-r--r--src/commands/setup.rs17
-rw-r--r--src/commands/update.rs13
-rw-r--r--src/db.rs406
-rw-r--r--src/lib.rs2
7 files changed, 203 insertions, 268 deletions
diff --git a/src/commands/download.rs b/src/commands/download.rs
index 05c54cb..993294b 100644
--- a/src/commands/download.rs
+++ b/src/commands/download.rs
@@ -4,12 +4,12 @@ use reqwest::Client;
4 4
5use futures_util::StreamExt; 5use futures_util::StreamExt;
6 6
7use crate::{get_current_list, config::Cfg, db::get_dl_links}; 7use crate::{get_current_list, config::Cfg, db::userlist_get_all_downloads};
8 8
9pub async fn download(config: Cfg) -> Result<(), Box<dyn std::error::Error>> { 9pub async fn download(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
10 let list = get_current_list(config.clone())?; 10 let list = get_current_list(config.clone())?;
11 11
12 let links = get_dl_links(config.clone(), list)?; 12 let links = userlist_get_all_downloads(config.clone(), list.id)?;
13 13
14 download_links(config, links).await?; 14 download_links(config, links).await?;
15 15
diff --git a/src/commands/list.rs b/src/commands/list.rs
index ffa5926..6c80e4e 100644
--- a/src/commands/list.rs
+++ b/src/commands/list.rs
@@ -1,8 +1,8 @@
1use std::io::{Error, ErrorKind}; 1use std::io::{Error, ErrorKind};
2 2
3use crate::{db::{lists_insert, remove_list, change_list, get_lists, get_current_list_id, get_list}, Modloader, config::Cfg, input::Input}; 3use crate::{db::{lists_insert, lists_remove, config_change_current_list, lists_get_all_ids, config_get_current_list, lists_get}, Modloader, config::Cfg, input::Input};
4 4
5#[derive(Clone)] 5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct List { 6pub struct List {
7 pub id: String, 7 pub id: String,
8 pub mc_version: String, 8 pub mc_version: String,
@@ -12,8 +12,8 @@ pub struct List {
12pub fn list(config: Cfg, args: Option<Vec<String>>) -> Result<(), Box<dyn std::error::Error>> { 12pub fn list(config: Cfg, args: Option<Vec<String>>) -> Result<(), Box<dyn std::error::Error>> {
13 13
14 if args.is_none() { 14 if args.is_none() {
15 let lists = get_lists(config.clone())?; 15 let lists = lists_get_all_ids(config.clone())?;
16 let current_list = get_current_list_id(config)?; 16 let current_list = config_get_current_list(config)?;
17 println!("Your lists:\n{}\n-----\nCurrently selected list: \"{}\"", lists.join(",\n"), current_list); 17 println!("Your lists:\n{}\n-----\nCurrently selected list: \"{}\"", lists.join(",\n"), current_list);
18 return Ok(()); 18 return Ok(());
19 } 19 }
@@ -37,8 +37,8 @@ pub fn list(config: Cfg, args: Option<Vec<String>>) -> Result<(), Box<dyn std::e
37} 37}
38 38
39pub fn get_current_list(config: Cfg) -> Result<List, Box<dyn std::error::Error>> { 39pub fn get_current_list(config: Cfg) -> Result<List, Box<dyn std::error::Error>> {
40 let id = get_current_list_id(config.clone())?; 40 let id = config_get_current_list(config.clone())?;
41 get_list(config, id) 41 lists_get(config, id)
42} 42}
43 43
44fn add(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>> { 44fn add(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>> {
@@ -52,10 +52,7 @@ fn add(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>>
52 "fabric" => Modloader::Fabric, 52 "fabric" => Modloader::Fabric,
53 _ => return Err(Box::new(Error::new(ErrorKind::InvalidInput, "UNKNOWN_MODLOADER"))) 53 _ => return Err(Box::new(Error::new(ErrorKind::InvalidInput, "UNKNOWN_MODLOADER")))
54 }; 54 };
55 match lists_insert(config, id, mc_version, mod_loader) { 55 lists_insert(config, id, mc_version, mod_loader)
56 Err(err) => { Err(Box::new(Error::new(ErrorKind::Other, "TBD"))) },
57 Ok(()) => Ok(()),
58 }
59 }, 56 },
60 5.. => Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_MANY_ARGUMENTS"))), 57 5.. => Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_MANY_ARGUMENTS"))),
61 _ => panic!("list arguments should never be zero or lower"), 58 _ => panic!("list arguments should never be zero or lower"),
@@ -63,13 +60,13 @@ fn add(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>>
63} 60}
64 61
65fn change(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>> { 62fn change(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>> {
66 let lists = get_lists(config.clone())?; 63 let lists = lists_get_all_ids(config.clone())?;
67 match args.len() { 64 match args.len() {
68 1 => { 65 1 => {
69 let list = String::from(&args[0]); 66 let list = String::from(&args[0]);
70 if !lists.contains(&list) { return Err(Box::new(Error::new(ErrorKind::NotFound, "LIST_DOESNT_EXIST"))); }; 67 if !lists.contains(&list) { return Err(Box::new(Error::new(ErrorKind::NotFound, "LIST_DOESNT_EXIST"))); };
71 match change_list(config, list) { 68 match config_change_current_list(config, list) {
72 Err(err) => { Err(Box::new(Error::new(ErrorKind::Other, "TBD"))) }, 69 Err(..) => { Err(Box::new(Error::new(ErrorKind::Other, "72"))) },
73 Ok(()) => Ok(()), 70 Ok(()) => Ok(()),
74 } 71 }
75 }, 72 },
@@ -81,8 +78,8 @@ fn change(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Erro
81fn remove(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>> { 78fn remove(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>> {
82 match args.len() { 79 match args.len() {
83 1 => { 80 1 => {
84 match remove_list(config, String::from(&args[0])) { 81 match lists_remove(config, String::from(&args[0])) {
85 Err(err) => { Err(Box::new(Error::new(ErrorKind::Other, "TBD"))) }, 82 Err(..) => { Err(Box::new(Error::new(ErrorKind::Other, "85"))) },
86 Ok(()) => Ok(()), 83 Ok(()) => Ok(()),
87 } 84 }
88 }, 85 },
diff --git a/src/commands/modification.rs b/src/commands/modification.rs
index 7836735..595b677 100644
--- a/src/commands/modification.rs
+++ b/src/commands/modification.rs
@@ -22,7 +22,7 @@ pub async fn modification(config: Cfg, args: Option<Vec<String>>) -> Result<(),
22} 22}
23 23
24async fn add(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>> { 24async fn add(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>> {
25 25 //TODO! DO NOT PANIC IF MOD IS ALREADY IN MODS DB
26 if args.is_empty() { return Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_FEW_ARGUMENTS"))); }; 26 if args.is_empty() { return Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_FEW_ARGUMENTS"))); };
27 27
28 let current_list = get_current_list(config.clone())?; 28 let current_list = get_current_list(config.clone())?;
diff --git a/src/commands/setup.rs b/src/commands/setup.rs
index 0940959..8c0fcfd 100644
--- a/src/commands/setup.rs
+++ b/src/commands/setup.rs
@@ -1,6 +1,6 @@
1use std::{fs::File, path::Path, io::{Error, ErrorKind}}; 1use std::{fs::File, path::Path, io::{Error, ErrorKind}};
2 2
3use crate::{config::Cfg, db::{db_setup, user_dbversion, create_dbversion, insert_column, get_lists, get_list, get_current_versions, insert_dl_link}, modrinth::get_raw_versions}; 3use crate::{config::Cfg, db::{db_setup, s_config_get_version, s_config_create_version, s_insert_column, lists_get_all_ids, lists_get, userlist_get_all_current_version_ids, s_userlist_update_download}, modrinth::get_raw_versions};
4 4
5pub async fn setup(config: Cfg) -> Result<(), Box<dyn std::error::Error>> { 5pub async fn setup(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
6 6
@@ -10,7 +10,7 @@ pub async fn setup(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
10 return create(config, db_file); 10 return create(config, db_file);
11 } 11 }
12 12
13 match user_dbversion(config.clone()) { 13 match s_config_get_version(config.clone()) {
14 Ok(ver) => { 14 Ok(ver) => {
15 match ver.as_str() { 15 match ver.as_str() {
16 _ => return Err(Box::new(Error::new(ErrorKind::Other, "UNKNOWN_VERSION"))) 16 _ => return Err(Box::new(Error::new(ErrorKind::Other, "UNKNOWN_VERSION")))
@@ -29,26 +29,25 @@ fn create(config: Cfg, db_file: String) -> Result<(), Box<dyn std::error::Error>
29} 29}
30 30
31async fn to_02(config: Cfg) -> Result<(), Box<dyn std::error::Error>> { 31async fn to_02(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
32 let lists = get_lists(config.clone())?; 32 let lists = lists_get_all_ids(config.clone())?;
33 33
34 for list in lists { 34 for list in lists {
35 println!("Updating {}", list); 35 println!("Updating {}", list);
36 insert_column(config.clone(), String::from(&list), String::from("current_download"), String::new())?; 36 s_insert_column(config.clone(), String::from(&list), String::from("current_download"), String::new())?;
37 37
38 let full_list = get_list(config.clone(), String::from(&list))?; 38 let full_list = lists_get(config.clone(), String::from(&list))?;
39 39
40 let versions = get_current_versions(config.clone(), full_list.clone())?; 40 let versions = userlist_get_all_current_version_ids(config.clone(), full_list.clone().id)?;
41 41
42 let raw_versions = get_raw_versions(String::from(&config.apis.modrinth), versions).await; 42 let raw_versions = get_raw_versions(String::from(&config.apis.modrinth), versions).await;
43 43
44 for ver in raw_versions { 44 for ver in raw_versions {
45 println!("Adding link for {}", ver.project_id); 45 println!("Adding link for {}", ver.project_id);
46 let file = ver.files.into_iter().find(|f| f.primary).unwrap(); 46 let file = ver.files.into_iter().find(|f| f.primary).unwrap();
47 insert_dl_link(config.clone(), full_list.clone(), ver.project_id, file.url)?; 47 s_userlist_update_download(config.clone(), String::from(&full_list.id), ver.project_id, file.url)?;
48 } 48 }
49 }; 49 };
50 create_dbversion(config)?; 50 s_config_create_version(config)?;
51
52 51
53 Ok(()) 52 Ok(())
54} 53}
diff --git a/src/commands/update.rs b/src/commands/update.rs
index d278a78..e383eae 100644
--- a/src/commands/update.rs
+++ b/src/commands/update.rs
@@ -4,7 +4,7 @@ use reqwest::Client;
4 4
5use futures_util::StreamExt; 5use futures_util::StreamExt;
6 6
7use crate::{config::Cfg, modrinth::{projects, Project, versions, extract_current_version, Version}, get_current_list, db::{userlist_get_all_ids, get_versions, get_list_version, change_list_versions}, List}; 7use crate::{config::Cfg, modrinth::{projects, Project, versions, extract_current_version, Version}, get_current_list, db::{userlist_get_all_ids, mods_get_versions, userlist_get_applicable_versions, userlist_change_versions}, List};
8 8
9pub async fn update(config: Cfg) -> Result<(), Box<dyn std::error::Error>> { 9pub async fn update(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
10 10
@@ -12,7 +12,7 @@ pub async fn update(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
12 12
13 let mods = userlist_get_all_ids(config.clone(), current_list.clone().id)?; 13 let mods = userlist_get_all_ids(config.clone(), current_list.clone().id)?;
14 14
15 let mut versions = get_versions(config.clone(), mods.clone())?; 15 let mut versions = mods_get_versions(config.clone(), mods.clone())?;
16 versions.sort_by_key(|ver| ver.mod_id.clone()); 16 versions.sort_by_key(|ver| ver.mod_id.clone());
17 17
18 let mut projects = projects(String::from(&config.apis.modrinth), mods).await; 18 let mut projects = projects(String::from(&config.apis.modrinth), mods).await;
@@ -54,12 +54,15 @@ async fn specific_update(config: Cfg, list: List, project: Project) -> Result<Ve
54 } 54 }
55 55
56 let mut current: Vec<Version> = vec![]; 56 let mut current: Vec<Version> = vec![];
57 if versions.join("|") != get_list_version(config.clone(), list.clone(), String::from(&project.id))? { 57 if versions.join("|") != userlist_get_applicable_versions(config.clone(), String::from(&list.id), String::from(&project.id))? {
58 //get new versions 58 //get new versions
59 print!(" | getting new version"); 59 print!(" | getting new version");
60 let current_str = extract_current_version(applicable_versions.clone())?; 60 let current_str = extract_current_version(applicable_versions.clone())?;
61 current.push(applicable_versions.into_iter().find(|ver| ver.id == current_str).unwrap()); 61 let current_ver = applicable_versions.into_iter().find(|ver| ver.id == current_str).ok_or("")?;
62 change_list_versions(config, list, current_str, versions, project.id)?; 62 current.push(current_ver.clone());
63
64 let link = current_ver.files.into_iter().find(|f| f.primary).ok_or("")?.url;
65 userlist_change_versions(config, list.id, current_str, versions.join("|"), link, project.id)?;
63 } 66 }
64 67
65 if current.is_empty() { return Err(Box::new(Error::new(ErrorKind::NotFound, "NO_UPDATE_AVAILABLE"))) }; 68 if current.is_empty() { return Err(Box::new(Error::new(ErrorKind::NotFound, "NO_UPDATE_AVAILABLE"))) };
diff --git a/src/db.rs b/src/db.rs
index 86e697e..5d82271 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -2,9 +2,9 @@ use std::io::{Error, ErrorKind};
2 2
3use rusqlite::Connection; 3use rusqlite::Connection;
4 4
5use crate::{Modloader, config::Cfg, List}; 5use crate::{Modloader, config::Cfg, List, get_modloader};
6 6
7//MODS 7//mods
8pub fn mods_insert(config: Cfg, id: String, name: String, versions: Vec<String>) -> Result<(), Box<dyn std::error::Error>> { 8pub fn mods_insert(config: Cfg, id: String, name: String, versions: Vec<String>) -> Result<(), Box<dyn std::error::Error>> {
9 9
10 println!("Inserting mod {}({}) into database", name, id); 10 println!("Inserting mod {}({}) into database", name, id);
@@ -75,6 +75,43 @@ pub fn mods_remove(config: Cfg, id: String) -> Result<(), Box<dyn std::error::Er
75 Ok(()) 75 Ok(())
76} 76}
77 77
78#[derive(Debug, Clone, PartialEq, Eq)]
79pub struct DBModlistVersions {
80 pub mod_id: String,
81 pub versions: String,
82}
83
84pub fn mods_get_versions(config: Cfg, mods: Vec<String>) -> Result<Vec<DBModlistVersions>, Box<dyn std::error::Error>> {
85 let data = format!("{}/data.db", config.data);
86 let connection = Connection::open(data)?;
87
88 if mods.is_empty() { return Err(Box::new(Error::new(ErrorKind::Other, "MODS_NO_INPUT"))); }
89
90 let mut wherestr = String::from("WHERE");
91 for (i, id) in mods.iter().enumerate() {
92 let mut or = " OR";
93 if i == mods.len() - 1 { or = "" };
94 wherestr = format!("{} id = '{}'{}", wherestr, id, or);
95 }
96
97 let mut versionmaps: Vec<DBModlistVersions> = Vec::new();
98 let mut stmt = connection.prepare(dbg!(format!("SELECT id, versions FROM mods {}", wherestr).as_str()))?;
99 let id_iter = stmt.query_map([], |row| {
100 Ok(vec![row.get::<usize, String>(0)?, row.get::<usize, String>(1)?])
101 })?;
102
103 for ver in id_iter {
104 let version = ver?;
105 println!("Found versions {} for mod {}", version[1], version[0]);
106 versionmaps.push(DBModlistVersions { mod_id: String::from(&version[0]), versions: String::from(&version[1]) })
107 };
108
109 match versionmaps.is_empty() {
110 true => Err(Box::new(Error::new(ErrorKind::NotFound, "MODS_MODS_NOT_FOUND"))),
111 false => Ok(versionmaps),
112 }
113}
114
78//userlist 115//userlist
79pub 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>> { 116pub 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>> {
80 println!("Inserting {} into current list({})", mod_id, list_id); 117 println!("Inserting {} into current list({})", mod_id, list_id);
@@ -119,69 +156,74 @@ pub fn userlist_remove(config: Cfg, list_id: String, mod_id: String) -> Result<(
119} 156}
120 157
121 158
122#[derive(Debug, Clone)] 159pub fn userlist_get_applicable_versions(config: Cfg, list_id: String, mod_id: String) -> Result<String, Box<dyn std::error::Error>> {
123pub struct DBModlistVersions {
124 pub mod_id: String,
125 pub versions: String,
126}
127
128pub fn get_versions(config: Cfg, mods: Vec<String>) -> Result<Vec<DBModlistVersions>, Box<dyn std::error::Error>> {
129 /*
130 let data = format!("{}/data.db", config.data); 160 let data = format!("{}/data.db", config.data);
131 let connection = sqlite::open(data).unwrap(); 161 let connection = Connection::open(data).unwrap();
132 162
133 let mut wherestr = String::from("WHERE"); 163 let mut version: String = String::new();
134 for (i, id) in mods.iter().enumerate() { 164 let mut stmt = connection.prepare(format!("SELECT applicable_versions FROM {} WHERE mod_id = ?", list_id).as_str())?;
135 let mut or = " OR"; 165 let ver_iter = stmt.query_map([mod_id], |row| {
136 if i == mods.len() - 1 { or = "" } 166 row.get::<usize, String>(0)
137 println!("Pushing {}({}) | OR: '{}'", id, i, or); 167 })?;
138 wherestr = format!("{} id = '{}'{}", wherestr, id, or);
139 }
140 168
141 let sql = format!("SELECT id, versions FROM mods {}", wherestr); 169 for ver in ver_iter {
170 println!("Found id {:?}", ver);
171 version = ver?;
172 };
142 173
143 dbg!(&sql); 174 match version.is_empty() {
175 true => Err(Box::new(Error::new(ErrorKind::NotFound, "MOD_NOT_FOUND"))),
176 false => Ok(version),
177 }
178}
144 179
145 let mut versionmaps: Vec<DBModlistVersions> = Vec::new(); 180pub fn userlist_get_all_current_version_ids(config: Cfg, list_id: String) -> Result<Vec<String>, Box<dyn std::error::Error>> {
146 //TODO catch sql errors better 181 let data = format!("{}/data.db", config.data);
147 let mut cursor = connection.prepare(sql).unwrap().into_cursor(); 182 let connection = Connection::open(data)?;
148 183
149 while let Some(Ok(row)) = cursor.next() { 184 let mut versions: Vec<String> = Vec::new();
150 println!("{}: {}", row.get::<String, _>(0), row.get::<String, _>(1)); 185 let mut stmt = connection.prepare(format!("SELECT current_version FROM {}", list_id).as_str())?;
151 versionmaps.push(DBModlistVersions { mod_id: row.get::<String, _>(0), versions: row.get::<String, _>(1) }) 186 let id_iter = stmt.query_map([], |row| {
187 row.get::<usize, String>(0)
188 })?;
189
190 for id in id_iter {
191 versions.push(id?);
152 }; 192 };
153 193
154 if versionmaps.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; 194 if versions.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); };
155 195
156 Ok(versionmaps) 196 Ok(versions)
157 */
158 Ok(vec![DBModlistVersions { mod_id: String::new(), versions: String::new() }])
159} 197}
160 198
161pub fn get_list_version(config: Cfg, list: List, mod_id: String) -> Result<String, Box<dyn std::error::Error>> { 199pub fn userlist_change_versions(config: Cfg, list_id: String, current_version: String, versions: String, link: String, mod_id: String) -> Result<(), Box<dyn std::error::Error>> {
162 /*
163 let data = format!("{}/data.db", config.data); 200 let data = format!("{}/data.db", config.data);
164 let connection = sqlite::open(data).unwrap(); 201 let connection = Connection::open(data)?;
165
166 let sql = format!("SELECT applicable_versions FROM {} WHERE mod_id = '{}'", list.id, mod_id);
167
168 //TODO catch sql errors better
169 let mut version: String = String::new();
170 connection.iterate(sql, |ver| {
171 if ver.is_empty() { return false; };
172 for &(_column, value) in ver.iter() {
173 version = String::from(value.unwrap());
174 }
175 true
176 }).unwrap();
177
178 if version.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); };
179 202
180 Ok(version) 203 connection.execute(format!("UPDATE {} SET current_version = ?1, applicable_versions = ?2, current_download = ?3 WHERE mod_id = ?4", list_id).as_str(), [current_version, versions, link, mod_id])?;
181 */ 204 Ok(())
182 Ok(String::new())
183} 205}
184 206
207pub fn userlist_get_all_downloads(config: Cfg, list_id: String) -> Result<Vec<String>, Box<dyn std::error::Error>> {
208 let data = format!("{}/data.db", config.data);
209 let connection = Connection::open(data).unwrap();
210
211 let mut links: Vec<String> = Vec::new();
212 let mut stmt = connection.prepare(format!("SELECT current_download FROM {}", list_id).as_str())?;
213 let link_iter = stmt.query_map([], |row| {
214 row.get::<usize, String>(0)
215 })?;
216
217 for link in link_iter {
218 let l = link?;
219 println!("Found link {}", String::from(&l));
220 links.push(l)
221 };
222
223 if links.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); };
224
225 Ok(links)
226}
185 227
186//lists 228//lists
187pub fn lists_insert(config: Cfg, id: String, mc_version: String, mod_loader: Modloader) -> Result<(), Box<dyn std::error::Error>> { 229pub fn lists_insert(config: Cfg, id: String, mc_version: String, mod_loader: Modloader) -> Result<(), Box<dyn std::error::Error>> {
@@ -196,222 +238,134 @@ pub fn lists_insert(config: Cfg, id: String, mc_version: String, mod_loader: Mod
196 Ok(()) 238 Ok(())
197} 239}
198 240
199pub fn remove_list(config: Cfg, id: String) -> Result<(), Box<dyn std::error::Error>> { 241pub fn lists_remove(config: Cfg, id: String) -> Result<(), Box<dyn std::error::Error>> {
200 /*
201 let data = format!("{}/data.db", config.data); 242 let data = format!("{}/data.db", config.data);
202 let connection = sqlite::open(data).unwrap(); 243 let connection = Connection::open(data)?;
203
204 let sql_list = format!("DELETE FROM lists WHERE id = '{}'", id);
205 let sql_table = format!("DROP TABLE '{}'", id);
206 let sql = format!("{};{};", sql_list, sql_table);
207 244
208 connection.execute(sql) 245 connection.execute("DELETE FROM lists WHERE id = ?", [&id])?;
209 */ 246 connection.execute(format!("DROP TABLE {}", id).as_str(), [])?;
210 Ok(()) 247 Ok(())
211} 248}
212 249
213pub fn get_lists(config: Cfg) -> Result<Vec<String>, Box<dyn std::error::Error>> { 250pub fn lists_get(config: Cfg, list_id: String) -> Result<List, Box<dyn std::error::Error>> {
214 /*
215 let data = format!("{}/data.db", config.data); 251 let data = format!("{}/data.db", config.data);
216 let connection = sqlite::open(data).unwrap(); 252 let connection = Connection::open(data).unwrap();
217
218 let sql = "SELECT id FROM lists";
219
220 let mut list: Vec<String> = Vec::new();
221 //TODO catch sql errors better
222 connection.iterate(sql, |ids| {
223 if ids.is_empty() { return false; };
224 for &(_column, value) in ids.iter() {
225 list.push(String::from(value.unwrap()));
226 }
227 true
228 }).unwrap();
229 match list.is_empty() {
230 true => Err(Box::new(std::io::Error::new(ErrorKind::NotFound, "NO_LISTS"))),
231 false => Ok(list),
232 }
233 */
234 Ok(vec![String::new()])
235}
236
237pub fn get_current_versions(config: Cfg, list: List) -> Result<Vec<String>, Box<std::io::Error>> {
238 /*
239 let data = format!("{}/data.db", config.data);
240 let connection = sqlite::open(data).unwrap();
241
242 let sql = format!("SELECT current_version FROM {}", list.id);
243 253
244 dbg!(&sql); 254 let mut list = List { id: String::new(), mc_version: String::new(), modloader: Modloader::Fabric };
255 let mut stmt = connection.prepare("SELECT mc_version, modloader FROM lists WHERE id = ?")?;
245 256
246 let mut versions: Vec<String> = Vec::new(); 257 let list_iter = stmt.query_map([&list_id], |row| {
247 //TODO catch sql errors better 258 Ok(vec![row.get::<usize, String>(0)?, row.get::<usize, String>(1)?])
248 let mut cursor = connection.prepare(sql).unwrap().into_cursor(); 259 })?;
249 260
250 while let Some(Ok(row)) = cursor.next() { 261 for l in list_iter {
251 versions.push(row.get::<String, _>(0)); 262 let li = l?;
263 list = List { id: String::from(&list_id), mc_version: String::from(&li[0]), modloader: get_modloader(String::from(&li[1]))? };
252 }; 264 };
253 265
254 if versions.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; 266 if list.id.is_empty() { return Err(Box::new(Error::new(ErrorKind::Other, "LIST_NOT_FOUND"))); }
255
256 Ok(versions)
257 */
258 Ok(vec![String::new()])
259}
260
261pub fn get_list(config: Cfg, id: String) -> Result<List, Box<dyn std::error::Error>> {
262 /*
263 let data = format!("{}/data.db", config.data);
264 let connection = sqlite::open(data).unwrap();
265
266 let sql = format!("SELECT mc_version, modloader FROM lists WHERE id = '{}'", id);
267 267
268 let mut list = vec![]; 268 Ok(list)
269 //TODO catch sql errors better
270 connection.iterate(sql, |ids| {
271 if ids.is_empty() { return false; };
272 for &(_column, value) in ids.iter() {
273 list.push(String::from(value.unwrap()));
274 }
275 true
276 }).unwrap();
277
278 if list.len() != 2 { return Err(Box::new(std::io::Error::new(ErrorKind::InvalidData, "LIST_MISSING_DATA"))) };
279
280 Ok(List { id, mc_version: String::from(&list[0]), modloader: get_modloader(String::from(&list[1]))? })
281 */
282 Ok(List { id: String::new(), mc_version: String::new(), modloader: Modloader::Fabric })
283} 269}
284 270
285pub fn change_list_versions(config: Cfg, list: List, current_version: String, versions: Vec<String>, mod_id: String) -> Result<(), Box<dyn std::error::Error>> { 271pub fn lists_get_all_ids(config: Cfg) -> Result<Vec<String>, Box<dyn std::error::Error>> {
286 /*
287 let data = format!("{}/data.db", config.data); 272 let data = format!("{}/data.db", config.data);
288 let connection = sqlite::open(data).unwrap(); 273 let connection = Connection::open(data).unwrap();
274
275 let mut list_ids: Vec<String> = Vec::new();
276 let mut stmt = connection.prepare("SELECT id FROM lists")?;
277 let id_iter = stmt.query_map([], |row| {
278 row.get::<usize, String>(0)
279 })?;
289 280
290 let sql = format!("UPDATE {} SET current_version = '{}', applicable_versions = '{}' WHERE mod_id = '{}'", list.id, current_version, versions.join("|"), mod_id); 281 for id in id_iter {
282 println!("Found id {:?}", id.as_ref().unwrap());
283 list_ids.push(id?)
284 };
291 285
292 connection.execute(sql) 286 match list_ids.is_empty() {
293 */ 287 true => Err(Box::new(std::io::Error::new(ErrorKind::NotFound, "NO_LISTS"))),
294 Ok(()) 288 false => Ok(list_ids),
289 }
295} 290}
296 291
297//DOWNLOAD 292//config
298 293pub fn config_change_current_list(config: Cfg, id: String) -> Result<(), Box<dyn std::error::Error>> {
299pub fn insert_dl_link(config: Cfg, list: List, mod_id: String, link: String) -> Result<(), Box<dyn std::error::Error>> {
300 /*
301 let data = format!("{}/data.db", config.data); 294 let data = format!("{}/data.db", config.data);
302 let connection = sqlite::open(data).unwrap(); 295 let connection = Connection::open(data)?;
303
304 let sql = format!("UPDATE {} SET current_download = '{}' WHERE mod_id = '{}'", list.id, link, mod_id);
305 296
306 connection.execute(sql) 297 connection.execute("UPDATE user_config SET value = ? WHERE id = 'current_list'", [id])?;
307 */
308 Ok(()) 298 Ok(())
309} 299}
310 300
311pub fn get_dl_links(config: Cfg, list: List) -> Result<Vec<String>, Box<std::io::Error>> { 301pub fn config_get_current_list(config: Cfg) -> Result<String, Box<dyn std::error::Error>> {
312 /*
313 let data = format!("{}/data.db", config.data); 302 let data = format!("{}/data.db", config.data);
314 let connection = sqlite::open(data).unwrap(); 303 let connection = Connection::open(data).unwrap();
315 304
316 let sql = format!("SELECT current_download FROM {}", list.id); 305 let mut list_id = String::new();
317 306 let mut stmt = connection.prepare("SELECT value FROM user_config WHERE id = 'current_list'")?;
318 dbg!(&sql); 307 let list_iter = stmt.query_map([], |row| {
319 308 row.get::<usize, String>(0)
320 let mut links: Vec<String> = Vec::new(); 309 })?;
321 //TODO catch sql errors better
322 let mut cursor = connection.prepare(sql).unwrap().into_cursor();
323 310
324 while let Some(Ok(row)) = cursor.next() { 311 for list in list_iter {
325 links.push(row.get::<String, _>(0)); 312 list_id = list?;
326 }; 313 };
327 314
328 if links.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; 315 if list_id.is_empty() { return Err(Box::new(Error::new(ErrorKind::Other, "NO_CURRENT_LIST"))); }
329 316
330 Ok(links) 317 Ok(list_id)
331 */
332 Ok(vec![String::new()])
333} 318}
334 319
335//config 320//SETUP(UPDATES)
336pub fn change_list(config: Cfg, id: String) -> Result<(), Box<dyn std::error::Error>> { 321pub fn s_userlist_update_download(config: Cfg, list_id: String, mod_id: String, link: String) -> Result<(), Box<dyn std::error::Error>> {
337 /*
338 let data = format!("{}/data.db", config.data); 322 let data = format!("{}/data.db", config.data);
339 let connection = sqlite::open(data).unwrap(); 323 let connection = Connection::open(data)?;
340
341 let sql = format!("UPDATE user_config SET value = '{}' WHERE id = 'current_list'", id);
342 324
343 connection.execute(sql) 325 connection.execute(format!("UPDATE {} SET current_download = ?1 WHERE mod_id = ?2", list_id).as_str(), [link, mod_id])?;
344 */
345 Ok(()) 326 Ok(())
346} 327}
347 328
348pub fn get_current_list_id(config: Cfg) -> Result<String, Box<dyn std::error::Error>> { 329pub fn s_config_create_version(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
349 /*
350 let data = format!("{}/data.db", config.data); 330 let data = format!("{}/data.db", config.data);
351 let connection = sqlite::open(data).unwrap(); 331 let connection = Connection::open(data)?;
352 332
353 let sql = "SELECT id FROM lists"; 333 connection.execute("INSERT INTO 'user_config' VALUES ( 'db_version', '0.2' )", ())?;
354 334 Ok(())
355 let mut list: String = String::new();
356 //TODO catch sql errors better
357 connection.iterate(sql, |ids| {
358 if ids.is_empty() { return false; };
359 for &(_column, value) in ids.iter() {
360 list = String::from(value.unwrap());
361 }
362 true
363 }).unwrap();
364 if list.is_empty() {
365 get_lists(config)?;
366 panic!("current list field should never be empty if there are other lists");
367 };
368 Ok(list)
369 */
370 Ok(String::new())
371} 335}
372 336
373pub fn update_dbversion(config: Cfg, ver: String) -> Result<(), Box<dyn std::error::Error>> { 337pub fn s_config_update_version(config: Cfg, ver: String) -> Result<(), Box<dyn std::error::Error>> {
374 /*
375 let data = format!("{}/data.db", config.data); 338 let data = format!("{}/data.db", config.data);
376 let connection = sqlite::open(data).unwrap(); 339 let connection = Connection::open(data)?;
377
378 let sql = format!("UPDATE user_config SET value = '{}' WHERE id = 'db_version'", ver);
379 340
380 connection.execute(sql) 341 connection.execute("UPDATE user_config SET value = ? WHERE id = 'db_version'", [ver])?;
381 */
382 Ok(()) 342 Ok(())
383} 343}
384 344
385pub fn create_dbversion(config: Cfg) -> Result<(), Box<dyn std::error::Error>> { 345pub fn s_config_get_version(config: Cfg) -> Result<String, Box<dyn std::error::Error>> {
386 /*
387 let data = format!("{}/data.db", config.data); 346 let data = format!("{}/data.db", config.data);
388 let connection = sqlite::open(data).unwrap(); 347 let connection = Connection::open(data)?;
389 let sql = "INSERT INTO 'user_config' VALUES ( 'db_version', '0.2' );"; 348
390 connection.execute(sql) 349 let mut version: String = String::new();
391 */ 350 let mut stmt = connection.prepare("SELECT value FROM user_config WHERE id = 'db_version'")?;
392 Ok(()) 351 let ver_iter = stmt.query_map([], |row| {
352 row.get::<usize, String>(0)
353 })?;
354
355 for ver in ver_iter {
356 version = ver?;
357 };
358
359 if version.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_DBVERSION"))); };
360 Ok(version)
393} 361}
394 362
395pub fn user_dbversion(config: Cfg) -> Result<String, Box<dyn std::error::Error>> { 363pub fn s_insert_column(config: Cfg, table: String, column: String, c_type: String) -> Result<(), Box<dyn std::error::Error>> {
396 /*
397 let data = format!("{}/data.db", config.data); 364 let data = format!("{}/data.db", config.data);
398 let connection = sqlite::open(data).unwrap(); 365 let connection = Connection::open(data)?;
399 366
400 let sql = "SELECT db_version FROM user_config"; 367 connection.execute(format!("ALTER TABLE {} ADD '{}' {}", table, column, c_type).as_str(), ())?;
401 368 Ok(())
402 let mut ver: String = String::new();
403 //TODO catch sql errors better
404 connection.iterate(sql, |ids| {
405 if ids.is_empty() { return false; };
406 for &(_column, value) in ids.iter() {
407 ver = String::from(value.unwrap());
408 }
409 true
410 })?;
411 if ver.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_DBVERSION"))); };
412 Ok(ver)
413 */
414 Ok(String::from("0.2"))
415} 369}
416 370
417pub fn db_setup(config: Cfg) -> Result<(), Box<dyn std::error::Error>> { 371pub fn db_setup(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
@@ -432,21 +386,3 @@ pub fn db_setup(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
432 Ok(()) 386 Ok(())
433} 387}
434 388
435pub fn insert_column(config: Cfg, table: String, column: String, c_type: String) -> Result<(), Box<dyn std::error::Error>> {
436 /*
437 let data = format!("{}/data.db", config.data);
438 let connection = sqlite::open(data).unwrap();
439
440 let ct = match c_type {
441 sqlite::Type::Null => "NULL",
442 sqlite::Type::Float => "FLOAT",
443 sqlite::Type::Binary => "BINARY",
444 sqlite::Type::String => "TEXT",
445 sqlite::Type::Integer => "INT",
446 };
447
448 let sql = format!("ALTER TABLE {} ADD '{}' {}", table, column, ct);
449 connection.execute(sql)
450 */
451 Ok(())
452}
diff --git a/src/lib.rs b/src/lib.rs
index e059293..1e7ebbf 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,7 +9,7 @@ use std::io::{Error, ErrorKind};
9pub use apis::*; 9pub use apis::*;
10pub use commands::*; 10pub use commands::*;
11 11
12#[derive(Debug, Clone)] 12#[derive(Debug, Clone, PartialEq, Eq)]
13pub enum Modloader { 13pub enum Modloader {
14 Fabric, 14 Fabric,
15 Forge 15 Forge