Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests and refactor #8

Merged
merged 3 commits into from
Aug 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions .idea/balalib.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions .idea/discord.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

72 changes: 13 additions & 59 deletions src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,7 @@ use std::process::Command;

pub fn need_update(lua: &Lua, _: ()) -> LuaResult<bool> {
let current_version = lua.load("require('balamod_version')").eval::<String>()?;
let client = reqwest::blocking::Client::builder()
.user_agent("balamod_lua")
.build()
.unwrap();

match client
.get("https://api.github.com/repos/balamod/balamod_lua/releases")
.send()
{
Ok(response) => match response.text() {
Ok(text) => {
let releases: Vec<serde_json::Value> = serde_json::from_str(&text)
.unwrap_or_else(|_| panic!("Failed to parse json: {}", text));
let latest_version = releases
.iter()
.find(|release| {
!release["prerelease"].as_bool().unwrap()
&& !release["draft"].as_bool().unwrap()
})
.unwrap()["tag_name"]
.as_str()
.unwrap();
Ok(current_version != latest_version)
}
Err(_) => Ok(false),
},
Err(_) => Ok(false),
}
super::updater::need_update(current_version)
}

fn lua_value_to_json_value(value: &Value) -> JsonValue {
Expand All @@ -54,16 +27,18 @@ fn lua_value_to_json_value(value: &Value) -> JsonValue {
fn table_to_json_value(table: &Table) -> JsonValue {
let mut map = serde_json::Map::new();
let table_clone = table.clone();
for (key, value) in table_clone.pairs::<Value, Value>().flatten() {
if let Value::String(k) = key {
map.insert(
k.to_str().unwrap().to_string(),
lua_value_to_json_value(&value),
);
} else if let Value::Integer(k) = key {
map.insert(k.to_string(), lua_value_to_json_value(&value));
} else if let Value::Number(k) = key {
map.insert(k.to_string(), lua_value_to_json_value(&value));
for pair in table_clone.pairs::<Value, Value>() {
if let Ok((key, value)) = pair {
if let Value::String(k) = key {
map.insert(
k.to_str().unwrap().to_string(),
lua_value_to_json_value(&value),
);
} else if let Value::Integer(k) = key {
map.insert(k.to_string(), lua_value_to_json_value(&value));
} else if let Value::Number(k) = key {
map.insert(k.to_string(), lua_value_to_json_value(&value));
}
}
}
JsonValue::Object(map)
Expand Down Expand Up @@ -140,27 +115,6 @@ pub fn is_mod_present(lua: &Lua, mod_info: ModInfo) -> LuaResult<bool> {
Ok(Path::new(&main_path).exists())
}

#[cfg(target_os = "windows")]
pub fn self_update(cli_ver: &str) -> LuaResult<()> {
let url = format!(
"https://github.com/balamod/balamod/releases/download/{}/balamod-{}-windows.exe",
cli_ver, cli_ver
);
let client = reqwest::blocking::Client::builder()
.user_agent("balalib")
.build()
.unwrap();
let mut response = client.get(&url).send().unwrap();
let mut file = std::fs::File::create("balamod.exe").unwrap();
std::io::copy(&mut response, &mut file).unwrap();
restart()?
}

#[cfg(any(target_os = "macos", target_os = "linux"))]
pub fn self_update(_cli_ver: &str) -> LuaResult<()> {
Ok(())
}

#[cfg(target_os = "windows")]
pub fn restart() -> LuaResult<()> {
let exe_path = env::current_exe()?;
Expand Down
13 changes: 6 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
use crate::core::{
inject, is_mod_present, json_to_lua, lua_to_json, need_update, restart, self_update,
setup_injection,
inject, is_mod_present, json_to_lua, lua_to_json, need_update, restart, setup_injection,
};
use mlua::prelude::*;
use mlua::Value;

use crate::mods::*;
use crate::updater::self_update;

mod core;
mod mods;
mod tests;
mod updater;
mod utils;

const VERSION: &str = env!("CARGO_PKG_VERSION");
Expand All @@ -21,13 +23,10 @@ fn echo(_: &Lua, name: String) -> LuaResult<String> {
fn balalib(lua: &Lua) -> LuaResult<LuaTable> {
let exports = lua.create_table()?;
exports.set("echo", lua.create_function(echo)?)?;
exports.set(
"fetch_mods",
lua.create_function(|lua, ()| fetch_mods(lua, ()))?,
)?;
exports.set("fetch_mods", lua.create_function(|_, ()| fetch_mods())?)?;
exports.set(
"get_local_mods",
lua.create_function(|lua, ()| get_local_mods(lua, ()))?,
lua.create_function(|lua, ()| get_local_mods(lua))?,
)?;
exports.set(
"need_update",
Expand Down
133 changes: 24 additions & 109 deletions src/mods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use jsonschema::JSONSchema;
use mlua::prelude::{LuaError, LuaResult, LuaValue};
use mlua::{FromLua, IntoLua, Lua};
use serde::{Deserialize, Serialize};
use serde_json::json;

#[derive(Debug, Clone)]
pub struct ModInfo {
Expand Down Expand Up @@ -72,7 +71,7 @@ pub fn download_mod(lua: &Lua, mod_info: ModInfo) -> LuaResult<()> {
let mod_dir = format!("{}/{}", mods_dir, id);
std::fs::create_dir_all(&mod_dir)?;
let tar = body.to_vec();
unpack_tar(&mod_dir, tar.clone()).unwrap_or_else(|_| panic!("Failed to unpack tar: {}", url));
unpack_tar(&mod_dir, tar.clone()).expect(format!("Failed to unpack tar: {}", url).as_str());
Ok(())
}

Expand All @@ -83,7 +82,7 @@ pub fn unpack_tar(dir: &str, tar: Vec<u8>) -> Result<(), Box<dyn std::error::Err
Ok(())
}

pub fn fetch_mods(_: &Lua, _: ()) -> LuaResult<Vec<ModInfo>> {
pub fn fetch_mods() -> LuaResult<Vec<ModInfo>> {
let client = reqwest::blocking::Client::new();
match client
.get("https://raw.githubusercontent.com/balamod/balamod/master/new_repos.index")
Expand Down Expand Up @@ -144,101 +143,10 @@ fn get_mods_from_repo(repo_url: String) -> Result<Vec<ModInfo>, reqwest::Error>
Ok(mod_infos)
}

pub fn get_local_mods(lua: &Lua, _: ()) -> LuaResult<Vec<LocalMod>> {
let schema = json!({
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
},
"versionConstraint": {
"type": "string",
"pattern": "^(\\^|>|>=|<|<=)? ?[0-9]+(\\.[0-9]+(\\.[0-9]+)?)?(, ?(>|>=|<|<=)? ?[0-9]+(\\.[0-9]+(\\.[0-9]+)?)?)?$"
},
"id": {
"type": "string",
"pattern": "[a-z0-9_\\-]+"
},
"authorName": {
"type": "string",
"pattern": "[A-Za-z0-9]+( <.+@[a-z0-9]+\\.[a-z\\.]{3,}>)?"
}
},
"type": "object",
"required": [
"id",
"name",
"version",
"description",
"author",
"load_before",
"load_after"
],
"properties": {
"id": {
"$ref": "#/$defs/id"
},
"name": {
"type": "string"
},
"version": {
"$ref": "#/$defs/version"
},
"description": {
"type": "array",
"items": {
"type": "string",
"maxLength": 50
}
},
"author": {
"oneOf": [
{
"$ref": "#/$defs/authorName"
},
{
"type": "array",
"items": {
"$ref": "#/$defs/authorName"
}
}
]
},
"load_before": {
"type": "array",
"items": {
"$ref": "#/$defs/version"
}
},
"load_after": {
"type": "array",
"items": {
"$ref": "#/$defs/version"
}
},
"min_balamod_version": {
"$ref": "#/$defs/version"
},
"max_balamod_version": {
"$ref": "#/$defs/version"
},
"balalib_version": {
"$ref": "#/$defs/versionConstraint"
},
"dependencies": {
"type": "object",
"patternProperties": {
"^[a-z0-9_\\-]+$": {
"$ref": "#/$defs/versionConstraint"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
});
let compiled_schema = JSONSchema::compile(&schema).expect("A valid schema");
pub fn get_local_mods(lua: &Lua) -> LuaResult<Vec<LocalMod>> {
let schema = include_bytes!("schema/manifest.schema.json");
let schema: serde_json::Value = serde_json::from_slice(schema).expect("Invalid schema");
let compiled_schema = JSONSchema::compile(&schema).expect("Invalid schema");

let love_dir = get_love_dir(lua)?;
let mods_dir = format!("{}/mods", love_dir);
Expand Down Expand Up @@ -280,8 +188,8 @@ pub fn get_local_mods(lua: &Lua, _: ()) -> LuaResult<Vec<LocalMod>> {

let mut manifest: LocalMod = serde_json::from_str(&manifest).unwrap();

if let Some(balalib_version) = manifest.clone().balalib_version {
match balalib_version.chars().next().unwrap() {
match manifest.clone().balalib_version {
Some(balalib_version) => match balalib_version.chars().next().unwrap() {
'>' => {
let balalib_version = balalib_version.split(">").nth(1).unwrap();
if balalib_version <= VERSION {
Expand All @@ -304,21 +212,28 @@ pub fn get_local_mods(lua: &Lua, _: ()) -> LuaResult<Vec<LocalMod>> {
}
}
_ => {}
}
},
None => {}
}

if let Some(min_balamod_version) = manifest.clone().min_balamod_version {
if balamod_version < min_balamod_version {
lua.load(format!("require('logging').getLogger('balalib'):error('Balalib version too low: {} for mod {}')", min_balamod_version, manifest.id)).exec()?;
continue;
match manifest.clone().min_balamod_version {
Some(min_balamod_version) => {
if balamod_version < min_balamod_version {
lua.load(format!("require('logging').getLogger('balalib'):error('Balalib version too low: {} for mod {}')", min_balamod_version, manifest.id)).exec()?;
continue;
}
}
None => {}
}

if let Some(max_balamod_version) = manifest.clone().max_balamod_version {
if balamod_version > max_balamod_version {
lua.load(format!("require('logging').getLogger('balalib'):error('Balalib version too high: {} for mod {}')", max_balamod_version, manifest.id)).exec()?;
continue;
match manifest.clone().max_balamod_version {
Some(max_balamod_version) => {
if balamod_version > max_balamod_version {
lua.load(format!("require('logging').getLogger('balalib'):error('Balalib version too high: {} for mod {}')", max_balamod_version, manifest.id)).exec()?;
continue;
}
}
None => {}
}

let folder_name = mod_dir.split("/").last().unwrap();
Expand Down
Loading
Loading