Files
Foundry-Scrapping-API/internal/foundry/models/db/module.go
2026-04-07 14:11:11 +03:00

283 lines
5.8 KiB
Go

package db
import (
"context"
"database/sql"
"errors"
"time"
)
type Module struct {
Id int64
TextId string
Title string
Description string
Url string
Version string
Availability int
CreatedAt time.Time
Languages []Language
Compatibility Compatibility
}
type Language struct {
Id int64
Lang string
Name string
Path string
}
type Modules []Module
func (modules Modules) GetById(id int) *Module {
return &modules[id]
}
func (m FoundryStateModel) InsertModule(module *Module, stateId int64) error {
query := `
INSERT INTO modules (state_id, text_id, title, description, url, version, availability)
VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING id, created_at`
args := []any{stateId, module.TextId, module.Title, module.Description, module.Url, module.Version, module.Availability}
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
err := m.DB.QueryRowContext(ctx, query, args...).Scan(&module.Id, &module.CreatedAt)
if err != nil {
return err
}
for i := range module.Languages {
err = m.InsertModuleLanguages(&module.Languages[i], module.Id)
if err != nil {
return err
}
}
return m.InsertModuleCompatibility(&module.Compatibility, module.Id)
}
func (m FoundryStateModel) InsertModuleCompatibility(compatibility *Compatibility, moduleId int64) error {
query := `
INSERT INTO modules_compatibility (module_id, minumum, verified, maximum)
VALUES ($1, $2, $3, $4)
RETURNING id`
args := []any{moduleId, compatibility.Minimum, compatibility.Verified, compatibility.Maximum}
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
return m.DB.QueryRowContext(ctx, query, args...).Scan(&compatibility.Id)
}
func (m FoundryStateModel) InsertModuleLanguages(lang *Language, moduleId int64) error {
query := `
INSERT INTO modules_compatibility (module_id, language, name, path)
VALUES ($1, $2, $3, $4)
RETURNING id`
args := []any{moduleId, lang.Lang, lang.Name, lang.Path}
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
return m.DB.QueryRowContext(ctx, query, args...).Scan(&lang.Id)
}
func (m FoundryStateModel) GetModules(idState int64) (Modules, error) {
if idState < 1 {
return nil, ErrorRecordNotFound
}
query := `
SELECT id, created_at, text_id, title, description, url, version, availability
FROM modules
WHERE state_id = $1`
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
rows, err := m.DB.QueryContext(ctx, query, idState)
if err != nil {
switch {
case errors.Is(err, sql.ErrNoRows):
return nil, ErrorRecordNotFound
default:
return nil, err
}
}
modules := make(Modules, 0, 1)
for rows.Next() {
var module Module
err := rows.Scan(
&module.Id,
&module.CreatedAt,
&module.TextId,
&module.Title,
&module.Description,
&module.Url,
&module.Version,
&module.Availability,
)
if err != nil {
return nil, err
}
module.Languages, err = m.GetModuleLanguages(module.Id)
if err != nil {
return nil, err
}
compatibility, err := m.GetModuleCompatibility(module.Id)
if err != nil {
return nil, err
}
module.Compatibility = *compatibility
modules = append(modules, module)
}
if err := rows.Err(); err != nil {
return nil, err
}
return modules, nil
}
func (m FoundryStateModel) GetModuleCompatibility(idModule int64) (*Compatibility, error) {
if idModule < 1 {
return nil, ErrorRecordNotFound
}
query := `
SELECT id, minimum, verified, maximum
FROM modules_compatibility
WHERE module_id = $1`
var compatibility Compatibility
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
err := m.DB.QueryRowContext(ctx, query, idModule).Scan(
&compatibility.Id,
&compatibility.Minimum,
&compatibility.Verified,
&compatibility.Maximum,
)
if err != nil {
switch {
case errors.Is(err, sql.ErrNoRows):
return nil, ErrorRecordNotFound
default:
return nil, err
}
}
return &compatibility, nil
}
func (m FoundryStateModel) GetModuleLanguages(idModule int64) ([]Language, error) {
if idModule < 1 {
return nil, ErrorRecordNotFound
}
query := `
SELECT id, language, name, path
FROM modules_languages
WHERE module_id = $1`
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
rows, err := m.DB.QueryContext(ctx, query, idModule)
if err != nil {
switch {
case errors.Is(err, sql.ErrNoRows):
return nil, ErrorRecordNotFound
default:
return nil, err
}
}
languages := make([]Language, 0, 1)
for rows.Next() {
var lang Language
err := rows.Scan(
&lang.Id,
&lang.Lang,
&lang.Name,
&lang.Path,
)
if err != nil {
return nil, err
}
languages = append(languages, lang)
}
if err := rows.Err(); err != nil {
return nil, err
}
return languages, nil
}
func (m FoundryStateModel) DeleteModules(idState int64) error {
if idState < 1 {
return ErrorRecordNotFound
}
query := `
DELETE FROM modules
WHERE state_id = $1`
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
result, err := m.DB.ExecContext(ctx, query, idState)
if err != nil {
return err
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return err
}
if rowsAffected == 0 {
return ErrorRecordNotFound
}
return nil
}
func (m FoundryStateModel) DeleteModule(idModule int64) error {
if idModule < 1 {
return ErrorRecordNotFound
}
query := `
DELETE FROM modules
WHERE id = $1`
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
result, err := m.DB.ExecContext(ctx, query, idModule)
if err != nil {
return err
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return err
}
if rowsAffected == 0 {
return ErrorRecordNotFound
}
return nil
}