Move SQL stuff into separate models module

This commit is contained in:
Tyler Hallada 2021-07-08 21:19:16 -04:00
parent d8080091f2
commit 19350081c3
8 changed files with 284 additions and 251 deletions

View File

@ -24,261 +24,19 @@ use tokio_util::compat::FuturesAsyncReadCompatExt;
use unrar::Archive; use unrar::Archive;
use zip::write::{FileOptions, ZipWriter}; use zip::write::{FileOptions, ZipWriter};
mod models;
use models::cell::insert_cell;
use models::file::{insert_file, File};
use models::game::insert_game;
use models::game_mod::{get_mod_by_nexus_mod_id, insert_mod, Mod};
use models::plugin::insert_plugin;
use models::plugin_cell::insert_plugin_cell;
static USER_AGENT: &str = "mod-mapper/0.1"; static USER_AGENT: &str = "mod-mapper/0.1";
static GAME_NAME: &str = "skyrimspecialedition"; static GAME_NAME: &str = "skyrimspecialedition";
const GAME_ID: u32 = 1704; const GAME_ID: u32 = 1704;
#[derive(Debug, Serialize, Deserialize)]
struct Game {
id: i32,
name: String,
nexus_game_id: i32,
updated_at: NaiveDateTime,
created_at: NaiveDateTime,
}
#[derive(Debug, Serialize, Deserialize)]
struct Mod {
id: i32,
name: String,
nexus_mod_id: i32,
author: String,
category: String,
description: Option<String>,
game_id: i32,
updated_at: NaiveDateTime,
created_at: NaiveDateTime,
}
#[derive(Debug, Serialize, Deserialize)]
struct File {
id: i32,
name: String,
file_name: String,
nexus_file_id: i32,
mod_id: i32,
category: Option<String>,
version: Option<String>,
mod_version: Option<String>,
uploaded_at: NaiveDateTime,
updated_at: NaiveDateTime,
created_at: NaiveDateTime,
}
#[derive(Debug, Serialize, Deserialize)]
struct Plugin {
id: i32,
name: String,
hash: i64,
file_id: i32,
version: Option<f64>,
author: Option<String>,
description: Option<String>,
masters: Option<Vec<String>>,
updated_at: NaiveDateTime,
created_at: NaiveDateTime,
}
#[derive(Debug, Serialize, Deserialize)]
struct Cell {
id: i32,
form_id: i32,
x: Option<i32>,
y: Option<i32>,
is_persistent: bool,
updated_at: NaiveDateTime,
created_at: NaiveDateTime,
}
#[derive(Debug, Serialize, Deserialize)]
struct PluginCell {
id: i32,
plugin_id: i32,
cell_id: i32,
editor_id: Option<String>,
updated_at: NaiveDateTime,
created_at: NaiveDateTime,
}
async fn insert_game(
pool: &sqlx::Pool<sqlx::Postgres>,
name: &str,
nexus_game_id: i32,
) -> Result<Game> {
sqlx::query_as!(
Game,
"INSERT INTO games
(name, nexus_game_id, created_at, updated_at)
VALUES ($1, $2, now(), now())
ON CONFLICT (nexus_game_id, name) DO UPDATE SET (name, updated_at) = (EXCLUDED.name, now())
RETURNING *",
name,
nexus_game_id
)
.fetch_one(pool)
.await
.context("Failed to insert game")
}
async fn get_mod_by_nexus_mod_id(
pool: &sqlx::Pool<sqlx::Postgres>,
nexus_mod_id: i32,
) -> Result<Option<Mod>> {
sqlx::query_as!(
Mod,
"SELECT * FROM mods WHERE nexus_mod_id = $1",
nexus_mod_id,
)
.fetch_optional(pool)
.await
.context("Failed to get mod")
}
async fn insert_mod(
pool: &sqlx::Pool<sqlx::Postgres>,
name: &str,
nexus_mod_id: i32,
author: &str,
category: &str,
description: Option<&str>,
game_id: i32,
) -> Result<Mod> {
sqlx::query_as!(
Mod,
"INSERT INTO mods
(name, nexus_mod_id, author, category, description, game_id, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, now(), now())
ON CONFLICT (game_id, nexus_mod_id) DO UPDATE
SET (name, author, category, description, updated_at) =
(EXCLUDED.name, EXCLUDED.author, EXCLUDED.category, EXCLUDED.description, now())
RETURNING *",
name,
nexus_mod_id,
author,
category,
description,
game_id
)
.fetch_one(pool)
.await
.context("Failed to insert or update mod")
}
async fn insert_file(
pool: &sqlx::Pool<sqlx::Postgres>,
name: &str,
file_name: &str,
nexus_file_id: i32,
mod_id: i32,
category: Option<&str>,
version: Option<&str>,
mod_version: Option<&str>,
uploaded_at: NaiveDateTime,
) -> Result<File> {
sqlx::query_as!(
File,
"INSERT INTO files
(name, file_name, nexus_file_id, mod_id, category, version, mod_version, uploaded_at, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, now(), now())
ON CONFLICT (mod_id, nexus_file_id) DO UPDATE
SET (name, file_name, category, version, mod_version, uploaded_at, updated_at) =
(EXCLUDED.name, EXCLUDED.file_name, EXCLUDED.category, EXCLUDED.version, EXCLUDED.mod_version, EXCLUDED.uploaded_at, now())
RETURNING *",
name,
file_name,
nexus_file_id,
mod_id,
category,
version,
mod_version,
uploaded_at
)
.fetch_one(pool)
.await
.context("Failed to insert file")
}
async fn insert_plugin(
pool: &sqlx::Pool<sqlx::Postgres>,
name: &str,
hash: i64,
file_id: i32,
version: Option<f64>,
author: Option<&str>,
description: Option<&str>,
masters: Option<&[String]>,
) -> Result<Plugin> {
sqlx::query_as!(
Plugin,
"INSERT INTO plugins
(name, hash, file_id, version, author, description, masters, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, now(), now())
ON CONFLICT (file_id, name) DO UPDATE
SET (hash, version, author, description, masters, updated_at) =
(EXCLUDED.hash, EXCLUDED.version, EXCLUDED.author, EXCLUDED.description, EXCLUDED.masters, now())
RETURNING *",
name,
hash,
file_id,
version,
author,
description,
masters
)
.fetch_one(pool)
.await
.context("Failed to insert plugin")
}
async fn insert_cell(
pool: &sqlx::Pool<sqlx::Postgres>,
form_id: i32,
x: Option<i32>,
y: Option<i32>,
is_persistent: bool,
) -> Result<Cell> {
sqlx::query_as!(
Cell,
"INSERT INTO cells
(form_id, x, y, is_persistent, created_at, updated_at)
VALUES ($1, $2, $3, $4, now(), now())
ON CONFLICT (form_id) DO UPDATE
SET (x, y, is_persistent, updated_at) =
(EXCLUDED.x, EXCLUDED.y, EXCLUDED.is_persistent, now())
RETURNING *",
form_id,
x,
y,
is_persistent
)
.fetch_one(pool)
.await
.context("Failed to insert cell")
}
async fn insert_plugin_cell(
pool: &sqlx::Pool<sqlx::Postgres>,
plugin_id: i32,
cell_id: i32,
editor_id: Option<String>,
) -> Result<PluginCell> {
sqlx::query_as!(
PluginCell,
"INSERT INTO plugin_cells
(plugin_id, cell_id, editor_id, created_at, updated_at)
VALUES ($1, $2, $3, now(), now())
ON CONFLICT (plugin_id, cell_id) DO UPDATE
SET (editor_id, updated_at) = (EXCLUDED.editor_id, now())
RETURNING *",
plugin_id,
cell_id,
editor_id,
)
.fetch_one(pool)
.await
.context("Failed to insert cell")
}
fn rate_limit_wait_duration(res: &Response) -> Result<Option<std::time::Duration>> { fn rate_limit_wait_duration(res: &Response) -> Result<Option<std::time::Duration>> {
let daily_remaining = res let daily_remaining = res
.headers() .headers()

40
src/models/cell.rs Normal file
View File

@ -0,0 +1,40 @@
use anyhow::{Context, Result};
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct Cell {
pub id: i32,
pub form_id: i32,
pub x: Option<i32>,
pub y: Option<i32>,
pub is_persistent: bool,
pub updated_at: NaiveDateTime,
pub created_at: NaiveDateTime,
}
pub async fn insert_cell(
pool: &sqlx::Pool<sqlx::Postgres>,
form_id: i32,
x: Option<i32>,
y: Option<i32>,
is_persistent: bool,
) -> Result<Cell> {
sqlx::query_as!(
Cell,
"INSERT INTO cells
(form_id, x, y, is_persistent, created_at, updated_at)
VALUES ($1, $2, $3, $4, now(), now())
ON CONFLICT (form_id) DO UPDATE
SET (x, y, is_persistent, updated_at) =
(EXCLUDED.x, EXCLUDED.y, EXCLUDED.is_persistent, now())
RETURNING *",
form_id,
x,
y,
is_persistent
)
.fetch_one(pool)
.await
.context("Failed to insert cell")
}

52
src/models/file.rs Normal file
View File

@ -0,0 +1,52 @@
use anyhow::{Context, Result};
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct File {
pub id: i32,
pub name: String,
pub file_name: String,
pub nexus_file_id: i32,
pub mod_id: i32,
pub category: Option<String>,
pub version: Option<String>,
pub mod_version: Option<String>,
pub uploaded_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
pub created_at: NaiveDateTime,
}
pub async fn insert_file(
pool: &sqlx::Pool<sqlx::Postgres>,
name: &str,
file_name: &str,
nexus_file_id: i32,
mod_id: i32,
category: Option<&str>,
version: Option<&str>,
mod_version: Option<&str>,
uploaded_at: NaiveDateTime,
) -> Result<File> {
sqlx::query_as!(
File,
"INSERT INTO files
(name, file_name, nexus_file_id, mod_id, category, version, mod_version, uploaded_at, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, now(), now())
ON CONFLICT (mod_id, nexus_file_id) DO UPDATE
SET (name, file_name, category, version, mod_version, uploaded_at, updated_at) =
(EXCLUDED.name, EXCLUDED.file_name, EXCLUDED.category, EXCLUDED.version, EXCLUDED.mod_version, EXCLUDED.uploaded_at, now())
RETURNING *",
name,
file_name,
nexus_file_id,
mod_id,
category,
version,
mod_version,
uploaded_at
)
.fetch_one(pool)
.await
.context("Failed to insert file")
}

32
src/models/game.rs Normal file
View File

@ -0,0 +1,32 @@
use anyhow::{Context, Result};
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct Game {
pub id: i32,
pub name: String,
pub nexus_game_id: i32,
pub updated_at: NaiveDateTime,
pub created_at: NaiveDateTime,
}
pub async fn insert_game(
pool: &sqlx::Pool<sqlx::Postgres>,
name: &str,
nexus_game_id: i32,
) -> Result<Game> {
sqlx::query_as!(
Game,
"INSERT INTO games
(name, nexus_game_id, created_at, updated_at)
VALUES ($1, $2, now(), now())
ON CONFLICT (nexus_game_id, name) DO UPDATE SET (name, updated_at) = (EXCLUDED.name, now())
RETURNING *",
name,
nexus_game_id
)
.fetch_one(pool)
.await
.context("Failed to insert game")
}

60
src/models/game_mod.rs Normal file
View File

@ -0,0 +1,60 @@
use anyhow::{Context, Result};
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct Mod {
pub id: i32,
pub name: String,
pub nexus_mod_id: i32,
pub author: String,
pub category: String,
pub description: Option<String>,
pub game_id: i32,
pub updated_at: NaiveDateTime,
pub created_at: NaiveDateTime,
}
pub async fn get_mod_by_nexus_mod_id(
pool: &sqlx::Pool<sqlx::Postgres>,
nexus_mod_id: i32,
) -> Result<Option<Mod>> {
sqlx::query_as!(
Mod,
"SELECT * FROM mods WHERE nexus_mod_id = $1",
nexus_mod_id,
)
.fetch_optional(pool)
.await
.context("Failed to get mod")
}
pub async fn insert_mod(
pool: &sqlx::Pool<sqlx::Postgres>,
name: &str,
nexus_mod_id: i32,
author: &str,
category: &str,
description: Option<&str>,
game_id: i32,
) -> Result<Mod> {
sqlx::query_as!(
Mod,
"INSERT INTO mods
(name, nexus_mod_id, author, category, description, game_id, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, now(), now())
ON CONFLICT (game_id, nexus_mod_id) DO UPDATE
SET (name, author, category, description, updated_at) =
(EXCLUDED.name, EXCLUDED.author, EXCLUDED.category, EXCLUDED.description, now())
RETURNING *",
name,
nexus_mod_id,
author,
category,
description,
game_id
)
.fetch_one(pool)
.await
.context("Failed to insert or update mod")
}

6
src/models/mod.rs Normal file
View File

@ -0,0 +1,6 @@
pub mod cell;
pub mod file;
pub mod game;
pub mod game_mod;
pub mod plugin;
pub mod plugin_cell;

49
src/models/plugin.rs Normal file
View File

@ -0,0 +1,49 @@
use anyhow::{Context, Result};
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct Plugin {
pub id: i32,
pub name: String,
pub hash: i64,
pub file_id: i32,
pub version: Option<f64>,
pub author: Option<String>,
pub description: Option<String>,
pub masters: Option<Vec<String>>,
pub updated_at: NaiveDateTime,
pub created_at: NaiveDateTime,
}
pub async fn insert_plugin(
pool: &sqlx::Pool<sqlx::Postgres>,
name: &str,
hash: i64,
file_id: i32,
version: Option<f64>,
author: Option<&str>,
description: Option<&str>,
masters: Option<&[String]>,
) -> Result<Plugin> {
sqlx::query_as!(
Plugin,
"INSERT INTO plugins
(name, hash, file_id, version, author, description, masters, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, now(), now())
ON CONFLICT (file_id, name) DO UPDATE
SET (hash, version, author, description, masters, updated_at) =
(EXCLUDED.hash, EXCLUDED.version, EXCLUDED.author, EXCLUDED.description, EXCLUDED.masters, now())
RETURNING *",
name,
hash,
file_id,
version,
author,
description,
masters
)
.fetch_one(pool)
.await
.context("Failed to insert plugin")
}

36
src/models/plugin_cell.rs Normal file
View File

@ -0,0 +1,36 @@
use anyhow::{Context, Result};
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct PluginCell {
pub id: i32,
pub plugin_id: i32,
pub cell_id: i32,
pub editor_id: Option<String>,
pub updated_at: NaiveDateTime,
pub created_at: NaiveDateTime,
}
pub async fn insert_plugin_cell(
pool: &sqlx::Pool<sqlx::Postgres>,
plugin_id: i32,
cell_id: i32,
editor_id: Option<String>,
) -> Result<PluginCell> {
sqlx::query_as!(
PluginCell,
"INSERT INTO plugin_cells
(plugin_id, cell_id, editor_id, created_at, updated_at)
VALUES ($1, $2, $3, now(), now())
ON CONFLICT (plugin_id, cell_id) DO UPDATE
SET (editor_id, updated_at) = (EXCLUDED.editor_id, now())
RETURNING *",
plugin_id,
cell_id,
editor_id,
)
.fetch_one(pool)
.await
.context("Failed to insert cell")
}