2026-08-25 12:04:07 +03:00
|
|
|
use crate::helpers::into_result;
|
2026-08-23 21:49:01 +03:00
|
|
|
use crate::notification::NotificationData;
|
2026-08-25 12:04:07 +03:00
|
|
|
use crate::notification::NotificationData::IncorrectAnkiFile;
|
2026-08-23 22:48:00 +03:00
|
|
|
use log::info;
|
2026-08-14 23:52:48 +03:00
|
|
|
use rusqlite::Connection;
|
2026-08-14 11:17:22 +03:00
|
|
|
use serde_json::Value;
|
2026-09-09 15:00:52 +03:00
|
|
|
use std::collections::BTreeMap;
|
2026-08-14 11:17:22 +03:00
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
2026-08-14 23:03:15 +03:00
|
|
|
pub struct ImportData(pub(crate) Vec<ImportGroup>);
|
2026-08-14 11:17:22 +03:00
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct ImportGroup {
|
2026-08-14 23:03:15 +03:00
|
|
|
pub id: u64,
|
|
|
|
|
pub name: String,
|
|
|
|
|
pub fields: Vec<String>,
|
|
|
|
|
pub length: u64,
|
2026-09-09 12:12:44 +03:00
|
|
|
pub mapping: BTreeMap<String, String>,
|
2026-08-15 21:32:24 +03:00
|
|
|
pub imported: bool,
|
2026-08-14 11:17:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct ImportNote {
|
2026-08-14 23:03:15 +03:00
|
|
|
pub tags: String,
|
|
|
|
|
pub fields: Vec<String>,
|
2026-08-14 11:17:22 +03:00
|
|
|
}
|
|
|
|
|
|
2026-08-23 21:49:01 +03:00
|
|
|
pub fn load_groups(connection: &Connection) -> Result<ImportData, NotificationData> {
|
2026-08-14 11:17:22 +03:00
|
|
|
let json_models: String = connection
|
|
|
|
|
.query_one("select models from col", (), |row| row.get(0))
|
2026-08-24 23:42:58 +03:00
|
|
|
.map_err(|_| IncorrectAnkiFile)?;
|
2026-08-25 12:04:07 +03:00
|
|
|
let raw: Value = serde_json::from_str(json_models.as_str()).map_err(|_| IncorrectAnkiFile)?;
|
2026-08-23 21:49:01 +03:00
|
|
|
let sets = raw.as_object();
|
|
|
|
|
if let Some(sets) = sets {
|
|
|
|
|
let mut total_data = ImportData(vec![]);
|
2026-08-14 11:17:22 +03:00
|
|
|
|
2026-08-23 21:49:01 +03:00
|
|
|
let mut count_stmt = connection
|
|
|
|
|
.prepare("select mid, count(id) from notes group by mid")
|
2026-08-24 23:42:58 +03:00
|
|
|
.map_err(|_| IncorrectAnkiFile)?;
|
2026-08-14 23:03:15 +03:00
|
|
|
|
2026-08-23 21:49:01 +03:00
|
|
|
let counts = count_stmt
|
|
|
|
|
.query_map([], |row| Ok((row.get(0)?, row.get(1)?)))
|
2026-08-24 23:42:58 +03:00
|
|
|
.map_err(|_| IncorrectAnkiFile)?
|
2026-08-24 23:10:23 +03:00
|
|
|
.filter_map(|x| x.ok())
|
2026-08-23 21:49:01 +03:00
|
|
|
.collect::<Vec<(i64, i64)>>();
|
2026-08-14 23:03:15 +03:00
|
|
|
|
2026-08-23 21:49:01 +03:00
|
|
|
for (_, collection) in sets {
|
2026-09-09 10:53:03 +03:00
|
|
|
let fields_property = collection.get("flds");
|
2026-08-23 21:49:01 +03:00
|
|
|
if let Some(fields_property) = fields_property {
|
2026-08-25 12:04:07 +03:00
|
|
|
let fields = into_result(fields_property.as_array(), IncorrectAnkiFile)?
|
2026-08-23 21:49:01 +03:00
|
|
|
.iter()
|
|
|
|
|
.filter_map(|x| x.get("name"))
|
|
|
|
|
.map(|x| x.as_str().unwrap().to_string())
|
|
|
|
|
.collect();
|
|
|
|
|
let id = collection.get("id");
|
2026-08-25 12:04:07 +03:00
|
|
|
if id.is_none() || id.unwrap().as_u64().is_none() {
|
2026-08-24 23:42:58 +03:00
|
|
|
return Err(IncorrectAnkiFile);
|
2026-08-23 21:49:01 +03:00
|
|
|
}
|
|
|
|
|
let id = id.unwrap().as_u64().unwrap();
|
|
|
|
|
let name = collection.get("name");
|
2026-08-24 23:10:23 +03:00
|
|
|
if name.is_none() || name.unwrap().as_str().is_none() {
|
2026-08-24 23:42:58 +03:00
|
|
|
return Err(IncorrectAnkiFile);
|
2026-08-23 21:49:01 +03:00
|
|
|
}
|
|
|
|
|
let name = name.unwrap().as_str().unwrap().to_string();
|
2026-08-23 22:48:00 +03:00
|
|
|
|
2026-08-23 21:49:01 +03:00
|
|
|
let mut group = ImportGroup {
|
|
|
|
|
id,
|
|
|
|
|
name,
|
|
|
|
|
fields,
|
|
|
|
|
mapping: Default::default(),
|
|
|
|
|
length: 0,
|
|
|
|
|
imported: false,
|
|
|
|
|
};
|
|
|
|
|
if let Some((_, count)) = counts.iter().find(|(id, _)| *id == group.id as i64) {
|
|
|
|
|
group.length = *count as u64
|
|
|
|
|
}
|
2026-08-23 22:48:00 +03:00
|
|
|
info!("{:?}", group);
|
2026-08-23 21:49:01 +03:00
|
|
|
total_data.0.push(group);
|
2026-08-20 18:53:13 +03:00
|
|
|
}
|
2026-08-14 23:03:15 +03:00
|
|
|
}
|
2026-08-25 12:04:07 +03:00
|
|
|
return Ok(total_data);
|
2026-08-14 11:17:22 +03:00
|
|
|
}
|
2026-08-24 23:42:58 +03:00
|
|
|
Err(IncorrectAnkiFile)
|
2026-08-14 11:17:22 +03:00
|
|
|
}
|
2026-08-14 23:03:15 +03:00
|
|
|
|
2026-08-25 12:04:07 +03:00
|
|
|
pub fn get_words_of_group(
|
|
|
|
|
connection: &Connection,
|
|
|
|
|
group_id: u64,
|
|
|
|
|
) -> Result<Vec<ImportNote>, NotificationData> {
|
2026-08-14 23:03:15 +03:00
|
|
|
let mut count_stmt = connection
|
|
|
|
|
.prepare("select tags, flds from notes where mid == ?1;")
|
2026-08-24 23:42:58 +03:00
|
|
|
.map_err(|_| IncorrectAnkiFile)?;
|
2026-08-14 23:03:15 +03:00
|
|
|
|
2026-08-23 21:49:01 +03:00
|
|
|
Ok(count_stmt
|
2026-08-15 21:32:24 +03:00
|
|
|
.query_map((group_id as i64,), |row| {
|
|
|
|
|
Ok(ImportNote {
|
|
|
|
|
tags: row.get(0)?,
|
|
|
|
|
fields: row
|
|
|
|
|
.get::<usize, String>(1)?
|
|
|
|
|
.split('')
|
|
|
|
|
.map(|x| x.to_string())
|
|
|
|
|
.collect(),
|
|
|
|
|
})
|
2026-08-14 23:03:15 +03:00
|
|
|
})
|
2026-08-24 23:42:58 +03:00
|
|
|
.map_err(|_| IncorrectAnkiFile)?
|
2026-08-24 23:10:23 +03:00
|
|
|
.filter_map(|x| x.ok())
|
2026-08-23 21:49:01 +03:00
|
|
|
.collect::<Vec<ImportNote>>())
|
2026-08-14 23:03:15 +03:00
|
|
|
}
|