diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/balalib.iml b/.idea/balalib.iml
new file mode 100644
index 0000000..cf84ae4
--- /dev/null
+++ b/.idea/balalib.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/discord.xml b/.idea/discord.xml
new file mode 100644
index 0000000..912db82
--- /dev/null
+++ b/.idea/discord.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..e075b7e
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/core.rs b/src/core.rs
index e54e445..9b40800 100644
--- a/src/core.rs
+++ b/src/core.rs
@@ -9,34 +9,7 @@ use std::process::Command;
pub fn need_update(lua: &Lua, _: ()) -> LuaResult {
let current_version = lua.load("require('balamod_version')").eval::()?;
- 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::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 {
@@ -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::().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::() {
+ 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)
@@ -140,27 +115,6 @@ pub fn is_mod_present(lua: &Lua, mod_info: ModInfo) -> LuaResult {
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()?;
diff --git a/src/lib.rs b/src/lib.rs
index 6ab67c6..495c811 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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");
@@ -21,13 +23,10 @@ fn echo(_: &Lua, name: String) -> LuaResult {
fn balalib(lua: &Lua) -> LuaResult {
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",
diff --git a/src/mods.rs b/src/mods.rs
index de63e53..6d4aa94 100644
--- a/src/mods.rs
+++ b/src/mods.rs
@@ -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 {
@@ -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(())
}
@@ -83,7 +82,7 @@ pub fn unpack_tar(dir: &str, tar: Vec) -> Result<(), Box LuaResult> {
+pub fn fetch_mods() -> LuaResult> {
let client = reqwest::blocking::Client::new();
match client
.get("https://raw.githubusercontent.com/balamod/balamod/master/new_repos.index")
@@ -144,101 +143,10 @@ fn get_mods_from_repo(repo_url: String) -> Result, reqwest::Error>
Ok(mod_infos)
}
-pub fn get_local_mods(lua: &Lua, _: ()) -> LuaResult> {
- 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> {
+ 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);
@@ -280,8 +188,8 @@ pub fn get_local_mods(lua: &Lua, _: ()) -> LuaResult> {
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 {
@@ -304,21 +212,28 @@ pub fn get_local_mods(lua: &Lua, _: ()) -> LuaResult> {
}
}
_ => {}
- }
+ },
+ 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();
diff --git a/src/schema/manifest.schema.json b/src/schema/manifest.schema.json
new file mode 100644
index 0000000..577d3c7
--- /dev/null
+++ b/src/schema/manifest.schema.json
@@ -0,0 +1,93 @@
+{
+ "$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
+}
\ No newline at end of file
diff --git a/src/tests.rs b/src/tests.rs
new file mode 100644
index 0000000..ab45c75
--- /dev/null
+++ b/src/tests.rs
@@ -0,0 +1,29 @@
+#[cfg(test)]
+mod tests {
+ use crate::utils::minify_lua;
+ use std::fs;
+
+ #[test]
+ fn test_update() {
+ let version = String::from("v0.1.10");
+ assert!(crate::updater::need_update(version).unwrap());
+ }
+
+ #[test]
+ fn test_mods_fetch() {
+ let mods = crate::mods::fetch_mods().unwrap();
+ assert!(mods.len() > 0);
+ }
+
+ #[test]
+ fn test_parsing() {
+ let lua_file = fs::read_to_string("test.lua").unwrap();
+ let functions = crate::utils::extract_functions(lua_file.clone());
+ assert_eq!(functions.len(), 1);
+ functions.get("test").unwrap();
+ assert_eq!(
+ minify_lua(lua_file),
+ r#"function test() print("Hello World!") a = function() print("Hello World!") end a() end test()"#
+ );
+ }
+}
diff --git a/src/updater.rs b/src/updater.rs
new file mode 100644
index 0000000..38d81e4
--- /dev/null
+++ b/src/updater.rs
@@ -0,0 +1,54 @@
+use crate::core::restart;
+use mlua::prelude::LuaResult;
+
+pub fn need_update(current_version: String) -> LuaResult {
+ 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::from_str(&text)
+ .expect(format!("Failed to parse json: {}", text).as_str());
+ 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),
+ }
+}
+
+#[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<()> {
+ restart()
+}
diff --git a/test.lua b/test.lua
new file mode 100644
index 0000000..882a9e4
--- /dev/null
+++ b/test.lua
@@ -0,0 +1,9 @@
+function test()
+ print("Hello World!")
+ a = function()
+ print("Hello World!")
+ end
+ a()
+end
+
+test()
\ No newline at end of file