You've already forked AstralRinth
forked from didirus/AstralRinth
Plugins (#758)
* plugins; datapacks * merge fixes/changes --------- Co-authored-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
This commit is contained in:
@@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n SELECT l.id id, l.loader loader, l.icon icon,\n ARRAY_AGG(DISTINCT pt.name) filter (where pt.name is not null) project_types,\n ARRAY_AGG(DISTINCT g.slug) filter (where g.slug is not null) games\n FROM loaders l \n LEFT OUTER JOIN loaders_project_types lpt ON joining_loader_id = l.id\n LEFT OUTER JOIN project_types pt ON lpt.joining_project_type_id = pt.id\n LEFT OUTER JOIN loaders_project_types_games lptg ON lptg.loader_id = lpt.joining_loader_id AND lptg.project_type_id = lpt.joining_project_type_id\n LEFT OUTER JOIN games g ON lptg.game_id = g.id\n GROUP BY l.id;\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "loader",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "icon",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "project_types",
|
|
||||||
"type_info": "VarcharArray"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "games",
|
|
||||||
"type_info": "VarcharArray"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": []
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
null
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "a796587302ae98d1af5f41696e401174fbeb9e8399bdcc78ffe8f80181b217a4"
|
|
||||||
}
|
|
||||||
50
.sqlx/query-cdb2f18f826097f0f17a1f7295d7c45eb1987b63c1a21666c6ca60c52217ba4d.json
generated
Normal file
50
.sqlx/query-cdb2f18f826097f0f17a1f7295d7c45eb1987b63c1a21666c6ca60c52217ba4d.json
generated
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "\n SELECT l.id id, l.loader loader, l.icon icon, l.metadata metadata,\n ARRAY_AGG(DISTINCT pt.name) filter (where pt.name is not null) project_types,\n ARRAY_AGG(DISTINCT g.slug) filter (where g.slug is not null) games\n FROM loaders l \n LEFT OUTER JOIN loaders_project_types lpt ON joining_loader_id = l.id\n LEFT OUTER JOIN project_types pt ON lpt.joining_project_type_id = pt.id\n LEFT OUTER JOIN loaders_project_types_games lptg ON lptg.loader_id = lpt.joining_loader_id AND lptg.project_type_id = lpt.joining_project_type_id\n LEFT OUTER JOIN games g ON lptg.game_id = g.id\n GROUP BY l.id;\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Int4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "loader",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 2,
|
||||||
|
"name": "icon",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 3,
|
||||||
|
"name": "metadata",
|
||||||
|
"type_info": "Jsonb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 4,
|
||||||
|
"name": "project_types",
|
||||||
|
"type_info": "VarcharArray"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 5,
|
||||||
|
"name": "games",
|
||||||
|
"type_info": "VarcharArray"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": []
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "cdb2f18f826097f0f17a1f7295d7c45eb1987b63c1a21666c6ca60c52217ba4d"
|
||||||
|
}
|
||||||
46
migrations/20231115105022_plugins_datapacks_v3.sql
Normal file
46
migrations/20231115105022_plugins_datapacks_v3.sql
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
ALTER TABLE loaders ADD COLUMN metadata jsonb NOT NULL DEFAULT '{}'::jsonb;
|
||||||
|
|
||||||
|
-- Set 'platform' to 'true' for all plugin loaders
|
||||||
|
-- From knossos v2
|
||||||
|
-- pluginLoaders: ['bukkit', 'spigot', 'paper', 'purpur', 'sponge', 'folia'],
|
||||||
|
-- pluginPlatformLoaders: ['bungeecord', 'waterfall', 'velocity'],
|
||||||
|
-- allPluginLoaders: [
|
||||||
|
-- 'bukkit',
|
||||||
|
-- 'spigot',
|
||||||
|
-- 'paper',
|
||||||
|
-- 'purpur',
|
||||||
|
-- 'sponge',
|
||||||
|
-- 'bungeecord',
|
||||||
|
-- 'waterfall',
|
||||||
|
-- 'velocity',
|
||||||
|
-- 'folia',
|
||||||
|
-- ],
|
||||||
|
-- dataPackLoaders: ['datapack'],
|
||||||
|
-- modLoaders: ['forge', 'fabric', 'quilt', 'liteloader', 'modloader', 'rift', 'neoforge'],
|
||||||
|
UPDATE loaders SET metadata = jsonb_set(metadata, '{platform}', 'false'::jsonb) WHERE loader in ('bukkit', 'spigot', 'paper', 'purpur', 'sponge', 'folia');
|
||||||
|
UPDATE loaders SET metadata = jsonb_set(metadata, '{platform}', 'true'::jsonb) WHERE loader in ('bungeecord', 'waterfall', 'velocity');
|
||||||
|
|
||||||
|
INSERT INTO project_types (name) VALUES ('plugin');
|
||||||
|
INSERT INTO project_types (name) VALUES ('datapack');
|
||||||
|
|
||||||
|
INSERT INTO loaders_project_types (joining_loader_id, joining_project_type_id)
|
||||||
|
SELECT l.id, pt.id
|
||||||
|
FROM loaders l
|
||||||
|
CROSS JOIN project_types pt
|
||||||
|
WHERE l.loader in ('datapack')
|
||||||
|
AND pt.name = 'datapack';
|
||||||
|
|
||||||
|
INSERT INTO loaders_project_types (joining_loader_id, joining_project_type_id)
|
||||||
|
SELECT l.id, pt.id
|
||||||
|
FROM loaders l
|
||||||
|
CROSS JOIN project_types pt
|
||||||
|
WHERE l.loader in ('bukkit', 'spigot', 'paper', 'purpur', 'sponge', 'bungeecord', 'waterfall', 'velocity', 'folia')
|
||||||
|
AND pt.name = 'plugin';
|
||||||
|
|
||||||
|
INSERT INTO loaders_project_types_games (loader_id, project_type_id, game_id)
|
||||||
|
SELECT joining_loader_id, joining_project_type_id, g.id
|
||||||
|
FROM loaders_project_types lpt
|
||||||
|
INNER JOIN project_types pt ON pt.id = lpt.joining_project_type_id
|
||||||
|
CROSS JOIN games g
|
||||||
|
WHERE g.name = 'minecraft'
|
||||||
|
AND pt.name in ('plugin', 'datapack');
|
||||||
@@ -85,6 +85,7 @@ pub struct Loader {
|
|||||||
pub icon: String,
|
pub icon: String,
|
||||||
pub supported_project_types: Vec<String>,
|
pub supported_project_types: Vec<String>,
|
||||||
pub supported_games: Vec<String>, // slugs
|
pub supported_games: Vec<String>, // slugs
|
||||||
|
pub metadata: serde_json::Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Loader {
|
impl Loader {
|
||||||
@@ -136,7 +137,7 @@ impl Loader {
|
|||||||
|
|
||||||
let result = sqlx::query!(
|
let result = sqlx::query!(
|
||||||
"
|
"
|
||||||
SELECT l.id id, l.loader loader, l.icon icon,
|
SELECT l.id id, l.loader loader, l.icon icon, l.metadata metadata,
|
||||||
ARRAY_AGG(DISTINCT pt.name) filter (where pt.name is not null) project_types,
|
ARRAY_AGG(DISTINCT pt.name) filter (where pt.name is not null) project_types,
|
||||||
ARRAY_AGG(DISTINCT g.slug) filter (where g.slug is not null) games
|
ARRAY_AGG(DISTINCT g.slug) filter (where g.slug is not null) games
|
||||||
FROM loaders l
|
FROM loaders l
|
||||||
@@ -161,7 +162,9 @@ impl Loader {
|
|||||||
.collect(),
|
.collect(),
|
||||||
supported_games: x
|
supported_games: x
|
||||||
.games
|
.games
|
||||||
.unwrap_or_default()
|
.unwrap_or_default(),
|
||||||
|
metadata: x.metadata
|
||||||
|
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
.try_collect::<Vec<_>>()
|
.try_collect::<Vec<_>>()
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ pub struct LoaderData {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
pub supported_project_types: Vec<String>,
|
pub supported_project_types: Vec<String>,
|
||||||
pub supported_games: Vec<String>,
|
pub supported_games: Vec<String>,
|
||||||
|
pub metadata: Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn loader_list(
|
pub async fn loader_list(
|
||||||
@@ -98,6 +99,7 @@ pub async fn loader_list(
|
|||||||
name: x.loader,
|
name: x.loader,
|
||||||
supported_project_types: x.supported_project_types,
|
supported_project_types: x.supported_project_types,
|
||||||
supported_games: x.supported_games,
|
supported_games: x.supported_games,
|
||||||
|
metadata: x.metadata,
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ use actix_web::{
|
|||||||
test::{self, TestRequest},
|
test::{self, TestRequest},
|
||||||
};
|
};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use labrinth::database::models::loader_fields::LoaderFieldEnumValue;
|
|
||||||
use labrinth::routes::v3::tags::GameData;
|
use labrinth::routes::v3::tags::GameData;
|
||||||
|
use labrinth::{
|
||||||
|
database::models::loader_fields::LoaderFieldEnumValue, routes::v3::tags::LoaderData,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
api_common::{
|
api_common::{
|
||||||
@@ -48,6 +50,12 @@ impl ApiTags for ApiV3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ApiV3 {
|
impl ApiV3 {
|
||||||
|
pub async fn get_loaders_deserialized(&self) -> Vec<LoaderData> {
|
||||||
|
let resp = self.get_loaders().await;
|
||||||
|
assert_eq!(resp.status(), 200);
|
||||||
|
test::read_body_json(resp).await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_loader_field_variants(&self, loader_field: &str) -> ServiceResponse {
|
pub async fn get_loader_field_variants(&self, loader_field: &str) -> ServiceResponse {
|
||||||
let req = TestRequest::get()
|
let req = TestRequest::get()
|
||||||
.uri(&format!("/v3/loader_field?loader_field={}", loader_field))
|
.uri(&format!("/v3/loader_field?loader_field={}", loader_field))
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ INSERT INTO loaders_project_types (joining_loader_id, joining_project_type_id) V
|
|||||||
INSERT INTO loaders (id, loader) VALUES (6, 'forge');
|
INSERT INTO loaders (id, loader) VALUES (6, 'forge');
|
||||||
INSERT INTO loaders_project_types (joining_loader_id, joining_project_type_id) VALUES (6,1);
|
INSERT INTO loaders_project_types (joining_loader_id, joining_project_type_id) VALUES (6,1);
|
||||||
|
|
||||||
|
INSERT INTO loaders (id, loader, metadata) VALUES (7, 'bukkit', '{"platform":false}'::jsonb);
|
||||||
|
INSERT INTO loaders (id, loader, metadata) VALUES (8, 'waterfall', '{"platform":true}'::jsonb);
|
||||||
|
|
||||||
-- Adds dummies to mrpack_loaders
|
-- Adds dummies to mrpack_loaders
|
||||||
INSERT INTO loader_field_enum_values (enum_id, value) SELECT id, 'fabric' FROM loader_field_enums WHERE enum_name = 'mrpack_loaders';
|
INSERT INTO loader_field_enum_values (enum_id, value) SELECT id, 'fabric' FROM loader_field_enums WHERE enum_name = 'mrpack_loaders';
|
||||||
INSERT INTO loader_field_enum_values (enum_id, value) SELECT id, 'forge' FROM loader_field_enums WHERE enum_name = 'mrpack_loaders';
|
INSERT INTO loader_field_enum_values (enum_id, value) SELECT id, 'forge' FROM loader_field_enums WHERE enum_name = 'mrpack_loaders';
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use common::environment::with_test_environment_all;
|
use common::{
|
||||||
|
api_v3::ApiV3,
|
||||||
|
environment::{with_test_environment, with_test_environment_all, TestEnvironment},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::common::api_common::ApiTags;
|
use crate::common::api_common::ApiTags;
|
||||||
|
|
||||||
@@ -10,18 +13,8 @@ mod common;
|
|||||||
async fn get_tags() {
|
async fn get_tags() {
|
||||||
with_test_environment_all(None, |test_env| async move {
|
with_test_environment_all(None, |test_env| async move {
|
||||||
let api = &test_env.api;
|
let api = &test_env.api;
|
||||||
let loaders = api.get_loaders_deserialized_common().await;
|
|
||||||
let categories = api.get_categories_deserialized_common().await;
|
let categories = api.get_categories_deserialized_common().await;
|
||||||
|
|
||||||
let loader_names = loaders.into_iter().map(|x| x.name).collect::<HashSet<_>>();
|
|
||||||
assert_eq!(
|
|
||||||
loader_names,
|
|
||||||
["fabric", "forge", "mrpack"]
|
|
||||||
.iter()
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.collect()
|
|
||||||
);
|
|
||||||
|
|
||||||
let category_names = categories
|
let category_names = categories
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x| x.name)
|
.map(|x| x.name)
|
||||||
@@ -44,3 +37,28 @@ async fn get_tags() {
|
|||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn get_tags_v3() {
|
||||||
|
with_test_environment(None, |test_env: TestEnvironment<ApiV3>| async move {
|
||||||
|
let api = &test_env.api;
|
||||||
|
let loaders = api.get_loaders_deserialized().await;
|
||||||
|
|
||||||
|
let loader_metadata = loaders
|
||||||
|
.into_iter()
|
||||||
|
.map(|x| (x.name, x.metadata.get("platform").and_then(|x| x.as_bool())))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
let loader_names = loader_metadata.keys().cloned().collect::<HashSet<String>>();
|
||||||
|
assert_eq!(
|
||||||
|
loader_names,
|
||||||
|
["fabric", "forge", "mrpack", "bukkit", "waterfall"]
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.collect()
|
||||||
|
);
|
||||||
|
assert_eq!(loader_metadata["fabric"], None);
|
||||||
|
assert_eq!(loader_metadata["bukkit"], Some(false));
|
||||||
|
assert_eq!(loader_metadata["waterfall"], Some(true));
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
@@ -12,33 +14,38 @@ async fn get_tags() {
|
|||||||
let game_versions = api.get_game_versions_deserialized().await;
|
let game_versions = api.get_game_versions_deserialized().await;
|
||||||
let loaders = api.get_loaders_deserialized().await;
|
let loaders = api.get_loaders_deserialized().await;
|
||||||
let side_types = api.get_side_types_deserialized().await;
|
let side_types = api.get_side_types_deserialized().await;
|
||||||
let categories = api.get_categories_deserialized().await;
|
|
||||||
|
|
||||||
// These tests match dummy data and will need to be updated if the dummy data changes;
|
// These tests match dummy data and will need to be updated if the dummy data changes
|
||||||
|
// Versions should be ordered by:
|
||||||
|
// - ordering
|
||||||
|
// - ordering ties settled by date added to database
|
||||||
|
// - We also expect presentation of NEWEST to OLDEST
|
||||||
|
// - All null orderings are treated as older than any non-null ordering
|
||||||
|
// (for this test, the 1.20.1, etc, versions are all null ordering)
|
||||||
let game_version_versions = game_versions
|
let game_version_versions = game_versions
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x| x.version)
|
.map(|x| x.version)
|
||||||
.collect::<HashSet<_>>();
|
.collect::<Vec<_>>();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
game_version_versions,
|
game_version_versions,
|
||||||
[
|
[
|
||||||
"1.20.1",
|
|
||||||
"1.20.2",
|
|
||||||
"1.20.3",
|
|
||||||
"1.20.4",
|
|
||||||
"1.20.5",
|
|
||||||
"Ordering_Negative1",
|
"Ordering_Negative1",
|
||||||
"Ordering_Positive100"
|
"Ordering_Positive100",
|
||||||
|
"1.20.5",
|
||||||
|
"1.20.4",
|
||||||
|
"1.20.3",
|
||||||
|
"1.20.2",
|
||||||
|
"1.20.1"
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.collect()
|
.collect_vec()
|
||||||
);
|
);
|
||||||
|
|
||||||
let loader_names = loaders.into_iter().map(|x| x.name).collect::<HashSet<_>>();
|
let loader_names = loaders.into_iter().map(|x| x.name).collect::<HashSet<_>>();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
loader_names,
|
loader_names,
|
||||||
["fabric", "forge", "mrpack"]
|
["fabric", "forge", "mrpack", "bukkit", "waterfall"]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.collect()
|
.collect()
|
||||||
@@ -52,26 +59,6 @@ async fn get_tags() {
|
|||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.collect()
|
.collect()
|
||||||
);
|
);
|
||||||
|
|
||||||
let category_names = categories
|
|
||||||
.into_iter()
|
|
||||||
.map(|x| x.name)
|
|
||||||
.collect::<HashSet<_>>();
|
|
||||||
assert_eq!(
|
|
||||||
category_names,
|
|
||||||
[
|
|
||||||
"combat",
|
|
||||||
"economy",
|
|
||||||
"food",
|
|
||||||
"optimization",
|
|
||||||
"decoration",
|
|
||||||
"mobs",
|
|
||||||
"magic"
|
|
||||||
]
|
|
||||||
.iter()
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.collect()
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user