You've already forked AstralRinth
forked from didirus/AstralRinth
Lots of little fixes (#73)
* Lots of little fixes * Change + Add TODOs back that were incomplete * Fix migrations * Run prepare * Minor fixes * Fix formatting * SQLX Prepare
This commit is contained in:
15
migrations/20201014165954_create-statuses.sql
Normal file
15
migrations/20201014165954_create-statuses.sql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
CREATE TABLE statuses (
|
||||||
|
id serial PRIMARY KEY UNIQUE NOT NULL,
|
||||||
|
status varchar(64) UNIQUE NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE mods
|
||||||
|
ADD COLUMN status integer REFERENCES statuses NOT NULL;
|
||||||
|
ALTER TABLE mods
|
||||||
|
ADD COLUMN updated timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||||
|
|
||||||
|
INSERT INTO statuses (status) VALUES ('approved');
|
||||||
|
INSERT INTO statuses (status) VALUES ('rejected');
|
||||||
|
INSERT INTO statuses (status) VALUES ('draft');
|
||||||
|
INSERT INTO statuses (status) VALUES ('unlisted');
|
||||||
|
INSERT INTO statuses (status) VALUES ('processing');
|
||||||
415
sqlx-data.json
415
sqlx-data.json
@@ -1,5 +1,45 @@
|
|||||||
{
|
{
|
||||||
"db": "PostgreSQL",
|
"db": "PostgreSQL",
|
||||||
|
"01858339ec93e444b83c5d8793285d7b03982344770221c8a5a9bab9958d78ff": {
|
||||||
|
"query": "\n SELECT id\n FROM release_channels\n WHERE channel = $1\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Int4"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Text"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"02d8895627dfe108735a6e10ad63239348b71b3322b4734526a2646f17aedf05": {
|
||||||
|
"query": "\n SELECT status FROM statuses\n WHERE id = $1\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "status",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Int4"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"03209c5bda2d704e688439919a7b3903db6ad7caebf7ddafb3ea52d312d47bfb": {
|
"03209c5bda2d704e688439919a7b3903db6ad7caebf7ddafb3ea52d312d47bfb": {
|
||||||
"query": "\n INSERT INTO users (\n id, github_id, username, name, email,\n avatar_url, bio, created\n )\n VALUES (\n $1, $2, $3, $4, $5,\n $6, $7, $8\n )\n ",
|
"query": "\n INSERT INTO users (\n id, github_id, username, name, email,\n avatar_url, bio, created\n )\n VALUES (\n $1, $2, $3, $4, $5,\n $6, $7, $8\n )\n ",
|
||||||
"describe": {
|
"describe": {
|
||||||
@@ -251,48 +291,8 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"1ffce9b2d5c9fa6c8b9abce4bad9f9419c44ad6367b7463b979c91b9b5b4fea1": {
|
"1d144ed2bfb98d93f0515bb663708f2f9eff26548a50383f4013ba80305f7ac5": {
|
||||||
"query": "SELECT EXISTS(SELECT 1 FROM versions WHERE id=$1)",
|
"query": "\n SELECT m.id, m.title, m.description, m.downloads, m.icon_url, m.body_url, m.published, m.updated, m.team_id FROM mods m\n ",
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "exists",
|
|
||||||
"type_info": "Bool"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
null
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"25131559cb73a088000ab6379a769233440ade6c7511542da410065190d203fc": {
|
|
||||||
"query": "\n SELECT id FROM loaders\n WHERE loader = $1\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Int4"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Text"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"268efd8c8145bbb2bc70bd5ae0a5e6f90c5917ffd18575afcdeaf78b4f895d1e": {
|
|
||||||
"query": "\n SELECT id, title, description, downloads,\n icon_url, body_url, published,\n issues_url, source_url, wiki_url,\n team_id\n FROM mods\n WHERE id IN (SELECT * FROM UNNEST($1::bigint[]))\n ",
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -332,29 +332,17 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 7,
|
"ordinal": 7,
|
||||||
"name": "issues_url",
|
"name": "updated",
|
||||||
"type_info": "Varchar"
|
"type_info": "Timestamptz"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 8,
|
"ordinal": 8,
|
||||||
"name": "source_url",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 9,
|
|
||||||
"name": "wiki_url",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 10,
|
|
||||||
"name": "team_id",
|
"name": "team_id",
|
||||||
"type_info": "Int8"
|
"type_info": "Int8"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Left": [
|
"Left": []
|
||||||
"Int8Array"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
@@ -364,9 +352,47 @@
|
|||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
true,
|
false,
|
||||||
true,
|
false
|
||||||
true,
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"1ffce9b2d5c9fa6c8b9abce4bad9f9419c44ad6367b7463b979c91b9b5b4fea1": {
|
||||||
|
"query": "SELECT EXISTS(SELECT 1 FROM versions WHERE id=$1)",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "exists",
|
||||||
|
"type_info": "Bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Int8"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
null
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"25131559cb73a088000ab6379a769233440ade6c7511542da410065190d203fc": {
|
||||||
|
"query": "\n SELECT id FROM loaders\n WHERE loader = $1\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Int4"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Text"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -422,6 +448,26 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"3135db1c5309dac7580a731b2829397ae7bdd6c9a67b21e813f26a4f5aa251a9": {
|
||||||
|
"query": "\n SELECT status FROM statuses\n WHERE id = $1\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "status",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Int4"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"33fc96ac71cfa382991cfb153e89da1e9f43ebf5367c28b30c336b758222307b": {
|
"33fc96ac71cfa382991cfb153e89da1e9f43ebf5367c28b30c336b758222307b": {
|
||||||
"query": "\n DELETE FROM loaders_versions\n WHERE loaders_versions.version_id = $1\n ",
|
"query": "\n DELETE FROM loaders_versions\n WHERE loaders_versions.version_id = $1\n ",
|
||||||
"describe": {
|
"describe": {
|
||||||
@@ -446,6 +492,26 @@
|
|||||||
"nullable": []
|
"nullable": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"40597b84607e77809c13ffa9c6b0b1674bd6378a4737a8f6118e91ae2ede7e4a": {
|
||||||
|
"query": "\n SELECT id\n FROM release_channels\n WHERE channel = $1\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Int4"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Text"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"4411f2aefd43881450da34db81e826110ac86c3a6cef9fd6a3e9e341508d1f09": {
|
"4411f2aefd43881450da34db81e826110ac86c3a6cef9fd6a3e9e341508d1f09": {
|
||||||
"query": "\n SELECT id FROM versions\n WHERE mod_id = $1\n ",
|
"query": "\n SELECT id FROM versions\n WHERE mod_id = $1\n ",
|
||||||
"describe": {
|
"describe": {
|
||||||
@@ -787,73 +853,91 @@
|
|||||||
"nullable": []
|
"nullable": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"96d7b2c8b7b69fc370bb1a2d4a449f972eb3893dad5d6c59e498663cfc93a5c3": {
|
"9a41d6c1d5c250df6114157edf5621a88bc336c5c628ba89182ba999e0af3ba8": {
|
||||||
"query": "\n SELECT title, description, downloads,\n icon_url, body_url, published,\n issues_url, source_url, wiki_url,\n team_id\n FROM mods\n WHERE id = $1\n ",
|
"query": "\n SELECT id, title, description, downloads,\n icon_url, body_url, published,\n updated, status,\n issues_url, source_url, wiki_url,\n team_id\n FROM mods\n WHERE id IN (SELECT * FROM UNNEST($1::bigint[]))\n ",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
"ordinal": 0,
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Int8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
"name": "title",
|
"name": "title",
|
||||||
"type_info": "Varchar"
|
"type_info": "Varchar"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 1,
|
"ordinal": 2,
|
||||||
"name": "description",
|
"name": "description",
|
||||||
"type_info": "Varchar"
|
"type_info": "Varchar"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 2,
|
"ordinal": 3,
|
||||||
"name": "downloads",
|
"name": "downloads",
|
||||||
"type_info": "Int4"
|
"type_info": "Int4"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 3,
|
"ordinal": 4,
|
||||||
"name": "icon_url",
|
"name": "icon_url",
|
||||||
"type_info": "Varchar"
|
"type_info": "Varchar"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 4,
|
"ordinal": 5,
|
||||||
"name": "body_url",
|
"name": "body_url",
|
||||||
"type_info": "Varchar"
|
"type_info": "Varchar"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 5,
|
"ordinal": 6,
|
||||||
"name": "published",
|
"name": "published",
|
||||||
"type_info": "Timestamptz"
|
"type_info": "Timestamptz"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 6,
|
"ordinal": 7,
|
||||||
|
"name": "updated",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 8,
|
||||||
|
"name": "status",
|
||||||
|
"type_info": "Int4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 9,
|
||||||
"name": "issues_url",
|
"name": "issues_url",
|
||||||
"type_info": "Varchar"
|
"type_info": "Varchar"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 7,
|
"ordinal": 10,
|
||||||
"name": "source_url",
|
"name": "source_url",
|
||||||
"type_info": "Varchar"
|
"type_info": "Varchar"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 8,
|
"ordinal": 11,
|
||||||
"name": "wiki_url",
|
"name": "wiki_url",
|
||||||
"type_info": "Varchar"
|
"type_info": "Varchar"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ordinal": 9,
|
"ordinal": 12,
|
||||||
"name": "team_id",
|
"name": "team_id",
|
||||||
"type_info": "Int8"
|
"type_info": "Int8"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Left": [
|
"Left": [
|
||||||
"Int8"
|
"Int8Array"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"nullable": [
|
"nullable": [
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
@@ -979,6 +1063,26 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"adecffb1c41f9ddddf60c7c3c5a6be129aa8c49c53a698c6f4c2ee9ba15d6347": {
|
||||||
|
"query": "\n SELECT id\n FROM statuses\n WHERE status = $1\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Int4"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Text"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"b0e3d1c70b87bb54819e3fac04b684a9b857aeedb4dcb7cb400c2af0dbb12922": {
|
"b0e3d1c70b87bb54819e3fac04b684a9b857aeedb4dcb7cb400c2af0dbb12922": {
|
||||||
"query": "\n DELETE FROM teams\n WHERE id = $1\n ",
|
"query": "\n DELETE FROM teams\n WHERE id = $1\n ",
|
||||||
"describe": {
|
"describe": {
|
||||||
@@ -1182,6 +1286,33 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"c7ee59f31b20790b6e865b2ec14ecd9985cacb0a84e40f087d0f908033566166": {
|
||||||
|
"query": "\n SELECT u.id, u.username FROM users u\n INNER JOIN team_members tm ON tm.role = $1\n WHERE tm.team_id = $2\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Int8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "username",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Text",
|
||||||
|
"Int8"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"c82eb1b059b62444ab1d17e5a0bd7ef8acea4b05c6f3576c07d20c4ca7635a11": {
|
"c82eb1b059b62444ab1d17e5a0bd7ef8acea4b05c6f3576c07d20c4ca7635a11": {
|
||||||
"query": "\n INSERT INTO dependencies (dependent_id, dependency_id)\n VALUES ($1, $2)\n ",
|
"query": "\n INSERT INTO dependencies (dependent_id, dependency_id)\n VALUES ($1, $2)\n ",
|
||||||
"describe": {
|
"describe": {
|
||||||
@@ -1593,60 +1724,6 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"efe1bc80203f608226fa33e44654b681cc4430cec63bf7cf09b5281ff8c1c437": {
|
|
||||||
"query": "\n SELECT m.id, m.title, m.description, m.downloads, m.icon_url, m.body_url, m.published FROM mods m\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "title",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "description",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "downloads",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "icon_url",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 5,
|
|
||||||
"name": "body_url",
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 6,
|
|
||||||
"name": "published",
|
|
||||||
"type_info": "Timestamptz"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": []
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"f0db9d8606ccc2196a9cfafe0e7090dab42bf790f25e0469b8947fac1cf043d5": {
|
"f0db9d8606ccc2196a9cfafe0e7090dab42bf790f25e0469b8947fac1cf043d5": {
|
||||||
"query": "\n SELECT version FROM game_versions\n WHERE id = $1\n ",
|
"query": "\n SELECT version FROM game_versions\n WHERE id = $1\n ",
|
||||||
"describe": {
|
"describe": {
|
||||||
@@ -1687,6 +1764,92 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"f78dac3d15be1ea0d0ed43a4beadc04ec00d8ba68be2bb68cbc3f2ebe5c93dbd": {
|
||||||
|
"query": "\n SELECT title, description, downloads,\n icon_url, body_url, published,\n updated, status,\n issues_url, source_url, wiki_url,\n team_id\n FROM mods\n WHERE id = $1\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "title",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "description",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 2,
|
||||||
|
"name": "downloads",
|
||||||
|
"type_info": "Int4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 3,
|
||||||
|
"name": "icon_url",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 4,
|
||||||
|
"name": "body_url",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 5,
|
||||||
|
"name": "published",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 6,
|
||||||
|
"name": "updated",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 7,
|
||||||
|
"name": "status",
|
||||||
|
"type_info": "Int4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 8,
|
||||||
|
"name": "issues_url",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 9,
|
||||||
|
"name": "source_url",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 10,
|
||||||
|
"name": "wiki_url",
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 11,
|
||||||
|
"name": "team_id",
|
||||||
|
"type_info": "Int8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Int8"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"f7bea04e8e279e27a24de1bdf3c413daa8677994df5131494b28691ed6611efc": {
|
"f7bea04e8e279e27a24de1bdf3c413daa8677994df5131494b28691ed6611efc": {
|
||||||
"query": "\n SELECT url,expires FROM states\n WHERE id = $1\n ",
|
"query": "\n SELECT url,expires FROM states\n WHERE id = $1\n ",
|
||||||
"describe": {
|
"describe": {
|
||||||
|
|||||||
@@ -102,6 +102,9 @@ pub struct TeamMemberId(pub i64);
|
|||||||
#[derive(Copy, Clone, Debug, Type)]
|
#[derive(Copy, Clone, Debug, Type)]
|
||||||
#[sqlx(transparent)]
|
#[sqlx(transparent)]
|
||||||
pub struct ModId(pub i64);
|
pub struct ModId(pub i64);
|
||||||
|
#[derive(Copy, Clone, Debug, Type)]
|
||||||
|
#[sqlx(transparent)]
|
||||||
|
pub struct StatusId(pub i32);
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Type)]
|
#[derive(Copy, Clone, Debug, Type)]
|
||||||
#[sqlx(transparent)]
|
#[sqlx(transparent)]
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ pub struct ModBuilder {
|
|||||||
pub wiki_url: Option<String>,
|
pub wiki_url: Option<String>,
|
||||||
pub categories: Vec<CategoryId>,
|
pub categories: Vec<CategoryId>,
|
||||||
pub initial_versions: Vec<super::version_item::VersionBuilder>,
|
pub initial_versions: Vec<super::version_item::VersionBuilder>,
|
||||||
|
pub status: StatusId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModBuilder {
|
impl ModBuilder {
|
||||||
@@ -26,6 +27,8 @@ impl ModBuilder {
|
|||||||
description: self.description,
|
description: self.description,
|
||||||
body_url: self.body_url,
|
body_url: self.body_url,
|
||||||
published: chrono::Utc::now(),
|
published: chrono::Utc::now(),
|
||||||
|
updated: chrono::Utc::now(),
|
||||||
|
status: self.status,
|
||||||
downloads: 0,
|
downloads: 0,
|
||||||
icon_url: self.icon_url,
|
icon_url: self.icon_url,
|
||||||
issues_url: self.issues_url,
|
issues_url: self.issues_url,
|
||||||
@@ -63,6 +66,8 @@ pub struct Mod {
|
|||||||
pub description: String,
|
pub description: String,
|
||||||
pub body_url: String,
|
pub body_url: String,
|
||||||
pub published: chrono::DateTime<chrono::Utc>,
|
pub published: chrono::DateTime<chrono::Utc>,
|
||||||
|
pub updated: chrono::DateTime<chrono::Utc>,
|
||||||
|
pub status: StatusId,
|
||||||
pub downloads: i32,
|
pub downloads: i32,
|
||||||
pub icon_url: Option<String>,
|
pub icon_url: Option<String>,
|
||||||
pub issues_url: Option<String>,
|
pub issues_url: Option<String>,
|
||||||
@@ -114,6 +119,7 @@ impl Mod {
|
|||||||
"
|
"
|
||||||
SELECT title, description, downloads,
|
SELECT title, description, downloads,
|
||||||
icon_url, body_url, published,
|
icon_url, body_url, published,
|
||||||
|
updated, status,
|
||||||
issues_url, source_url, wiki_url,
|
issues_url, source_url, wiki_url,
|
||||||
team_id
|
team_id
|
||||||
FROM mods
|
FROM mods
|
||||||
@@ -134,9 +140,11 @@ impl Mod {
|
|||||||
body_url: row.body_url,
|
body_url: row.body_url,
|
||||||
icon_url: row.icon_url,
|
icon_url: row.icon_url,
|
||||||
published: row.published,
|
published: row.published,
|
||||||
|
updated: row.updated,
|
||||||
issues_url: row.issues_url,
|
issues_url: row.issues_url,
|
||||||
source_url: row.source_url,
|
source_url: row.source_url,
|
||||||
wiki_url: row.wiki_url,
|
wiki_url: row.wiki_url,
|
||||||
|
status: StatusId(row.status),
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@@ -154,6 +162,7 @@ impl Mod {
|
|||||||
"
|
"
|
||||||
SELECT id, title, description, downloads,
|
SELECT id, title, description, downloads,
|
||||||
icon_url, body_url, published,
|
icon_url, body_url, published,
|
||||||
|
updated, status,
|
||||||
issues_url, source_url, wiki_url,
|
issues_url, source_url, wiki_url,
|
||||||
team_id
|
team_id
|
||||||
FROM mods
|
FROM mods
|
||||||
@@ -172,9 +181,11 @@ impl Mod {
|
|||||||
body_url: m.body_url,
|
body_url: m.body_url,
|
||||||
icon_url: m.icon_url,
|
icon_url: m.icon_url,
|
||||||
published: m.published,
|
published: m.published,
|
||||||
|
updated: m.updated,
|
||||||
issues_url: m.issues_url,
|
issues_url: m.issues_url,
|
||||||
source_url: m.source_url,
|
source_url: m.source_url,
|
||||||
wiki_url: m.wiki_url,
|
wiki_url: m.wiki_url,
|
||||||
|
status: StatusId(m.status),
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
.try_collect::<Vec<Mod>>()
|
.try_collect::<Vec<Mod>>()
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ pub struct Mod {
|
|||||||
pub body_url: String,
|
pub body_url: String,
|
||||||
/// The date at which the mod was first published.
|
/// The date at which the mod was first published.
|
||||||
pub published: DateTime<Utc>,
|
pub published: DateTime<Utc>,
|
||||||
|
/// The date at which the mod was first published.
|
||||||
|
pub updated: DateTime<Utc>,
|
||||||
|
/// The status of the mod
|
||||||
|
pub status: ModStatus,
|
||||||
|
|
||||||
/// The total number of downloads the mod has had.
|
/// The total number of downloads the mod has had.
|
||||||
pub downloads: u32,
|
pub downloads: u32,
|
||||||
@@ -48,6 +52,49 @@ pub struct Mod {
|
|||||||
pub wiki_url: Option<String>,
|
pub wiki_url: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A status decides the visbility of a mod in search, URLs, and the whole site itself.
|
||||||
|
/// Approved - Mod is displayed on search, and accessible by URL
|
||||||
|
/// Rejected - Mod is not displayed on search, and not accessible by URL (Temporary state, mod can reapply)
|
||||||
|
/// Draft - Mod is not displayed on search, and not accessible by URL
|
||||||
|
/// Unlisted - Mod is not displayed on search, but accessible by URL
|
||||||
|
/// Processing - Mod is not displayed on search, and not accessible by URL (Temporary state, mod under review)
|
||||||
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum ModStatus {
|
||||||
|
Approved,
|
||||||
|
Rejected,
|
||||||
|
Draft,
|
||||||
|
Unlisted,
|
||||||
|
Processing,
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for ModStatus {
|
||||||
|
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
ModStatus::Approved => write!(fmt, "release"),
|
||||||
|
ModStatus::Rejected => write!(fmt, "beta"),
|
||||||
|
ModStatus::Draft => write!(fmt, "alpha"),
|
||||||
|
ModStatus::Unlisted => write!(fmt, "unlisted"),
|
||||||
|
ModStatus::Processing => write!(fmt, "Processing"),
|
||||||
|
ModStatus::Unknown => write!(fmt, "Unknown"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModStatus {
|
||||||
|
pub fn from_str(string: &str) -> ModStatus {
|
||||||
|
match string {
|
||||||
|
"processing" => ModStatus::Processing,
|
||||||
|
"rejected" => ModStatus::Processing,
|
||||||
|
"approved" => ModStatus::Processing,
|
||||||
|
"draft" => ModStatus::Processing,
|
||||||
|
"unlisted" => ModStatus::Processing,
|
||||||
|
_ => ModStatus::Unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A specific version of a mod
|
/// A specific version of a mod
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct Version {
|
pub struct Version {
|
||||||
@@ -128,7 +175,7 @@ pub struct SearchRequest {
|
|||||||
pub query: Option<String>,
|
pub query: Option<String>,
|
||||||
/// Must match a json 2 deep array of strings `[["categories:misc"]]`
|
/// Must match a json 2 deep array of strings `[["categories:misc"]]`
|
||||||
// TODO: We may want to have a better representation of this, so that
|
// TODO: We may want to have a better representation of this, so that
|
||||||
// we are less likely to break backwards compatability
|
// we are less likely to break backwards compatibility
|
||||||
pub facets: Option<String>,
|
pub facets: Option<String>,
|
||||||
pub filters: Option<String>,
|
pub filters: Option<String>,
|
||||||
pub version: Option<String>,
|
pub version: Option<String>,
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
#[serde(into = "Base62Id")]
|
#[serde(into = "Base62Id")]
|
||||||
pub struct TeamId(pub u64);
|
pub struct TeamId(pub u64);
|
||||||
|
|
||||||
|
pub const OWNER_ROLE: &str = "Owner";
|
||||||
|
|
||||||
// TODO: permissions, role names, etc
|
// TODO: permissions, role names, etc
|
||||||
/// A team of users who control a mod
|
/// A team of users who control a mod
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ pub async fn index_get() -> HttpResponse {
|
|||||||
let data = json!({
|
let data = json!({
|
||||||
"name": "modrinth-labrinth",
|
"name": "modrinth-labrinth",
|
||||||
"version": env!("CARGO_PKG_VERSION"),
|
"version": env!("CARGO_PKG_VERSION"),
|
||||||
//TODO: Add the documentation link
|
"documentation": "https://modrinth.com/documentation",
|
||||||
"documentation": "Nowhere yet",
|
|
||||||
"about": "Welcome traveler !"
|
"about": "Welcome traveler !"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
use crate::auth::{get_user_from_headers, AuthenticationError};
|
use crate::auth::{get_user_from_headers, AuthenticationError};
|
||||||
use crate::database::models;
|
use crate::database::models;
|
||||||
|
use crate::database::models::StatusId;
|
||||||
use crate::file_hosting::{FileHost, FileHostingError};
|
use crate::file_hosting::{FileHost, FileHostingError};
|
||||||
use crate::models::error::ApiError;
|
use crate::models::error::ApiError;
|
||||||
use crate::models::mods::{ModId, VersionId, VersionType};
|
use crate::models::mods::{ModId, ModStatus, VersionId};
|
||||||
use crate::models::teams::TeamMember;
|
use crate::models::teams::TeamMember;
|
||||||
use crate::models::users::UserId;
|
use crate::models::users::UserId;
|
||||||
use crate::routes::version_creation::InitialVersionData;
|
use crate::routes::version_creation::InitialVersionData;
|
||||||
@@ -97,8 +98,6 @@ impl actix_web::ResponseError for CreateError {
|
|||||||
struct ModCreateData {
|
struct ModCreateData {
|
||||||
/// The title or name of the mod.
|
/// The title or name of the mod.
|
||||||
pub mod_name: String,
|
pub mod_name: String,
|
||||||
/// The namespace of the mod
|
|
||||||
pub mod_namespace: String,
|
|
||||||
/// A short description of the mod.
|
/// A short description of the mod.
|
||||||
pub mod_description: String,
|
pub mod_description: String,
|
||||||
/// A long description of the mod, in markdown.
|
/// A long description of the mod, in markdown.
|
||||||
@@ -212,6 +211,9 @@ async fn mod_create_inner(
|
|||||||
CreateError::InvalidInput(String::from("`data` field must come before file fields"))
|
CreateError::InvalidInput(String::from("`data` field must come before file fields"))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
check_length("mod_name", 3, 255, &*create_data.mod_name)?;
|
||||||
|
check_length("mod_description", 3, 2048, &*create_data.mod_description)?;
|
||||||
|
|
||||||
let (file_name, file_extension) =
|
let (file_name, file_extension) =
|
||||||
super::version_creation::get_name_ext(&content_disposition)?;
|
super::version_creation::get_name_ext(&content_disposition)?;
|
||||||
|
|
||||||
@@ -267,12 +269,19 @@ async fn mod_create_inner(
|
|||||||
file_name: uploaded_text.file_name.clone(),
|
file_name: uploaded_text.file_name.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: do a real lookup for the channels
|
let release_channel = models::ChannelId(
|
||||||
let release_channel = match version_data.release_channel {
|
sqlx::query!(
|
||||||
VersionType::Release => models::ChannelId(1),
|
"
|
||||||
VersionType::Beta => models::ChannelId(3),
|
SELECT id
|
||||||
VersionType::Alpha => models::ChannelId(5),
|
FROM release_channels
|
||||||
};
|
WHERE channel = $1
|
||||||
|
",
|
||||||
|
version_data.release_channel.to_string()
|
||||||
|
)
|
||||||
|
.fetch_one(&mut *transaction)
|
||||||
|
.await?
|
||||||
|
.id,
|
||||||
|
);
|
||||||
|
|
||||||
let mut game_versions = Vec::with_capacity(version_data.game_versions.len());
|
let mut game_versions = Vec::with_capacity(version_data.game_versions.len());
|
||||||
for v in &version_data.game_versions {
|
for v in &version_data.game_versions {
|
||||||
@@ -379,7 +388,18 @@ async fn mod_create_inner(
|
|||||||
|
|
||||||
let team_id = team.insert(&mut *transaction).await?;
|
let team_id = team.insert(&mut *transaction).await?;
|
||||||
|
|
||||||
// Insert the new mod into the database
|
let status = ModStatus::Processing;
|
||||||
|
let status_id = sqlx::query!(
|
||||||
|
"
|
||||||
|
SELECT id
|
||||||
|
FROM statuses
|
||||||
|
WHERE status = $1
|
||||||
|
",
|
||||||
|
status.to_string()
|
||||||
|
)
|
||||||
|
.fetch_one(&mut *transaction)
|
||||||
|
.await?
|
||||||
|
.id;
|
||||||
|
|
||||||
let mod_builder = models::mod_item::ModBuilder {
|
let mod_builder = models::mod_item::ModBuilder {
|
||||||
mod_id: mod_id.into(),
|
mod_id: mod_id.into(),
|
||||||
@@ -394,6 +414,7 @@ async fn mod_create_inner(
|
|||||||
|
|
||||||
categories,
|
categories,
|
||||||
initial_versions: created_versions,
|
initial_versions: created_versions,
|
||||||
|
status: StatusId(status_id),
|
||||||
};
|
};
|
||||||
|
|
||||||
let versions_list = mod_builder
|
let versions_list = mod_builder
|
||||||
@@ -410,7 +431,6 @@ async fn mod_create_inner(
|
|||||||
|
|
||||||
let now = chrono::Utc::now();
|
let now = chrono::Utc::now();
|
||||||
let timestamp = now.timestamp();
|
let timestamp = now.timestamp();
|
||||||
let formatted = now.to_string();
|
|
||||||
|
|
||||||
let index_mod = crate::search::UploadSearchMod {
|
let index_mod = crate::search::UploadSearchMod {
|
||||||
mod_id: format!("local-{}", mod_id),
|
mod_id: format!("local-{}", mod_id),
|
||||||
@@ -418,17 +438,16 @@ async fn mod_create_inner(
|
|||||||
description: mod_builder.description.clone(),
|
description: mod_builder.description.clone(),
|
||||||
categories: create_data.categories.clone(),
|
categories: create_data.categories.clone(),
|
||||||
versions: versions_list,
|
versions: versions_list,
|
||||||
page_url: mod_builder.body_url.clone(),
|
page_url: format!("https://modrinth.com/mod/{}", mod_id),
|
||||||
icon_url: mod_builder.icon_url.clone().unwrap(),
|
icon_url: mod_builder.icon_url.clone().unwrap(),
|
||||||
author: user.username,
|
author: user.username,
|
||||||
author_url: format!("https://modrinth.com/user/{}", user.id),
|
author_url: format!("https://modrinth.com/user/{}", user.id),
|
||||||
// TODO: latest version info
|
// TODO: latest version info
|
||||||
latest_version: String::new(),
|
latest_version: String::new(),
|
||||||
downloads: 0,
|
downloads: 0,
|
||||||
date_created: formatted.clone(),
|
date_created: now,
|
||||||
created_timestamp: timestamp,
|
created_timestamp: timestamp,
|
||||||
// TODO: store and return modified time
|
date_modified: now,
|
||||||
date_modified: formatted,
|
|
||||||
modified_timestamp: timestamp,
|
modified_timestamp: timestamp,
|
||||||
host: Cow::Borrowed("modrinth"),
|
host: Cow::Borrowed("modrinth"),
|
||||||
empty: Cow::Borrowed("{}{}{}"),
|
empty: Cow::Borrowed("{}{}{}"),
|
||||||
@@ -443,6 +462,8 @@ async fn mod_create_inner(
|
|||||||
description: mod_builder.description.clone(),
|
description: mod_builder.description.clone(),
|
||||||
body_url: mod_builder.body_url.clone(),
|
body_url: mod_builder.body_url.clone(),
|
||||||
published: now,
|
published: now,
|
||||||
|
updated: now,
|
||||||
|
status,
|
||||||
downloads: 0,
|
downloads: 0,
|
||||||
categories: create_data.categories.clone(),
|
categories: create_data.categories.clone(),
|
||||||
versions: mod_builder
|
versions: mod_builder
|
||||||
@@ -514,3 +535,19 @@ fn get_image_content_type(extension: &str) -> Option<&'static str> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_length(
|
||||||
|
var_name: &str,
|
||||||
|
min_length: usize,
|
||||||
|
max_length: usize,
|
||||||
|
string: &str,
|
||||||
|
) -> Result<(), CreateError> {
|
||||||
|
if string.len() > max_length || string.len() < min_length {
|
||||||
|
Err(CreateError::InvalidInput(format!(
|
||||||
|
"The {} must be between {} and {} characters; got {}.",
|
||||||
|
var_name, string, min_length, max_length
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,15 +36,29 @@ pub async fn mods_get(
|
|||||||
.await
|
.await
|
||||||
.map_err(|e| ApiError::DatabaseError(e.into()))?;
|
.map_err(|e| ApiError::DatabaseError(e.into()))?;
|
||||||
|
|
||||||
let mods: Vec<models::mods::Mod> = mods_data
|
let mut mods: Vec<models::mods::Mod> = Vec::new();
|
||||||
.into_iter()
|
for m in mods_data {
|
||||||
.map(|m| models::mods::Mod {
|
let status = sqlx::query!(
|
||||||
|
"
|
||||||
|
SELECT status FROM statuses
|
||||||
|
WHERE id = $1
|
||||||
|
",
|
||||||
|
m.status.0,
|
||||||
|
)
|
||||||
|
.fetch_one(&**pool)
|
||||||
|
.await
|
||||||
|
.map_err(|e| ApiError::DatabaseError(e.into()))?
|
||||||
|
.status;
|
||||||
|
|
||||||
|
mods.push(models::mods::Mod {
|
||||||
id: m.id.into(),
|
id: m.id.into(),
|
||||||
team: m.team_id.into(),
|
team: m.team_id.into(),
|
||||||
title: m.title,
|
title: m.title,
|
||||||
description: m.description,
|
description: m.description,
|
||||||
body_url: m.body_url,
|
body_url: m.body_url,
|
||||||
published: m.published,
|
published: m.published,
|
||||||
|
updated: m.updated,
|
||||||
|
status: models::mods::ModStatus::from_str(&*status),
|
||||||
|
|
||||||
downloads: m.downloads as u32,
|
downloads: m.downloads as u32,
|
||||||
categories: vec![],
|
categories: vec![],
|
||||||
@@ -54,7 +68,7 @@ pub async fn mods_get(
|
|||||||
source_url: m.source_url,
|
source_url: m.source_url,
|
||||||
wiki_url: m.wiki_url,
|
wiki_url: m.wiki_url,
|
||||||
})
|
})
|
||||||
.collect();
|
}
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(mods))
|
Ok(HttpResponse::Ok().json(mods))
|
||||||
}
|
}
|
||||||
@@ -71,6 +85,19 @@ pub async fn mod_get(
|
|||||||
|
|
||||||
if let Some(data) = mod_data {
|
if let Some(data) = mod_data {
|
||||||
let m = data.inner;
|
let m = data.inner;
|
||||||
|
|
||||||
|
let status = sqlx::query!(
|
||||||
|
"
|
||||||
|
SELECT status FROM statuses
|
||||||
|
WHERE id = $1
|
||||||
|
",
|
||||||
|
m.status.0,
|
||||||
|
)
|
||||||
|
.fetch_one(&**pool)
|
||||||
|
.await
|
||||||
|
.map_err(|e| ApiError::DatabaseError(e.into()))?
|
||||||
|
.status;
|
||||||
|
|
||||||
let response = models::mods::Mod {
|
let response = models::mods::Mod {
|
||||||
id: m.id.into(),
|
id: m.id.into(),
|
||||||
team: m.team_id.into(),
|
team: m.team_id.into(),
|
||||||
@@ -78,6 +105,8 @@ pub async fn mod_get(
|
|||||||
description: m.description,
|
description: m.description,
|
||||||
body_url: m.body_url,
|
body_url: m.body_url,
|
||||||
published: m.published,
|
published: m.published,
|
||||||
|
updated: m.updated,
|
||||||
|
status: models::mods::ModStatus::from_str(&*status),
|
||||||
|
|
||||||
downloads: m.downloads as u32,
|
downloads: m.downloads as u32,
|
||||||
categories: data.categories,
|
categories: data.categories,
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ pub async fn version_create(
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// TODO: Update mod timestamp when new version is created
|
||||||
async fn version_create_inner(
|
async fn version_create_inner(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
mut payload: Multipart,
|
mut payload: Multipart,
|
||||||
@@ -167,12 +168,35 @@ async fn version_create_inner(
|
|||||||
file_name: uploaded_text.file_name.clone(),
|
file_name: uploaded_text.file_name.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: do a real lookup for the channels
|
let release_channel = models::ChannelId(
|
||||||
let release_channel = match version_create_data.release_channel {
|
sqlx::query!(
|
||||||
VersionType::Release => models::ChannelId(1),
|
"
|
||||||
VersionType::Beta => models::ChannelId(3),
|
SELECT id
|
||||||
VersionType::Alpha => models::ChannelId(5),
|
FROM release_channels
|
||||||
};
|
WHERE channel = $1
|
||||||
|
",
|
||||||
|
version_create_data.release_channel.to_string()
|
||||||
|
)
|
||||||
|
.fetch_one(&mut *transaction)
|
||||||
|
.await?
|
||||||
|
.id,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut game_versions = Vec::with_capacity(version_create_data.game_versions.len());
|
||||||
|
for v in &version_create_data.game_versions {
|
||||||
|
let id = models::categories::GameVersion::get_id(&v.0, &mut *transaction)
|
||||||
|
.await?
|
||||||
|
.ok_or_else(|| CreateError::InvalidGameVersion(v.0.clone()))?;
|
||||||
|
game_versions.push(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut loaders = Vec::with_capacity(version_create_data.loaders.len());
|
||||||
|
for l in &version_create_data.loaders {
|
||||||
|
let id = models::categories::Loader::get_id(&l.0, &mut *transaction)
|
||||||
|
.await?
|
||||||
|
.ok_or_else(|| CreateError::InvalidLoader(l.0.clone()))?;
|
||||||
|
loaders.push(id);
|
||||||
|
}
|
||||||
|
|
||||||
version_builder = Some(VersionBuilder {
|
version_builder = Some(VersionBuilder {
|
||||||
version_id: version_id.into(),
|
version_id: version_id.into(),
|
||||||
@@ -187,9 +211,8 @@ async fn version_create_inner(
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|x| (*x).into())
|
.map(|x| (*x).into())
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
// TODO: add game_versions and loaders info
|
game_versions,
|
||||||
game_versions: vec![],
|
loaders,
|
||||||
loaders: vec![],
|
|
||||||
release_channel,
|
release_channel,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -197,9 +197,9 @@ pub async fn index_curseforge(
|
|||||||
page_url: curseforge_mod.website_url,
|
page_url: curseforge_mod.website_url,
|
||||||
icon_url,
|
icon_url,
|
||||||
author_url: (&curseforge_mod.authors[0].url).to_string(),
|
author_url: (&curseforge_mod.authors[0].url).to_string(),
|
||||||
date_created: created.to_rfc3339(),
|
date_created: created,
|
||||||
created_timestamp: created.timestamp(),
|
created_timestamp: created.timestamp(),
|
||||||
date_modified: modified.to_rfc3339(),
|
date_modified: modified,
|
||||||
modified_timestamp: modified.timestamp(),
|
modified_timestamp: modified.timestamp(),
|
||||||
latest_version,
|
latest_version,
|
||||||
host: Cow::Borrowed("curseforge"),
|
host: Cow::Borrowed("curseforge"),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::search::UploadSearchMod;
|
|||||||
use sqlx::postgres::PgPool;
|
use sqlx::postgres::PgPool;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
// TODO: only loaders for recent versions? For mods that have moved from forge to fabric
|
||||||
pub async fn index_local(pool: PgPool) -> Result<Vec<UploadSearchMod>, IndexingError> {
|
pub async fn index_local(pool: PgPool) -> Result<Vec<UploadSearchMod>, IndexingError> {
|
||||||
info!("Indexing local mods!");
|
info!("Indexing local mods!");
|
||||||
|
|
||||||
@@ -13,10 +14,9 @@ pub async fn index_local(pool: PgPool) -> Result<Vec<UploadSearchMod>, IndexingE
|
|||||||
|
|
||||||
let mut results = sqlx::query!(
|
let mut results = sqlx::query!(
|
||||||
"
|
"
|
||||||
SELECT m.id, m.title, m.description, m.downloads, m.icon_url, m.body_url, m.published FROM mods m
|
SELECT m.id, m.title, m.description, m.downloads, m.icon_url, m.body_url, m.published, m.updated, m.team_id FROM mods m
|
||||||
"
|
"
|
||||||
)
|
).fetch(&pool);
|
||||||
.fetch(&pool);
|
|
||||||
|
|
||||||
while let Some(result) = results.next().await {
|
while let Some(result) = results.next().await {
|
||||||
if let Ok(result) = result {
|
if let Ok(result) = result {
|
||||||
@@ -34,7 +34,6 @@ pub async fn index_local(pool: PgPool) -> Result<Vec<UploadSearchMod>, IndexingE
|
|||||||
.try_collect::<Vec<String>>()
|
.try_collect::<Vec<String>>()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// TODO: only loaders for recent versions? For mods that have moved from forge to fabric
|
|
||||||
let loaders: Vec<String> = sqlx::query!(
|
let loaders: Vec<String> = sqlx::query!(
|
||||||
"
|
"
|
||||||
SELECT loaders.loader FROM versions
|
SELECT loaders.loader FROM versions
|
||||||
@@ -65,14 +64,24 @@ pub async fn index_local(pool: PgPool) -> Result<Vec<UploadSearchMod>, IndexingE
|
|||||||
|
|
||||||
categories.extend(loaders);
|
categories.extend(loaders);
|
||||||
|
|
||||||
|
let user = sqlx::query!(
|
||||||
|
"
|
||||||
|
SELECT u.id, u.username FROM users u
|
||||||
|
INNER JOIN team_members tm ON tm.role = $1
|
||||||
|
WHERE tm.team_id = $2
|
||||||
|
",
|
||||||
|
crate::models::teams::OWNER_ROLE,
|
||||||
|
result.team_id,
|
||||||
|
)
|
||||||
|
.fetch_one(&pool)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let mut icon_url = "".to_string();
|
let mut icon_url = "".to_string();
|
||||||
|
|
||||||
if let Some(url) = result.icon_url {
|
if let Some(url) = result.icon_url {
|
||||||
icon_url = url;
|
icon_url = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
let formatted = result.published.to_rfc3339();
|
|
||||||
let timestamp = result.published.timestamp();
|
|
||||||
docs_to_add.push(UploadSearchMod {
|
docs_to_add.push(UploadSearchMod {
|
||||||
mod_id: format!("local-{}", crate::models::ids::ModId(result.id as u64)),
|
mod_id: format!("local-{}", crate::models::ids::ModId(result.id as u64)),
|
||||||
title: result.title,
|
title: result.title,
|
||||||
@@ -80,14 +89,14 @@ pub async fn index_local(pool: PgPool) -> Result<Vec<UploadSearchMod>, IndexingE
|
|||||||
categories,
|
categories,
|
||||||
versions,
|
versions,
|
||||||
downloads: result.downloads,
|
downloads: result.downloads,
|
||||||
page_url: result.body_url,
|
page_url: format!("https://modrinth.com/mod/{}", result.id),
|
||||||
icon_url,
|
icon_url,
|
||||||
author: "".to_string(), // TODO: author/team info
|
author: user.username,
|
||||||
author_url: "".to_string(),
|
author_url: format!("https://modrinth.com/user/{}", user.id),
|
||||||
date_created: formatted.clone(),
|
date_created: result.published,
|
||||||
created_timestamp: timestamp,
|
created_timestamp: result.published.timestamp(),
|
||||||
date_modified: formatted,
|
date_modified: result.updated,
|
||||||
modified_timestamp: timestamp,
|
modified_timestamp: result.updated.timestamp(),
|
||||||
latest_version: "".to_string(), // TODO: Info about latest version
|
latest_version: "".to_string(), // TODO: Info about latest version
|
||||||
host: Cow::Borrowed("modrinth"),
|
host: Cow::Borrowed("modrinth"),
|
||||||
empty: Cow::Borrowed("{}{}{}"),
|
empty: Cow::Borrowed("{}{}{}"),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use crate::models::error::ApiError;
|
|||||||
use crate::models::mods::SearchRequest;
|
use crate::models::mods::SearchRequest;
|
||||||
use actix_web::http::StatusCode;
|
use actix_web::http::StatusCode;
|
||||||
use actix_web::web::HttpResponse;
|
use actix_web::web::HttpResponse;
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use meilisearch_sdk::client::Client;
|
use meilisearch_sdk::client::Client;
|
||||||
use meilisearch_sdk::document::Document;
|
use meilisearch_sdk::document::Document;
|
||||||
use meilisearch_sdk::search::Query;
|
use meilisearch_sdk::search::Query;
|
||||||
@@ -64,11 +65,11 @@ pub struct UploadSearchMod {
|
|||||||
pub latest_version: String,
|
pub latest_version: String,
|
||||||
|
|
||||||
/// RFC 3339 formatted creation date of the mod
|
/// RFC 3339 formatted creation date of the mod
|
||||||
pub date_created: String,
|
pub date_created: DateTime<Utc>,
|
||||||
/// Unix timestamp of the creation date of the mod
|
/// Unix timestamp of the creation date of the mod
|
||||||
pub created_timestamp: i64,
|
pub created_timestamp: i64,
|
||||||
/// RFC 3339 formatted date/time of last major modification (update)
|
/// RFC 3339 formatted date/time of last major modification (update)
|
||||||
pub date_modified: String,
|
pub date_modified: DateTime<Utc>,
|
||||||
/// Unix timestamp of the last major modification
|
/// Unix timestamp of the last major modification
|
||||||
pub modified_timestamp: i64,
|
pub modified_timestamp: i64,
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user