mirror of
https://github.com/Sheldan/gw2-tools.git
synced 2026-07-02 17:00:07 +00:00
initial commit of functioning opening tracking
This commit is contained in:
62
gw2-tools-backend/database/pom.xml
Normal file
62
gw2-tools-backend/database/pom.xml
Normal file
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.sheldan.gw2.tools</groupId>
|
||||
<artifactId>gw2-tools</artifactId>
|
||||
<version>0.0.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>database</artifactId>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src/main/kotlin</sourceDirectory>
|
||||
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compile</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-compile</id>
|
||||
<phase>test-compile</phase>
|
||||
<goals>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-test-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
2
gw2-tools-backend/database/src/main/docker/Dockerfile
Normal file
2
gw2-tools-backend/database/src/main/docker/Dockerfile
Normal file
@@ -0,0 +1,2 @@
|
||||
FROM liquibase/liquibase:4.25.1-alpine
|
||||
ADD resources/changeLog/ /liquibase/
|
||||
@@ -0,0 +1,27 @@
|
||||
package dev.sheldan.gw2.tools.entity
|
||||
|
||||
import jakarta.persistence.*
|
||||
|
||||
@Entity(name = "currency")
|
||||
class Currency(@Column(name="name", nullable = false)
|
||||
val name: String,
|
||||
|
||||
@Column(name="description")
|
||||
val description: String,
|
||||
|
||||
@Column(name="icon_url", nullable = false)
|
||||
val iconUrl: String,
|
||||
|
||||
@OneToMany(
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = [CascadeType.PERSIST, CascadeType.MERGE],
|
||||
mappedBy = "currency"
|
||||
)
|
||||
private var openings: List<OpeningCurrency>? = null,
|
||||
|
||||
@Id
|
||||
@Column(name="id", nullable = false)
|
||||
val id: Int) {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package dev.sheldan.gw2.tools.entity
|
||||
|
||||
import jakarta.persistence.*
|
||||
|
||||
@Entity(name = "item")
|
||||
class Item(@Column(name="name", nullable = false)
|
||||
val name: String,
|
||||
|
||||
@Column(name="description")
|
||||
val description: String,
|
||||
|
||||
@Column(name="icon_url", nullable = false)
|
||||
val iconUrl: String,
|
||||
|
||||
@Column(name="type", nullable = false)
|
||||
val type: String,
|
||||
|
||||
@Column(name="rarity", nullable = false)
|
||||
val rarity: String,
|
||||
|
||||
@OneToMany(cascade = [CascadeType.MERGE, CascadeType.PERSIST], orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "item")
|
||||
var submissionTemplates: List<SubmissionTemplate>? = null,
|
||||
|
||||
@OneToMany(
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = [CascadeType.PERSIST, CascadeType.MERGE],
|
||||
mappedBy = "item"
|
||||
)
|
||||
private var openings: List<OpeningItem>? = null,
|
||||
|
||||
@Id
|
||||
@Column(name="id", nullable = false)
|
||||
val id: Int) {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package dev.sheldan.gw2.tools.entity
|
||||
|
||||
import jakarta.persistence.*
|
||||
import java.time.Instant
|
||||
|
||||
@Entity(name = "opening")
|
||||
class Opening(
|
||||
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||
@JoinColumn(name = "user_id", referencedColumnName = "id")
|
||||
val user: User,
|
||||
@OneToMany(cascade = [CascadeType.MERGE, CascadeType.PERSIST], orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "opening")
|
||||
var currencies: List<OpeningCurrency>? = null,
|
||||
@OneToMany(cascade = [CascadeType.MERGE, CascadeType.PERSIST], orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "opening")
|
||||
var items: List<OpeningItem>? = null,
|
||||
@Column(name = "description")
|
||||
var description: String?=null,
|
||||
@Column(name = "created", insertable = false, updatable = false)
|
||||
var creationDate: Instant?=null,
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
val id: Int?=null
|
||||
) {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package dev.sheldan.gw2.tools.entity
|
||||
|
||||
import jakarta.persistence.*
|
||||
|
||||
@Entity(name = "opening_currency")
|
||||
class OpeningCurrency(
|
||||
@ManyToOne(cascade = [CascadeType.PERSIST, CascadeType.MERGE])
|
||||
@JoinColumn(name = "currency_id", nullable = false)
|
||||
val currency: Currency,
|
||||
@ManyToOne(cascade = [CascadeType.PERSIST, CascadeType.MERGE])
|
||||
@JoinColumn(name = "opening_id", nullable = false)
|
||||
val opening: Opening,
|
||||
@Column(name = "amount")
|
||||
val amount: Int,
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
val id: Int?=null
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package dev.sheldan.gw2.tools.entity
|
||||
|
||||
import jakarta.persistence.*
|
||||
|
||||
@Entity(name = "opening_item")
|
||||
class OpeningItem(
|
||||
@ManyToOne(cascade = [CascadeType.PERSIST, CascadeType.MERGE])
|
||||
@JoinColumn(name = "item_id", nullable = false)
|
||||
val item: Item,
|
||||
@ManyToOne(cascade = [CascadeType.PERSIST, CascadeType.MERGE])
|
||||
@JoinColumn(name = "opening_id", nullable = false)
|
||||
val opening: Opening,
|
||||
@Column(name = "count")
|
||||
val count: Int,
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
val id: Int?=null
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.sheldan.gw2.tools.entity
|
||||
|
||||
import jakarta.persistence.*
|
||||
|
||||
@Entity(name = "submission_template")
|
||||
class SubmissionTemplate(
|
||||
@ManyToOne(cascade = [CascadeType.PERSIST, CascadeType.MERGE])
|
||||
@JoinColumn(name = "item_id", nullable = false)
|
||||
val item: Item,
|
||||
@Column(name = "template_text")
|
||||
val templateText: String,
|
||||
@Column(name = "name")
|
||||
val name: String,
|
||||
@Column(name = "description")
|
||||
val description: String,
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
val id: Int?=null
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package dev.sheldan.gw2.tools.entity
|
||||
|
||||
import jakarta.persistence.Column
|
||||
import jakarta.persistence.Entity
|
||||
import jakarta.persistence.Id
|
||||
|
||||
@Entity(name = "gw2_user")
|
||||
class User( @Id
|
||||
@Column(name="id", nullable = false)
|
||||
val id: String) {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package dev.sheldan.gw2.tools.repo
|
||||
|
||||
import dev.sheldan.gw2.tools.entity.Currency
|
||||
import org.springframework.data.repository.CrudRepository
|
||||
|
||||
interface CurrencyRepository : CrudRepository<Currency, Int> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package dev.sheldan.gw2.tools.repo
|
||||
|
||||
import dev.sheldan.gw2.tools.entity.Item
|
||||
import org.springframework.data.repository.CrudRepository
|
||||
|
||||
interface ItemRepository : CrudRepository<Item, Int> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.sheldan.gw2.tools.repo
|
||||
|
||||
import dev.sheldan.gw2.tools.entity.Opening
|
||||
import dev.sheldan.gw2.tools.entity.User
|
||||
import org.springframework.data.repository.CrudRepository
|
||||
|
||||
interface OpeningRepository : CrudRepository<Opening, Int> {
|
||||
fun getAllByUser(user: User): List<Opening>
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.sheldan.gw2.tools.repo
|
||||
|
||||
import dev.sheldan.gw2.tools.entity.Item
|
||||
import dev.sheldan.gw2.tools.entity.SubmissionTemplate
|
||||
import org.springframework.data.repository.CrudRepository
|
||||
|
||||
interface SubmissionTemplateRepository : CrudRepository<SubmissionTemplate, Int> {
|
||||
fun getSubmissionTemplateByItem(item: Item): List<SubmissionTemplate>
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package dev.sheldan.gw2.tools.repo
|
||||
|
||||
import dev.sheldan.gw2.tools.entity.User
|
||||
import org.springframework.data.repository.CrudRepository
|
||||
|
||||
interface UserRepository : CrudRepository<User, String> {
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package dev.sheldan.gw2.tools.service
|
||||
|
||||
import dev.sheldan.gw2.tools.entity.Currency
|
||||
import dev.sheldan.gw2.tools.repo.CurrencyRepository
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class CurrencyManagement(val currencyRepository: CurrencyRepository) {
|
||||
fun getCurrencies(currencyIds: List<Int>): List<Currency> {
|
||||
return currencyRepository.findAllById(currencyIds).toList()
|
||||
}
|
||||
|
||||
fun getCurrenciesAsMap(currencyIds: List<Int>): Map<Int, Currency> {
|
||||
return getCurrencies(currencyIds).associateBy { it.id }
|
||||
}
|
||||
|
||||
fun getCurrencies() : List<Currency> {
|
||||
return currencyRepository.findAll().toList()
|
||||
}
|
||||
|
||||
fun createAndSaveCurrency(id: Int, name: String, description: String, iconUrl: String): Currency {
|
||||
val currency = createCurrency(id, name, description, iconUrl)
|
||||
return currencyRepository.save(currency)
|
||||
}
|
||||
|
||||
fun createCurrency(id: Int, name: String, description: String, iconUrl: String): Currency {
|
||||
return Currency(name, description, iconUrl, null, id)
|
||||
}
|
||||
|
||||
fun saveCurrency(currency: Currency): Currency {
|
||||
return currencyRepository.save(currency)
|
||||
}
|
||||
|
||||
fun saveCurrencies(currencies: List<Currency>) {
|
||||
currencyRepository.saveAll(currencies)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package dev.sheldan.gw2.tools.service
|
||||
|
||||
import dev.sheldan.gw2.tools.entity.Item
|
||||
import dev.sheldan.gw2.tools.repo.ItemRepository
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class ItemManagement(val itemRepository: ItemRepository) {
|
||||
fun getItems(itemIds: List<Int>) : List<Item> {
|
||||
return itemRepository.findAllById(itemIds).toList()
|
||||
}
|
||||
|
||||
fun getItem(itemId: Int) : Item? {
|
||||
return itemRepository.findByIdOrNull(itemId)
|
||||
}
|
||||
|
||||
fun getItemsAsMap(itemIds: List<Int>) : Map<Int, Item> {
|
||||
return getItems(itemIds).associateBy { it.id }
|
||||
}
|
||||
|
||||
fun getItems() : List<Item> {
|
||||
return itemRepository.findAll().toList()
|
||||
}
|
||||
|
||||
fun createItem(id: Int, name: String, description: String, iconUrl: String, type: String, rarity: String): Item {
|
||||
return Item(name, description, iconUrl, type, rarity, null, null, id)
|
||||
}
|
||||
|
||||
fun createAndSaveItem(id: Int, name: String, description: String, iconUrl: String, type: String, rarity: String): Item {
|
||||
val item = createItem(id, name, description, iconUrl, type, rarity)
|
||||
return saveItem(item)
|
||||
}
|
||||
|
||||
fun saveItems(items: List<Item>) {
|
||||
itemRepository.saveAll(items)
|
||||
}
|
||||
|
||||
fun saveItem(item: Item): Item {
|
||||
return itemRepository.save(item)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package dev.sheldan.gw2.tools.service
|
||||
|
||||
import dev.sheldan.gw2.tools.entity.*
|
||||
import dev.sheldan.gw2.tools.entity.Currency
|
||||
import dev.sheldan.gw2.tools.repo.OpeningRepository
|
||||
import org.springframework.stereotype.Component
|
||||
import java.util.*
|
||||
|
||||
@Component
|
||||
class OpeningManagement(
|
||||
val openingRepository: OpeningRepository
|
||||
) {
|
||||
fun createOpening(user: User, items: Map<Item, Int>, currencies: Map<Currency, Int>, description: String?){
|
||||
val opening = Opening(user, description = description)
|
||||
val openingItems: List<OpeningItem> = items.map { OpeningItem(it.key, opening, it.value) }
|
||||
val openingCurrencies: List<OpeningCurrency> = currencies.map { OpeningCurrency(it.key, opening, it.value) }
|
||||
opening.currencies = openingCurrencies
|
||||
opening.items = openingItems
|
||||
openingRepository.save(opening)
|
||||
}
|
||||
|
||||
fun getOpeningsByUser(user: User): List<Opening> {
|
||||
return openingRepository.getAllByUser(user)
|
||||
}
|
||||
|
||||
fun getAllOpenings(): List<Opening> {
|
||||
return openingRepository.findAll().toList()
|
||||
}
|
||||
|
||||
fun getOpening(id: Int): Optional<Opening> {
|
||||
return openingRepository.findById(id)
|
||||
}
|
||||
|
||||
fun deleteOpening(opening: Opening) {
|
||||
openingRepository.delete(opening)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.sheldan.gw2.tools.service
|
||||
|
||||
import dev.sheldan.gw2.tools.entity.Item
|
||||
import dev.sheldan.gw2.tools.entity.SubmissionTemplate
|
||||
import dev.sheldan.gw2.tools.repo.SubmissionTemplateRepository
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class SubmissionTemplateManagement(
|
||||
val submissionTemplateRepository: SubmissionTemplateRepository
|
||||
) {
|
||||
|
||||
fun getSubmissionTemplatesForItem(item: Item): List<SubmissionTemplate> {
|
||||
return submissionTemplateRepository.getSubmissionTemplateByItem(item)
|
||||
}
|
||||
|
||||
fun getAllSubmissionTemplates(): List<SubmissionTemplate> {
|
||||
return submissionTemplateRepository.findAll().toList()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package dev.sheldan.gw2.tools.service
|
||||
|
||||
import dev.sheldan.gw2.tools.entity.User
|
||||
import dev.sheldan.gw2.tools.repo.UserRepository
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
import org.springframework.stereotype.Component
|
||||
import java.security.MessageDigest
|
||||
|
||||
@Component
|
||||
class UserManagement(val userRepository: UserRepository) {
|
||||
fun getUser(id: String): User? {
|
||||
return userRepository.findByIdOrNull(id)
|
||||
}
|
||||
|
||||
fun getOrCreateUser(token: String): User {
|
||||
val userId = createUserId(token)
|
||||
val possibleUser = getUser(userId)
|
||||
return possibleUser ?: createUser(userId)
|
||||
}
|
||||
|
||||
fun createUserWithId(id: String): User {
|
||||
val userObj = User(id)
|
||||
return userRepository.save(userObj)
|
||||
}
|
||||
|
||||
fun createUser(token: String): User {
|
||||
val hashed = createUserId(token)
|
||||
val userObj = User(hashed)
|
||||
return userRepository.save(userObj)
|
||||
}
|
||||
|
||||
private fun createUserId(token: String): String {
|
||||
val md = MessageDigest.getInstance("SHA-256")
|
||||
val digest = md.digest(token.toByteArray())
|
||||
val hashed = digest.fold("") { str, it -> str + "%02x".format(it) }
|
||||
return hashed
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.25.xsd">
|
||||
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.25.xsd">
|
||||
|
||||
<changeSet author="Sheldan" id="currency-table">
|
||||
<createTable tableName="currency">
|
||||
<column name="id" type="INTEGER">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="name" type="VARCHAR(64)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="description" type="VARCHAR(255)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="icon_url" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
</createTable>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS currency_update_trigger ON currency;
|
||||
CREATE TRIGGER currency_update_trigger BEFORE UPDATE ON currency FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS currency_insert_trigger ON currency;
|
||||
CREATE TRIGGER currency_insert_trigger BEFORE INSERT ON currency FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.25.xsd">
|
||||
|
||||
<changeSet author="Sheldan" id="item-table">
|
||||
<createTable tableName="item">
|
||||
<column name="id" type="INTEGER">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="name" type="VARCHAR(128)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="description" type="VARCHAR(1024)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="icon_url" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="type" type="VARCHAR(64)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="rarity" type="VARCHAR(32)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
</createTable>
|
||||
<sql>
|
||||
ALTER TABLE item ADD CONSTRAINT check_item_rarity CHECK (rarity IN ('JUNK', 'BASIC', 'FINE', 'MASTERWORK', 'RARE', 'EXOTIC', 'ASCENDED', 'LEGENDARY'));
|
||||
ALTER TABLE item ADD CONSTRAINT check_item_type CHECK (type IN ('CONTAINER', 'ARMOR', 'BACK', 'BAG', 'CONSUMABLE', 'CRAFTING_MATERIAL', 'GATHERING', 'GIZMO', 'JADE_TECH_MODULE', 'KEY', 'MINI_PET', 'POWER_CORE', 'TOOL', 'TRAIT', 'TRINKET', 'TROPHY', 'UPGRADE_COMPONENT', 'WEAPON', 'RELIC'));
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS item_update_trigger ON item;
|
||||
CREATE TRIGGER item_update_trigger BEFORE UPDATE ON item FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS item_insert_trigger ON item;
|
||||
CREATE TRIGGER item_insert_trigger BEFORE INSERT ON item FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,82 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.25.xsd">
|
||||
|
||||
<changeSet author="Sheldan" id="opening-table">
|
||||
<createTable tableName="opening">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="pk_opening"/>
|
||||
</column>
|
||||
<column name="user_id" type="VARCHAR(255)">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="description" type="VARCHAR(1024)"/>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseColumnNames="user_id" baseTableName="opening" constraintName="fk_opening_user" deferrable="false"
|
||||
initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id"
|
||||
referencedTableName="gw2_user" validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS opening_update_trigger ON opening;
|
||||
CREATE TRIGGER opening_update_trigger BEFORE UPDATE ON opening FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS opening_insert_trigger ON opening;
|
||||
CREATE TRIGGER opening_insert_trigger BEFORE INSERT ON opening FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
<changeSet author="Sheldan" id="opening_currency-table">
|
||||
<createTable tableName="opening_currency">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="pk_opening_currency"/>
|
||||
</column>
|
||||
<column name="opening_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="currency_id" type="INT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="amount" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseColumnNames="opening_id" baseTableName="opening_currency"
|
||||
constraintName="fk_opening_currency_opening" deferrable="false"
|
||||
initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="opening"
|
||||
validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="currency_id" baseTableName="opening_currency"
|
||||
constraintName="fk_opening_currency_currency" deferrable="false"
|
||||
initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id"
|
||||
referencedTableName="currency" validate="true"/>
|
||||
</changeSet>
|
||||
<changeSet author="Sheldan" id="opening_item-table">
|
||||
<createTable tableName="opening_item">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="pk_opening_item"/>
|
||||
</column>
|
||||
<column name="opening_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="item_id" type="INT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="count" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseColumnNames="opening_id" baseTableName="opening_item"
|
||||
constraintName="fk_opening_item_opening" deferrable="false"
|
||||
initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="opening"
|
||||
validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="item_id" baseTableName="opening_item"
|
||||
constraintName="fk_opening_item_item" deferrable="false"
|
||||
initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id"
|
||||
referencedTableName="item" validate="true"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,8 @@
|
||||
CREATE OR REPLACE FUNCTION insert_trigger_procedure() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
NEW.created := CURRENT_TIMESTAMP;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
@@ -0,0 +1,8 @@
|
||||
CREATE OR REPLACE FUNCTION update_trigger_procedure() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
NEW.updated := CURRENT_TIMESTAMP;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.25.xsd">
|
||||
|
||||
<changeSet author="Sheldan" id="submission_template-table">
|
||||
<createTable tableName="submission_template">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="pk_submission_template"/>
|
||||
</column>
|
||||
<column name="item_id" type="INTEGER">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="description" type="VARCHAR(1024)"/>
|
||||
<column name="template_text" type="VARCHAR(2048)"/>
|
||||
<column name="name" type="VARCHAR(128)"/>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseColumnNames="item_id" baseTableName="submission_template" constraintName="fk_submission_template_item" deferrable="false"
|
||||
initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id"
|
||||
referencedTableName="item" validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS submission_template_update_trigger ON submission_template;
|
||||
CREATE TRIGGER submission_template_update_trigger BEFORE UPDATE ON submission_template FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS submission_template_insert_trigger ON submission_template;
|
||||
CREATE TRIGGER submission_template_insert_trigger BEFORE INSERT ON submission_template FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.25.xsd">
|
||||
<include file="trigger_functions.xml" relativeToChangelogFile="true"/>
|
||||
<include file="item.xml" relativeToChangelogFile="true"/>
|
||||
<include file="currency.xml" relativeToChangelogFile="true"/>
|
||||
<include file="user.xml" relativeToChangelogFile="true"/>
|
||||
<include file="opening.xml" relativeToChangelogFile="true"/>
|
||||
<include file="submission_template.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.25.xsd">
|
||||
<changeSet author="Sheldan" id="insert_trigger" dbms="postgresql">
|
||||
<sqlFile encoding="utf8" path="sql/insert_trigger.sql"
|
||||
relativeToChangelogFile="true"
|
||||
splitStatements="false"/>
|
||||
</changeSet>
|
||||
<changeSet author="Sheldan" id="update_trigger" dbms="postgresql">
|
||||
<sqlFile encoding="utf8" path="sql/update_trigger.sql"
|
||||
relativeToChangelogFile="true"
|
||||
splitStatements="false"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.25.xsd">
|
||||
|
||||
<changeSet author="Sheldan" id="user-table">
|
||||
<createTable tableName="gw2_user">
|
||||
<column name="id" type="VARCHAR(255)">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
</createTable>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS gw2_user_update_trigger ON gw2_user;
|
||||
CREATE TRIGGER gw2_user_update_trigger BEFORE UPDATE ON gw2_user FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS gw2_user_insert_trigger ON gw2_user;
|
||||
CREATE TRIGGER gw2_user_insert_trigger BEFORE INSERT ON gw2_user FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.25.xsd">
|
||||
<include file="0.0.1/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
10
gw2-tools-backend/executable/Dockerfile
Normal file
10
gw2-tools-backend/executable/Dockerfile
Normal file
@@ -0,0 +1,10 @@
|
||||
FROM amazoncorretto:21.0.1-alpine3.18
|
||||
RUN apk add entr
|
||||
|
||||
WORKDIR /app
|
||||
ADD BOOT-INF/lib/ /app/lib
|
||||
ADD snapshots/ /app/lib
|
||||
ADD META-INF /app/META-INF
|
||||
ADD BOOT-INF/classes /app
|
||||
|
||||
ENTRYPOINT java -cp .:./lib/* dev.sheldan.gw2.tools.ToolApplicationKt
|
||||
127
gw2-tools-backend/executable/pom.xml
Normal file
127
gw2-tools-backend/executable/pom.xml
Normal file
@@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.sheldan.gw2.tools</groupId>
|
||||
<artifactId>gw2-tools</artifactId>
|
||||
<version>0.0.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>executable</artifactId>
|
||||
|
||||
<properties>
|
||||
<main.class>dev.sheldan.gw2.tools.ToolApplicationKt</main.class>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<finalName>gw2-tools</finalName>
|
||||
<sourceDirectory>src/main/kotlin</sourceDirectory>
|
||||
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compile</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-compile</id>
|
||||
<phase>test-compile</phase>
|
||||
<goals>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>${maven-jar-plugin.version}</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
<mainClass>${main.class}</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>${maven-assembly-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals> <goal>single</goal> </goals>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>${main.class}</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>repackage</id>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>exec</classifier>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-test-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.gw2.tools</groupId>
|
||||
<artifactId>rest-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,13 @@
|
||||
package dev.sheldan.gw2.tools
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
import org.springframework.boot.runApplication
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories
|
||||
|
||||
@SpringBootApplication(exclude = [org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration::class])
|
||||
@EnableJpaRepositories(basePackages = ["dev.sheldan.gw2"])
|
||||
class ToolApplication
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
runApplication<ToolApplication>(*args)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
management.endpoints.web.exposure.include=mappings
|
||||
|
||||
security.basic.enabled=false
|
||||
management.security.enabled=false
|
||||
|
||||
|
||||
spring.datasource.url=jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}
|
||||
spring.datasource.username= ${DB_USER}
|
||||
spring.datasource.password= ${DB_PASS}
|
||||
spring.datasource.hikari.maximum-pool-size=${hikariPoolSize}
|
||||
spring.jpa.hibernate.default_schema=gw2
|
||||
spring.jpa.properties.hibernate.default_schema=gw2
|
||||
spring.quartz.jdbc.initialize-schema=never
|
||||
management.metrics.tags.application=GW2-Tools
|
||||
management.endpoint.health.probes.enabled=true
|
||||
management.health.livenessState.enabled=true
|
||||
management.health.readinessState.enabled=true
|
||||
spring.application.name=GW2-Tools
|
||||
11
gw2-tools-backend/executable/src/main/resources/logback.xml
Normal file
11
gw2-tools-backend/executable/src/main/resources/logback.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] [%-5level] [%logger{36}]: %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
71
gw2-tools-backend/gw2-api-client/pom.xml
Normal file
71
gw2-tools-backend/gw2-api-client/pom.xml
Normal file
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.sheldan.gw2.tools</groupId>
|
||||
<artifactId>gw2-tools</artifactId>
|
||||
<version>0.0.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>gw2-api-client</artifactId>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src/main/kotlin</sourceDirectory>
|
||||
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compile</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-compile</id>
|
||||
<phase>test-compile</phase>
|
||||
<goals>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-test-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.kryszak</groupId>
|
||||
<artifactId>gwatlin</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.gw2.tools</groupId>
|
||||
<artifactId>database</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,6 @@
|
||||
package dev.sheldan.gw2.tools.config
|
||||
|
||||
interface ApiKey {
|
||||
fun getApiKey(): String
|
||||
fun setApiKey(key: String)
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package dev.sheldan.gw2.tools.config
|
||||
|
||||
import io.github.kryszak.gwatlin.api.account.GWAccountClient
|
||||
import io.github.kryszak.gwatlin.api.characters.GWCharactersClient
|
||||
import io.github.kryszak.gwatlin.api.items.GWItemsClient
|
||||
import io.github.kryszak.gwatlin.api.miscellaneous.GWMiscellaneousClient
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.annotation.ScopedProxyMode
|
||||
import org.springframework.web.context.annotation.RequestScope
|
||||
|
||||
@Configuration
|
||||
class BeanConfig(val apiKey: ApiKey) {
|
||||
|
||||
@Bean
|
||||
@RequestScope(proxyMode = ScopedProxyMode.DEFAULT)
|
||||
fun gwCharacterClient(): GWCharactersClient {
|
||||
return GWCharactersClient(apiKey.getApiKey())
|
||||
}
|
||||
|
||||
@Bean
|
||||
@RequestScope(proxyMode = ScopedProxyMode.DEFAULT)
|
||||
fun getAccountClient(): GWAccountClient {
|
||||
return GWAccountClient(apiKey.getApiKey())
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun getMiscellaneousClient(): GWMiscellaneousClient {
|
||||
return GWMiscellaneousClient()
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun gwItemClient(): GWItemsClient {
|
||||
return GWItemsClient()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package dev.sheldan.gw2.tools.loader
|
||||
|
||||
import dev.sheldan.gw2.tools.models.*
|
||||
import dev.sheldan.gw2.tools.service.ItemManagement
|
||||
import io.github.kryszak.gwatlin.api.account.GWAccountClient
|
||||
import io.github.kryszak.gwatlin.api.characters.GWCharactersClient
|
||||
import io.github.kryszak.gwatlin.api.miscellaneous.GWMiscellaneousClient
|
||||
import org.springframework.stereotype.Component
|
||||
import org.springframework.web.context.annotation.RequestScope
|
||||
|
||||
@Component
|
||||
@RequestScope
|
||||
class AccountLoader(
|
||||
val charClient: GWCharactersClient,
|
||||
val accountClient: GWAccountClient,
|
||||
val miscellaneousClient: GWMiscellaneousClient,
|
||||
val itemManagement: ItemManagement
|
||||
) {
|
||||
fun getCharacters(): List<String>? {
|
||||
return charClient.getCharacters()
|
||||
}
|
||||
|
||||
fun getWallet(): AccountWalletView {
|
||||
val wallet = accountClient.getWallet()
|
||||
val currencies = miscellaneousClient.getCurrencies().associateBy { it.id }
|
||||
val enrichedCurrencies = wallet.mapNotNull { walletCurrency ->
|
||||
val currency = currencies[walletCurrency.id]
|
||||
currency?.let {
|
||||
EnrichedCurrency(walletCurrency.id, walletCurrency.value, it.name, it.description, it.icon)
|
||||
}
|
||||
}
|
||||
return AccountWalletView(enrichedCurrencies)
|
||||
}
|
||||
|
||||
fun getBank(): AccountVaultView {
|
||||
val bank = accountClient.getAccountVault()
|
||||
val itemIds = mutableSetOf<Int>()
|
||||
val items = bank.filterNotNull().mapNotNull {
|
||||
itemIds.add(it.id)
|
||||
EnrichedItem(it.id, it.count, it.boundTo)
|
||||
}
|
||||
val itemStats = itemManagement.getItemsAsMap(itemIds.toList())
|
||||
items.forEach { item ->
|
||||
itemStats[item.id]?.let {
|
||||
item.setValuesFromDbItem(it)
|
||||
}
|
||||
}
|
||||
return AccountVaultView(items)
|
||||
}
|
||||
|
||||
fun getMaterials(): AccountMaterialView{
|
||||
val materials = accountClient.getMaterials()
|
||||
val itemIds = mutableSetOf<Int>()
|
||||
val items = materials
|
||||
.filter { it.count > 0 }
|
||||
.map {
|
||||
|
||||
itemIds.add(it.id)
|
||||
EnrichedItem(it.id, it.count)
|
||||
}
|
||||
val actualMaterials = itemManagement.getItemsAsMap(itemIds.toList())
|
||||
items.forEach { item ->
|
||||
actualMaterials[item.id]?.let {
|
||||
item.setValuesFromDbItem(it)
|
||||
}
|
||||
}
|
||||
return AccountMaterialView(items)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package dev.sheldan.gw2.tools.loader
|
||||
|
||||
import dev.sheldan.gw2.tools.models.EnrichedCurrency
|
||||
import io.github.kryszak.gwatlin.api.miscellaneous.GWMiscellaneousClient
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class CurrencyLoader(
|
||||
var miscellaneousClient: GWMiscellaneousClient,
|
||||
) {
|
||||
fun getAllCurrencies(): List<EnrichedCurrency> {
|
||||
return miscellaneousClient.getCurrencies().map { EnrichedCurrency(it.id, 0, it.name, it.description, it.icon) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package dev.sheldan.gw2.tools.loader
|
||||
|
||||
import dev.sheldan.gw2.tools.entity.Item
|
||||
import dev.sheldan.gw2.tools.models.*
|
||||
import dev.sheldan.gw2.tools.service.ItemManagement
|
||||
import io.github.kryszak.gwatlin.api.account.GWAccountClient
|
||||
import io.github.kryszak.gwatlin.api.account.model.InventoryItem
|
||||
import io.github.kryszak.gwatlin.api.characters.GWCharactersClient
|
||||
import io.github.kryszak.gwatlin.api.characters.model.character.inventory.Bag
|
||||
import io.github.kryszak.gwatlin.api.characters.model.character.inventory.InventorySlot
|
||||
import org.springframework.stereotype.Component
|
||||
import org.springframework.web.context.annotation.RequestScope
|
||||
|
||||
@Component
|
||||
@RequestScope
|
||||
class InventoryLoader(
|
||||
val charClient: GWCharactersClient,
|
||||
val accountClient: GWAccountClient,
|
||||
val itemManagement: ItemManagement
|
||||
) {
|
||||
|
||||
fun getInventory(characterName: String): List<Bag?>? {
|
||||
return charClient.getInventory(characterName)
|
||||
}
|
||||
|
||||
fun getFullCharacterInventory(characterName: String): CharacterInventory {
|
||||
val itemIds = mutableSetOf<Int>()
|
||||
val characterInventory = getCharacterInventory(characterName, itemIds)
|
||||
val itemStats = getFullItemInfos(itemIds)
|
||||
enrichCharacterInventory(characterInventory, itemStats)
|
||||
return characterInventory
|
||||
}
|
||||
|
||||
private fun getCharacterInventory(characterName: String, itemIds: MutableSet<Int>): CharacterInventory {
|
||||
val characterInventory = getInventory(characterName)
|
||||
val convertedBags = mutableListOf<InventoryBag>()
|
||||
characterInventory?.let {
|
||||
for (bag in characterInventory.filterNotNull()) {
|
||||
convertedBags.addLast(convertApiBagToCharacterInventory(bag, itemIds))
|
||||
}
|
||||
}
|
||||
return CharacterInventory(characterName, convertedBags)
|
||||
}
|
||||
|
||||
fun getAccountInventory(): AccountInventoryView {
|
||||
val characters = charClient.getCharacters()
|
||||
val itemIds = mutableSetOf<Int>()
|
||||
val inventories = mutableListOf<CharacterInventory>()
|
||||
for (characterName in characters) {
|
||||
inventories.addLast(getCharacterInventory(characterName, itemIds))
|
||||
}
|
||||
|
||||
val itemStats = getFullItemInfos(itemIds)
|
||||
inventories.forEach { enrichCharacterInventory(it, itemStats) }
|
||||
return AccountInventoryView(inventories)
|
||||
}
|
||||
|
||||
private fun enrichCharacterInventory(characterInventory: CharacterInventory, itemStats: Map<Int, Item>) {
|
||||
return characterInventory.bags.forEach { bag ->
|
||||
bag.items.forEach { item ->
|
||||
itemStats[item.id]?.let {
|
||||
item.setValuesFromDbItem(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun convertApiBagToCharacterInventory(bag: Bag, itemIds: MutableSet<Int>): InventoryBag {
|
||||
val items = bag.inventory.filterNotNull().map { convertInventorySlot(it, itemIds) }
|
||||
return InventoryBag(bag.id, bag.size, items)
|
||||
}
|
||||
|
||||
private fun convertInventorySlot(slot: InventorySlot, itemIds: MutableSet<Int>): EnrichedItem {
|
||||
itemIds.add(slot.id)
|
||||
return EnrichedItem(slot.id, slot.count, slot.boundTo)
|
||||
}
|
||||
|
||||
private fun convertInventoryItem(item: InventoryItem, itemIds: MutableSet<Int>): EnrichedItem {
|
||||
itemIds.add(item.id)
|
||||
return EnrichedItem(item.id, item.count, item.binding)
|
||||
}
|
||||
|
||||
fun getSharedInventory(): AccountInventory {
|
||||
val itemIds = mutableSetOf<Int>()
|
||||
val sharedInventorySlots = accountClient.getInventory().filterNotNull()
|
||||
val sharedItems = sharedInventorySlots.map { convertInventoryItem(it, itemIds) }
|
||||
val fullItemInfo = getFullItemInfos(itemIds)
|
||||
sharedItems.forEach { item ->
|
||||
fullItemInfo[item.id]?.let {
|
||||
item.setValuesFromDbItem(it)
|
||||
}
|
||||
}
|
||||
return AccountInventory(sharedItems)
|
||||
}
|
||||
|
||||
private fun getFullItemInfos(itemIds: MutableSet<Int>) = itemManagement.getItemsAsMap(itemIds.toList())
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package dev.sheldan.gw2.tools.loader
|
||||
|
||||
import dev.sheldan.gw2.tools.models.EnrichedItem
|
||||
import io.github.kryszak.gwatlin.api.items.GWItemsClient
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class ItemLoader(
|
||||
val itemClient: GWItemsClient
|
||||
) {
|
||||
fun getAllItems(): List<EnrichedItem> {
|
||||
return itemClient.getItemIds().chunked(200)
|
||||
.flatMap { (itemClient.getItems(it)) }
|
||||
.map {
|
||||
val item = EnrichedItem(it.id, 1)
|
||||
item.setValuesFromItem(it)
|
||||
item
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package dev.sheldan.gw2.tools.models
|
||||
|
||||
class AccountInventory(
|
||||
val slots: List<EnrichedItem>
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package dev.sheldan.gw2.tools.models
|
||||
|
||||
data class AccountInventoryView(
|
||||
val inventories: List<CharacterInventory>
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package dev.sheldan.gw2.tools.models
|
||||
|
||||
class AccountMaterialView(
|
||||
val slots: List<EnrichedItem>
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package dev.sheldan.gw2.tools.models
|
||||
|
||||
class AccountVaultView(
|
||||
val slots: List<EnrichedItem>
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package dev.sheldan.gw2.tools.models
|
||||
|
||||
class AccountWalletView(
|
||||
val currencies: List<EnrichedCurrency>
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package dev.sheldan.gw2.tools.models
|
||||
|
||||
data class CharacterInventory(
|
||||
val name: String,
|
||||
val bags: List<InventoryBag>
|
||||
)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dev.sheldan.gw2.tools.models
|
||||
|
||||
class EnrichedCurrency(
|
||||
val id: Int,
|
||||
var amount: Int,
|
||||
val name: String,
|
||||
val description: String,
|
||||
val iconUrl: String
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package dev.sheldan.gw2.tools.models
|
||||
|
||||
import io.github.kryszak.gwatlin.api.items.model.item.Item
|
||||
|
||||
data class EnrichedItem(
|
||||
val id: Int,
|
||||
var count: Int,
|
||||
val boundTo: String? = null,
|
||||
|
||||
var iconUrl: String? = null,
|
||||
var name: String? = null,
|
||||
var description: String? = null,
|
||||
var type: Gw2TItemType? = null,
|
||||
var level: Int? = null,
|
||||
var rarity: Gw2TItemRarity? = null
|
||||
) {
|
||||
fun setValuesFromItem(item: Item) {
|
||||
this.name = item.name
|
||||
this.level = item.level
|
||||
this.description = item.description
|
||||
this.type = Gw2TItemType.convertFromAPI(item.type)
|
||||
this.rarity = Gw2TItemRarity.convertFromAPI(item.rarity)
|
||||
this.iconUrl = item.icon.ifBlank { "https://render.guildwars2.com/file/4BC52199DBDEEF5D4D90736B582DDA0F092B0DE4/434780.png" } // default icon if nothing is shown
|
||||
}
|
||||
|
||||
fun setValuesFromDbItem(item: dev.sheldan.gw2.tools.entity.Item) {
|
||||
this.name = item.name
|
||||
this.description = item.description
|
||||
this.type = Gw2TItemType.valueOf(item.type)
|
||||
this.rarity = Gw2TItemRarity.valueOf(item.rarity)
|
||||
this.iconUrl = item.iconUrl
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package dev.sheldan.gw2.tools.models
|
||||
|
||||
import io.github.kryszak.gwatlin.api.items.model.item.ItemRarity
|
||||
|
||||
enum class Gw2TItemRarity {
|
||||
JUNK,
|
||||
BASIC,
|
||||
FINE,
|
||||
MASTERWORK,
|
||||
RARE,
|
||||
EXOTIC,
|
||||
ASCENDED,
|
||||
LEGENDARY;
|
||||
|
||||
companion object {
|
||||
fun convertFromAPI(rarity: ItemRarity): Gw2TItemRarity = when (rarity) {
|
||||
ItemRarity.FINE -> FINE
|
||||
ItemRarity.MASTERWORK -> MASTERWORK
|
||||
ItemRarity.RARE -> RARE
|
||||
ItemRarity.EXOTIC -> EXOTIC
|
||||
ItemRarity.JUNK -> JUNK
|
||||
ItemRarity.BASIC -> BASIC
|
||||
ItemRarity.ASCENDED -> ASCENDED
|
||||
ItemRarity.LEGENDARY -> LEGENDARY
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package dev.sheldan.gw2.tools.models
|
||||
|
||||
import io.github.kryszak.gwatlin.api.items.model.item.ItemType
|
||||
|
||||
enum class Gw2TItemType {
|
||||
CONTAINER,
|
||||
ARMOR,
|
||||
BACK,
|
||||
BAG,
|
||||
CONSUMABLE,
|
||||
CRAFTING_MATERIAL,
|
||||
GATHERING,
|
||||
GIZMO,
|
||||
JADE_TECH_MODULE,
|
||||
KEY,
|
||||
MINI_PET,
|
||||
POWER_CORE,
|
||||
TOOL,
|
||||
TRAIT,
|
||||
TRINKET,
|
||||
TROPHY,
|
||||
UPGRADE_COMPONENT,
|
||||
WEAPON,
|
||||
RELIC;
|
||||
|
||||
companion object {
|
||||
fun convertFromAPI(type: ItemType): Gw2TItemType = when (type) {
|
||||
ItemType.CONTAINER -> CONTAINER
|
||||
ItemType.ARMOR -> ARMOR
|
||||
ItemType.BACK -> BACK
|
||||
ItemType.BAG -> BAG
|
||||
ItemType.CONSUMABLE -> CONSUMABLE
|
||||
ItemType.CRAFTING_MATERIAL -> CRAFTING_MATERIAL
|
||||
ItemType.GATHERING -> GATHERING
|
||||
ItemType.GIZMO -> GIZMO
|
||||
ItemType.JADE_TECH_MODULE -> JADE_TECH_MODULE
|
||||
ItemType.KEY -> KEY
|
||||
ItemType.MINI_PET -> MINI_PET
|
||||
ItemType.POWER_CORE -> POWER_CORE
|
||||
ItemType.TOOL -> TOOL
|
||||
ItemType.TRAIT -> TRAIT
|
||||
ItemType.TRINKET -> TRINKET
|
||||
ItemType.TROPHY -> TROPHY
|
||||
ItemType.UPGRADE_COMPONENT -> UPGRADE_COMPONENT
|
||||
ItemType.WEAPON -> WEAPON
|
||||
ItemType.RELIC -> RELIC
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package dev.sheldan.gw2.tools.models
|
||||
|
||||
data class InventoryBag(
|
||||
val id: Int,
|
||||
val size: Int,
|
||||
val items: List<EnrichedItem>
|
||||
) {
|
||||
}
|
||||
308
gw2-tools-backend/mvnw
vendored
Executable file
308
gw2-tools-backend/mvnw
vendored
Executable file
@@ -0,0 +1,308 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Apache Maven Wrapper startup batch script, version 3.2.0
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||
|
||||
if [ -f /usr/local/etc/mavenrc ] ; then
|
||||
. /usr/local/etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f /etc/mavenrc ] ; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
mingw=false
|
||||
case "$(uname)" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true;;
|
||||
Darwin*) darwin=true
|
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -x "/usr/libexec/java_home" ]; then
|
||||
JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
|
||||
else
|
||||
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
if [ -r /etc/gentoo-release ] ; then
|
||||
JAVA_HOME=$(java-config --jre-home)
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
|
||||
fi
|
||||
|
||||
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw ; then
|
||||
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="$(which javac)"
|
||||
if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=$(which readlink)
|
||||
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
|
||||
if $darwin ; then
|
||||
javaHome="$(dirname "\"$javaExecutable\"")"
|
||||
javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
|
||||
else
|
||||
javaExecutable="$(readlink -f "\"$javaExecutable\"")"
|
||||
fi
|
||||
javaHome="$(dirname "\"$javaExecutable\"")"
|
||||
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Path not specified to find_maven_basedir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
basedir="$1"
|
||||
wdir="$1"
|
||||
while [ "$wdir" != '/' ] ; do
|
||||
if [ -d "$wdir"/.mvn ] ; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||
if [ -d "${wdir}" ]; then
|
||||
wdir=$(cd "$wdir/.." || exit 1; pwd)
|
||||
fi
|
||||
# end of workaround
|
||||
done
|
||||
printf '%s' "$(cd "$basedir" || exit 1; pwd)"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
# Remove \r in case we run on Windows within Git Bash
|
||||
# and check out the repository with auto CRLF management
|
||||
# enabled. Otherwise, we may read lines that are delimited with
|
||||
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
|
||||
# splitting rules.
|
||||
tr -s '\r\n' ' ' < "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
log() {
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
printf '%s\n' "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
|
||||
log "$MAVEN_PROJECTBASEDIR"
|
||||
|
||||
##########################################################################################
|
||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
##########################################################################################
|
||||
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
|
||||
if [ -r "$wrapperJarPath" ]; then
|
||||
log "Found $wrapperJarPath"
|
||||
else
|
||||
log "Couldn't find $wrapperJarPath, downloading it ..."
|
||||
|
||||
if [ -n "$MVNW_REPOURL" ]; then
|
||||
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
|
||||
else
|
||||
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
|
||||
fi
|
||||
while IFS="=" read -r key value; do
|
||||
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
|
||||
safeValue=$(echo "$value" | tr -d '\r')
|
||||
case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
|
||||
esac
|
||||
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
log "Downloading from: $wrapperUrl"
|
||||
|
||||
if $cygwin; then
|
||||
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
|
||||
fi
|
||||
|
||||
if command -v wget > /dev/null; then
|
||||
log "Found wget ... using wget"
|
||||
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
else
|
||||
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
elif command -v curl > /dev/null; then
|
||||
log "Found curl ... using curl"
|
||||
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
|
||||
else
|
||||
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
else
|
||||
log "Falling back to using Java to download"
|
||||
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
|
||||
# For Cygwin, switch paths to Windows format before running javac
|
||||
if $cygwin; then
|
||||
javaSource=$(cygpath --path --windows "$javaSource")
|
||||
javaClass=$(cygpath --path --windows "$javaClass")
|
||||
fi
|
||||
if [ -e "$javaSource" ]; then
|
||||
if [ ! -e "$javaClass" ]; then
|
||||
log " - Compiling MavenWrapperDownloader.java ..."
|
||||
("$JAVA_HOME/bin/javac" "$javaSource")
|
||||
fi
|
||||
if [ -e "$javaClass" ]; then
|
||||
log " - Running MavenWrapperDownloader.java ..."
|
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
##########################################################################################
|
||||
# End of extension
|
||||
##########################################################################################
|
||||
|
||||
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
|
||||
wrapperSha256Sum=""
|
||||
while IFS="=" read -r key value; do
|
||||
case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
|
||||
esac
|
||||
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
if [ -n "$wrapperSha256Sum" ]; then
|
||||
wrapperSha256Result=false
|
||||
if command -v sha256sum > /dev/null; then
|
||||
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
|
||||
wrapperSha256Result=true
|
||||
fi
|
||||
elif command -v shasum > /dev/null; then
|
||||
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
|
||||
wrapperSha256Result=true
|
||||
fi
|
||||
else
|
||||
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
|
||||
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
|
||||
exit 1
|
||||
fi
|
||||
if [ $wrapperSha256Result = false ]; then
|
||||
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
|
||||
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
|
||||
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
|
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
|
||||
fi
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
# shellcheck disable=SC2086 # safe args
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
$MAVEN_DEBUG_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
||||
205
gw2-tools-backend/mvnw.cmd
vendored
Normal file
205
gw2-tools-backend/mvnw.cmd
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM https://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Apache Maven Wrapper startup batch script, version 3.2.0
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM set title of command window
|
||||
title %0
|
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
|
||||
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
|
||||
|
||||
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
|
||||
)
|
||||
|
||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
if exist %WRAPPER_JAR% (
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Found %WRAPPER_JAR%
|
||||
)
|
||||
) else (
|
||||
if not "%MVNW_REPOURL%" == "" (
|
||||
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
|
||||
)
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %WRAPPER_URL%
|
||||
)
|
||||
|
||||
powershell -Command "&{"^
|
||||
"$webclient = new-object System.Net.WebClient;"^
|
||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||
"}"^
|
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
|
||||
"}"
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
)
|
||||
)
|
||||
@REM End of extension
|
||||
|
||||
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
|
||||
SET WRAPPER_SHA_256_SUM=""
|
||||
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
|
||||
)
|
||||
IF NOT %WRAPPER_SHA_256_SUM%=="" (
|
||||
powershell -Command "&{"^
|
||||
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
|
||||
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
|
||||
" Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
|
||||
" Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
|
||||
" Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
|
||||
" exit 1;"^
|
||||
"}"^
|
||||
"}"
|
||||
if ERRORLEVEL 1 goto error
|
||||
)
|
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||
@REM work with both Windows and non-Windows executions.
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
%MAVEN_JAVA_EXE% ^
|
||||
%JVM_CONFIG_MAVEN_PROPS% ^
|
||||
%MAVEN_OPTS% ^
|
||||
%MAVEN_DEBUG_OPTS% ^
|
||||
-classpath %WRAPPER_JAR% ^
|
||||
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
|
||||
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
|
||||
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%"=="on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
|
||||
|
||||
cmd /C exit /B %ERROR_CODE%
|
||||
50
gw2-tools-backend/packaging/pom.xml
Normal file
50
gw2-tools-backend/packaging/pom.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.sheldan.gw2.tools</groupId>
|
||||
<artifactId>gw2-tools</artifactId>
|
||||
<version>0.0.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>packaging</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<properties>
|
||||
<file.basedir>${project.basedir}/src/main/docker/</file.basedir>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>copy</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
|
||||
<!-- backend jar -->
|
||||
<artifactItem>
|
||||
<groupId>dev.sheldan.gw2.tools</groupId>
|
||||
<artifactId>executable</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>exec</classifier>
|
||||
<type>jar</type>
|
||||
<overWrite>true</overWrite>
|
||||
<outputDirectory>${file.basedir}/tools</outputDirectory>
|
||||
<destFileName>app.jar</destFileName>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
8
gw2-tools-backend/packaging/src/main/docker/Dockerfile
Normal file
8
gw2-tools-backend/packaging/src/main/docker/Dockerfile
Normal file
@@ -0,0 +1,8 @@
|
||||
FROM amazoncorretto:21.0.1-alpine3.18
|
||||
MAINTAINER Sheldan
|
||||
VOLUME /tmp
|
||||
ADD config/* /config/
|
||||
ADD wrapper/*.sh /
|
||||
RUN chmod +x /start.sh
|
||||
ADD tools/app.jar /app.jar
|
||||
CMD ["/start.sh"]
|
||||
@@ -0,0 +1 @@
|
||||
logging.config=config/logback.xml
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration scan="true" scanPeriod="30 seconds">
|
||||
<property name="LOG_PATH" value="logs"/>
|
||||
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>
|
||||
%d{dd-MM-yyyy HH:mm:ss.SSS} %magenta([%thread]) %highlight(%-5level) %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="logFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
|
||||
<file>${LOG_PATH}/log.log</file>
|
||||
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<Pattern>
|
||||
%d{dd-MM-yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</Pattern>
|
||||
</encoder>
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>
|
||||
${LOG_PATH}/archived/log_%d{dd-MM-yyyy}.log
|
||||
</fileNamePattern>
|
||||
<maxHistory>10</maxHistory>
|
||||
<totalSizeCap>1GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
|
||||
</appender>
|
||||
|
||||
<logger name="dev.sheldan.gw2" level="INFO"/>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="logFileAppender"/>
|
||||
<appender-ref ref="stdout"/>
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
DEBUG_PARAMS=""
|
||||
if [ "x$REMOTE_DEBUG" = 'xtrue' ]; then
|
||||
DEBUG_PARAMS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"
|
||||
echo "Starting with remote debugging on port 5005"
|
||||
fi;
|
||||
java ${DEBUG_PARAMS} -jar app.jar
|
||||
176
gw2-tools-backend/pom.xml
Normal file
176
gw2-tools-backend/pom.xml
Normal file
@@ -0,0 +1,176 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>dev.sheldan.gw2.tools</groupId>
|
||||
<artifactId>gw2-tools</artifactId>
|
||||
<version>0.0.9-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>gw2-tools</name>
|
||||
<description>Tools for GW2</description>
|
||||
<modules>
|
||||
<module>executable</module>
|
||||
<module>gw2-api-client</module>
|
||||
<module>rest-api</module>
|
||||
<module>packaging</module>
|
||||
<module>database</module>
|
||||
</modules>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:${project.scm.url}</connection>
|
||||
<developerConnection>scm:git:${project.scm.url}</developerConnection>
|
||||
<url>https://github.com/Sheldan/gw2-tools.git</url>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>github</id>
|
||||
<url>https://maven.pkg.github.com/Sheldan/gw2-tools</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
|
||||
<properties>
|
||||
<java.version>21</java.version>
|
||||
<kotlin.version>1.9.21</kotlin.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<kotlin.code.style>official</kotlin.code.style>
|
||||
<kotlin.compiler.jvmTarget>21</kotlin.compiler.jvmTarget>
|
||||
<maven-surefire-plugin.version>3.2.5</maven-surefire-plugin.version>
|
||||
<maven-failsafe-plugin.version>3.2.5</maven-failsafe-plugin.version>
|
||||
<exec-maven-plugin.version>3.1.1</exec-maven-plugin.version>
|
||||
<junit-jupiter-engine.version>5.10.1</junit-jupiter-engine.version>
|
||||
<maven-jar-plugin.version>3.3.0</maven-jar-plugin.version>
|
||||
<maven-assembly-plugin.version>3.6.0</maven-assembly-plugin.version>
|
||||
<kotlin-logging.version>2.0.11</kotlin-logging.version>
|
||||
<gwatlin.version>1.9.5</gwatlin.version>
|
||||
<maven-release-plugin.version>2.5.3</maven-release-plugin.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.module</groupId>
|
||||
<artifactId>jackson-module-kotlin</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-reflect</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
|
||||
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
|
||||
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<args>
|
||||
<arg>-Xjsr305=strict</arg>
|
||||
</args>
|
||||
<compilerPlugins>
|
||||
<plugin>spring</plugin>
|
||||
<plugin>jpa</plugin>
|
||||
</compilerPlugins>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-allopen</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-noarg</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>${maven-release-plugin.version}</version>
|
||||
<configuration>
|
||||
<scmCommentPrefix>[RELEASE]</scmCommentPrefix>
|
||||
<tagNameFormat>@{project.version}</tagNameFormat>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-test-junit5</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>${junit-jupiter-engine.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.kryszak</groupId>
|
||||
<artifactId>gwatlin</artifactId>
|
||||
<version>${gwatlin.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.microutils</groupId>
|
||||
<artifactId>kotlin-logging-jvm</artifactId>
|
||||
<version>${kotlin-logging.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
</project>
|
||||
79
gw2-tools-backend/rest-api/pom.xml
Normal file
79
gw2-tools-backend/rest-api/pom.xml
Normal file
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.sheldan.gw2.tools</groupId>
|
||||
<artifactId>gw2-tools</artifactId>
|
||||
<version>0.0.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>rest-api</artifactId>
|
||||
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src/main/kotlin</sourceDirectory>
|
||||
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compile</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-compile</id>
|
||||
<phase>test-compile</phase>
|
||||
<goals>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>${maven-failsafe-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-test-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.gw2.tools</groupId>
|
||||
<artifactId>gw2-api-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.gw2.tools</groupId>
|
||||
<artifactId>database</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.microutils</groupId>
|
||||
<artifactId>kotlin-logging-jvm</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,4 @@
|
||||
package dev.sheldan.gw2.tools
|
||||
|
||||
class ItemNotFoundException(message: String): Throwable(message) {
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package dev.sheldan.gw2.tools.api
|
||||
|
||||
import dev.sheldan.gw2.tools.loader.AccountLoader
|
||||
import dev.sheldan.gw2.tools.models.AccountMaterialView
|
||||
import dev.sheldan.gw2.tools.models.AccountVaultView
|
||||
import dev.sheldan.gw2.tools.models.AccountWalletView
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import org.springframework.web.context.annotation.RequestScope
|
||||
|
||||
@RestController
|
||||
@RequestScope
|
||||
class AccountController(var accountLoader: AccountLoader) {
|
||||
@GetMapping("/characters")
|
||||
fun inventory(): List<String>? {
|
||||
return accountLoader.getCharacters()
|
||||
}
|
||||
|
||||
@GetMapping("/wallet")
|
||||
fun wallet(): AccountWalletView {
|
||||
return accountLoader.getWallet()
|
||||
}
|
||||
|
||||
@GetMapping("/bank")
|
||||
fun bank(): AccountVaultView {
|
||||
return accountLoader.getBank()
|
||||
}
|
||||
|
||||
@GetMapping("/materials")
|
||||
fun materials(): AccountMaterialView {
|
||||
return accountLoader.getMaterials()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.gw2.tools.api
|
||||
|
||||
import dev.sheldan.gw2.tools.service.CacheService
|
||||
import org.springframework.web.bind.annotation.PostMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RestController
|
||||
class CurrencyController(val cacheService: CacheService) {
|
||||
|
||||
@PostMapping("/currency-cache")
|
||||
fun updateCurrencyCache() {
|
||||
cacheService.reloadCurrencyCache()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package dev.sheldan.gw2.tools.api
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RestController
|
||||
class Health {
|
||||
@GetMapping("/health-check")
|
||||
fun healCheck(): String {
|
||||
return "yes"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package dev.sheldan.gw2.tools.api
|
||||
|
||||
import dev.sheldan.gw2.tools.loader.InventoryLoader
|
||||
import dev.sheldan.gw2.tools.models.AccountInventory
|
||||
import dev.sheldan.gw2.tools.models.AccountInventoryView
|
||||
import dev.sheldan.gw2.tools.models.CharacterInventory
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.PathVariable
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import org.springframework.web.context.annotation.RequestScope
|
||||
|
||||
@RestController
|
||||
@RequestScope
|
||||
class InventoryController(var inventoryLoader: InventoryLoader) {
|
||||
|
||||
@GetMapping("/inventory/{name}")
|
||||
fun characterInventory(@PathVariable("name") characterName: String): CharacterInventory {
|
||||
return inventoryLoader.getFullCharacterInventory(characterName)
|
||||
}
|
||||
|
||||
@GetMapping("/inventory")
|
||||
fun completeCharacterInventory(): AccountInventoryView {
|
||||
return inventoryLoader.getAccountInventory()
|
||||
}
|
||||
|
||||
@GetMapping("/sharedInventory")
|
||||
fun accountInventory(): AccountInventory {
|
||||
return inventoryLoader.getSharedInventory()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.gw2.tools.api
|
||||
|
||||
import dev.sheldan.gw2.tools.service.CacheService
|
||||
import org.springframework.web.bind.annotation.PostMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RestController
|
||||
class ItemController(val cacheService: CacheService) {
|
||||
|
||||
@PostMapping("/item-cache")
|
||||
fun updateItemCache() {
|
||||
cacheService.reloadItemCache()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package dev.sheldan.gw2.tools.api
|
||||
|
||||
import dev.sheldan.gw2.tools.config.ApiKeyInterceptor
|
||||
import dev.sheldan.gw2.tools.model.ItemRates
|
||||
import dev.sheldan.gw2.tools.model.OpeningRequest
|
||||
import dev.sheldan.gw2.tools.model.OpeningsView
|
||||
import dev.sheldan.gw2.tools.service.OpeningService
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import mu.KotlinLogging
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import org.springframework.web.context.annotation.RequestScope
|
||||
|
||||
@RestController
|
||||
@RequestScope
|
||||
class OpeningController(val openingService: OpeningService) {
|
||||
private val logger = KotlinLogging.logger {}
|
||||
|
||||
@PostMapping("/openings")
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
fun createOpenings(request: HttpServletRequest, @RequestBody openingRequest: OpeningRequest) {
|
||||
val apiKey: String = request.getHeader(ApiKeyInterceptor.API_KEY_HEADER_NAME) ?: throw IllegalArgumentException("API key not provided.")
|
||||
openingService.createOpening(openingRequest, apiKey)
|
||||
}
|
||||
|
||||
@GetMapping("/openings")
|
||||
fun getOpenings(request: HttpServletRequest, @RequestParam("showOwnOnly") ownOnly: String?): OpeningsView {
|
||||
val apiKey: String? = request.getHeader(ApiKeyInterceptor.API_KEY_HEADER_NAME)
|
||||
val showOnOnly = ownOnly.toBoolean()
|
||||
logger.info { "Retrieving openings" }
|
||||
val loadedOpenings = openingService.loadOpenings(apiKey, showOnOnly)
|
||||
logger.info { "Loaded ${loadedOpenings.openings.size} openings" }
|
||||
return loadedOpenings
|
||||
}
|
||||
|
||||
@DeleteMapping("/openings/{id}")
|
||||
fun deleteOpening(request: HttpServletRequest, @PathVariable("id") openingId: Int) {
|
||||
val apiKey: String = request.getHeader(ApiKeyInterceptor.API_KEY_HEADER_NAME) ?: throw IllegalArgumentException("API key not provided.")
|
||||
openingService.deleteOpening(apiKey, openingId)
|
||||
}
|
||||
|
||||
@GetMapping("/itemRates")
|
||||
fun getItemRates(): ItemRates {
|
||||
return openingService.loadItemRates()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package dev.sheldan.gw2.tools.api
|
||||
|
||||
import dev.sheldan.gw2.tools.ItemNotFoundException
|
||||
import dev.sheldan.gw2.tools.service.SubmissionTemplateService
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.*
|
||||
|
||||
@RestController
|
||||
class SubmissionTemplateController(
|
||||
val submissionTemplateService: SubmissionTemplateService
|
||||
) {
|
||||
@GetMapping("/submissionTemplates")
|
||||
@ResponseBody
|
||||
fun getSubmissionTemplatesForItem(@RequestParam("itemId") itemId: Int?): ResponseEntity<Any> {
|
||||
try {
|
||||
val responseObj = itemId?.let { submissionTemplateService.getSubmissionTemplateForItem(itemId) } ?: submissionTemplateService.getSubmissionTemplates()
|
||||
return ResponseEntity(responseObj, HttpStatus.OK)
|
||||
} catch (e: ItemNotFoundException) {
|
||||
return ResponseEntity(e.message, HttpStatus.BAD_REQUEST)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package dev.sheldan.gw2.tools.config
|
||||
|
||||
open class ApiKeyContainer : ApiKey {
|
||||
var apiKeyValue: String = "";
|
||||
override fun getApiKey(): String {
|
||||
return apiKeyValue
|
||||
}
|
||||
|
||||
override fun setApiKey(key: String) {
|
||||
this.apiKeyValue = key
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package dev.sheldan.gw2.tools.config
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.web.servlet.HandlerInterceptor
|
||||
|
||||
class ApiKeyInterceptor(private val apiKeyContainer: ApiKey) : HandlerInterceptor {
|
||||
|
||||
companion object {
|
||||
const val API_KEY_HEADER_NAME = "api-key"
|
||||
}
|
||||
|
||||
override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean {
|
||||
val apiKey: String? = request.getHeader(API_KEY_HEADER_NAME)
|
||||
apiKey?.let { apiKeyContainer.setApiKey(it) }
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package dev.sheldan.gw2.tools.config
|
||||
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.web.context.annotation.RequestScope
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
|
||||
|
||||
|
||||
@Configuration
|
||||
class HeaderInterceptorConfig : WebMvcConfigurer {
|
||||
override fun addInterceptors(registry: InterceptorRegistry) {
|
||||
registry.addInterceptor(apiKeyInterceptor())
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun apiKeyInterceptor(): ApiKeyInterceptor {
|
||||
return ApiKeyInterceptor(apiContainer())
|
||||
}
|
||||
|
||||
@Bean
|
||||
@RequestScope
|
||||
fun apiContainer(): ApiKeyContainer {
|
||||
return ApiKeyContainer()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package dev.sheldan.gw2.tools.model
|
||||
|
||||
|
||||
data class DisplayOpeningItem(val itemId: Int, val change: Int, val itemType: OpeningItemType) {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dev.sheldan.gw2.tools.model
|
||||
|
||||
class ItemDisplay(
|
||||
val id: Int,
|
||||
val name: String,
|
||||
val iconUrl: String,
|
||||
val description: String,
|
||||
val rarity: String
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package dev.sheldan.gw2.tools.model
|
||||
|
||||
import dev.sheldan.gw2.tools.models.EnrichedCurrency
|
||||
import dev.sheldan.gw2.tools.models.EnrichedItem
|
||||
|
||||
class ItemRate(val item: EnrichedItem, val receivedItems: List<EnrichedItem>, val receivedCurrencies: List<EnrichedCurrency>) {
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package dev.sheldan.gw2.tools.model
|
||||
|
||||
class ItemRates(val itemRates: List<ItemRate>) {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package dev.sheldan.gw2.tools.model
|
||||
|
||||
class ItemSubmissionTemplate(
|
||||
val submissionTemplates: List<SubmissionTemplateDisplay>,
|
||||
val item: ItemDisplay
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package dev.sheldan.gw2.tools.model
|
||||
|
||||
class ItemSubmissionTemplateList(
|
||||
val itemSubmissionTemplates: List<ItemSubmissionTemplate>
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package dev.sheldan.gw2.tools.model
|
||||
|
||||
enum class OpeningItemType {
|
||||
CURRENCY, ITEM
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package dev.sheldan.gw2.tools.model
|
||||
|
||||
data class OpeningRequest(
|
||||
val items: List<DisplayOpeningItem>,
|
||||
val description: String?=null,
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package dev.sheldan.gw2.tools.model
|
||||
|
||||
import dev.sheldan.gw2.tools.models.EnrichedCurrency
|
||||
import dev.sheldan.gw2.tools.models.EnrichedItem
|
||||
import java.time.Instant
|
||||
|
||||
class OpeningView(
|
||||
val itemChanges: List<EnrichedItem>,
|
||||
val currencyChanges: List<EnrichedCurrency>,
|
||||
val openingId: Int,
|
||||
val description: String?,
|
||||
val openingDate: Instant) {
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package dev.sheldan.gw2.tools.model
|
||||
|
||||
class OpeningsView(val openings: List<OpeningView>) {
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package dev.sheldan.gw2.tools.model
|
||||
|
||||
class SubmissionTemplateDisplay(
|
||||
val name: String,
|
||||
val description: String,
|
||||
val templateText: String
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package dev.sheldan.gw2.tools.service
|
||||
|
||||
import dev.sheldan.gw2.tools.loader.CurrencyLoader
|
||||
import dev.sheldan.gw2.tools.loader.ItemLoader
|
||||
import mu.KotlinLogging
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class CacheService(
|
||||
val itemLoader: ItemLoader,
|
||||
val itemManagement: ItemManagement,
|
||||
val currencyLoader: CurrencyLoader,
|
||||
val currencyManagement: CurrencyManagement
|
||||
) {
|
||||
|
||||
private val logger = KotlinLogging.logger {}
|
||||
fun reloadItemCache() {
|
||||
val allItemsApi = itemLoader.getAllItems().associateBy { it.id }
|
||||
logger.info { "Loaded ${allItemsApi.size} items from API" }
|
||||
val allItemsDb = itemManagement.getItems().associateBy { it.id }
|
||||
logger.info { "Loaded ${allItemsDb.size} items from DB" }
|
||||
val missingItems = allItemsApi.keys.minus(allItemsDb.keys)
|
||||
val newDbItems = missingItems.mapNotNull { itemId ->
|
||||
val item = allItemsApi[itemId]
|
||||
item?.let {
|
||||
itemManagement.createItem(
|
||||
it.id,
|
||||
item.name!!,
|
||||
item.description!!,
|
||||
item.iconUrl!!,
|
||||
it.type!!.name,
|
||||
item.rarity!!.name
|
||||
)
|
||||
}
|
||||
}.toList()
|
||||
logger.info { "Creating ${newDbItems.size} new items" }
|
||||
itemManagement.saveItems(newDbItems)
|
||||
|
||||
}
|
||||
|
||||
fun reloadCurrencyCache() {
|
||||
val allCurrenciesApi = currencyLoader.getAllCurrencies().associateBy { it.id }
|
||||
logger.info { "Loaded ${allCurrenciesApi.size} currencies from API" }
|
||||
val allCurrenciesDb = currencyManagement.getCurrencies().associateBy { it.id }
|
||||
logger.info { "Loaded ${allCurrenciesDb.size} currencies from DB" }
|
||||
val missingCurrencies = allCurrenciesApi.keys.minus(allCurrenciesDb.keys)
|
||||
val newDbCurrencies = missingCurrencies.mapNotNull {
|
||||
itemId ->
|
||||
val item = allCurrenciesApi[itemId]
|
||||
item?.let {
|
||||
currencyManagement.createCurrency(
|
||||
it.id,
|
||||
item.name,
|
||||
item.description,
|
||||
item.iconUrl
|
||||
)
|
||||
}
|
||||
}
|
||||
logger.info { "Creating ${newDbCurrencies.size} new items" }
|
||||
currencyManagement.saveCurrencies(newDbCurrencies)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package dev.sheldan.gw2.tools.service
|
||||
|
||||
import dev.sheldan.gw2.tools.entity.Currency
|
||||
import dev.sheldan.gw2.tools.entity.Item
|
||||
import dev.sheldan.gw2.tools.entity.Opening
|
||||
import dev.sheldan.gw2.tools.entity.OpeningItem
|
||||
import dev.sheldan.gw2.tools.model.*
|
||||
import dev.sheldan.gw2.tools.models.EnrichedCurrency
|
||||
import dev.sheldan.gw2.tools.models.EnrichedItem
|
||||
import dev.sheldan.gw2.tools.models.Gw2TItemType
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class OpeningService(
|
||||
val userManagement: UserManagement,
|
||||
val openingManagement: OpeningManagement,
|
||||
val itemManagement: ItemManagement,
|
||||
val currencyManagement: CurrencyManagement
|
||||
) {
|
||||
fun createOpening(openingRequest: OpeningRequest, token: String) {
|
||||
val user = userManagement.getOrCreateUser(token)
|
||||
val itemsWithIds = openingRequest.items.filter { it.itemType == OpeningItemType.ITEM }.associateBy { it.itemId }
|
||||
val fullItems =
|
||||
itemManagement.getItems(itemsWithIds.keys.toList()).associateWith { itemsWithIds[it.id]!!.change }
|
||||
val currenciesWithIds =
|
||||
openingRequest.items.filter { it.itemType == OpeningItemType.CURRENCY }.associateBy { it.itemId }
|
||||
val fullCurrencies = currencyManagement.getCurrencies(currenciesWithIds.keys.toList())
|
||||
.associateWith { currenciesWithIds[it.id]!!.change }
|
||||
openingManagement.createOpening(user, fullItems, fullCurrencies, openingRequest.description)
|
||||
}
|
||||
|
||||
fun loadOpenings(token: String?, ownOnly: Boolean): OpeningsView {
|
||||
val openings: List<Opening>;
|
||||
if (ownOnly && token != null) {
|
||||
val user = userManagement.getOrCreateUser(token)
|
||||
openings = openingManagement.getOpeningsByUser(user)
|
||||
} else {
|
||||
openings = openingManagement.getAllOpenings()
|
||||
}
|
||||
val items = openings.filter { it.items != null }.flatMap { it.items!! }
|
||||
val itemIds = items.map { it.item.id }
|
||||
val loadedItemsMap = itemManagement.getItemsAsMap(itemIds)
|
||||
val currencies = openings.filter { it.currencies != null }.flatMap { it.currencies!! }
|
||||
val currencyIds = currencies.map { it.currency.id }
|
||||
val loadedCurrenciesMapMap = currencyManagement.getCurrenciesAsMap(currencyIds)
|
||||
val openingViews = openings.map { convertOpening(it, loadedItemsMap, loadedCurrenciesMapMap) }
|
||||
return OpeningsView(openingViews)
|
||||
}
|
||||
|
||||
fun deleteOpening(token: String, openingId: Int) {
|
||||
val user = userManagement.getOrCreateUser(token)
|
||||
val opening = openingManagement.getOpening(openingId)
|
||||
opening.map {
|
||||
if (user.id == it.user.id) {
|
||||
openingManagement.deleteOpening(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun convertOpening(opening: Opening, itemMap: Map<Int, Item>, currencyMap: Map<Int, Currency>): OpeningView {
|
||||
val items = mutableListOf<EnrichedItem>()
|
||||
opening.items?.mapNotNull {
|
||||
val enrichedItem = EnrichedItem(it.item.id, it.count)
|
||||
itemMap[it.item.id]?.let { item ->
|
||||
enrichedItem.setValuesFromDbItem(item)
|
||||
return@mapNotNull enrichedItem
|
||||
}
|
||||
}?.let { items.addAll(it) }
|
||||
val currencies = mutableListOf<EnrichedCurrency>()
|
||||
opening.currencies?.mapNotNull {
|
||||
currencyMap[it.currency.id]?.let { currency ->
|
||||
EnrichedCurrency(currency.id, it.amount, currency.name, currency.description, currency.iconUrl)
|
||||
}
|
||||
}?.let { currencies.addAll(it) }
|
||||
return OpeningView(items, currencies, opening.id!!, opening.description, opening.creationDate!!)
|
||||
}
|
||||
|
||||
fun loadItemRates(): ItemRates {
|
||||
val openings = openingManagement.getAllOpenings()
|
||||
val presentItems = openings.filter { it.items != null }.flatMap { it.items!! }.map { it.item }
|
||||
val presentCurrencies = openings.filter { it.currencies != null }.flatMap { it.currencies!! }.map { it.currency }
|
||||
val itemIds = presentItems.map { it.id }
|
||||
val currencyIds = presentCurrencies.map { it.id }
|
||||
val loadedItemsMap = itemManagement.getItemsAsMap(itemIds)
|
||||
val loadedCurrenciesMap = currencyManagement.getCurrenciesAsMap(currencyIds)
|
||||
val allItems = openings.mapNotNull { opening ->
|
||||
val containers = getListOfContainersFromOpening(opening)
|
||||
if(containers.size == 1) {
|
||||
val containerOpeningItem = containers[0]
|
||||
val enrichedContainerItem = EnrichedItem(containerOpeningItem.item.id, containerOpeningItem.count)
|
||||
loadedItemsMap[containerOpeningItem.item.id]?.let { item ->
|
||||
enrichedContainerItem.setValuesFromDbItem(item)
|
||||
}
|
||||
val resultingItems = opening.items?.filter { it.count > 0 }?.mapNotNull itemMap@ {
|
||||
val enrichedItem = EnrichedItem(it.item.id, it.count)
|
||||
loadedItemsMap[it.item.id]?.let { item ->
|
||||
enrichedItem.setValuesFromDbItem(item)
|
||||
return@itemMap enrichedItem
|
||||
}
|
||||
}?: listOf()
|
||||
val resultingCurrencies = opening.currencies?.filter { it.amount > 0 }?.mapNotNull currencyMap@ {
|
||||
loadedCurrenciesMap[it.currency.id]?.let { currency ->
|
||||
val enrichedCurrency = EnrichedCurrency(it.currency.id, it.amount, currency.name, currency.description, currency.iconUrl)
|
||||
return@currencyMap enrichedCurrency
|
||||
}
|
||||
}?: listOf()
|
||||
return@mapNotNull ItemRate(enrichedContainerItem, resultingItems, resultingCurrencies)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
val itemRateMap = mutableMapOf<Int, ItemRate>()
|
||||
allItems.forEach{ item ->
|
||||
itemRateMap[item.item.id]?.let { itemRate ->
|
||||
val existingEnrichedItems = itemRate.receivedItems.associateBy { receivedItem -> receivedItem.id }
|
||||
item.receivedItems.forEach{receivedItem ->
|
||||
existingEnrichedItems[receivedItem.id]?.let{
|
||||
it.count += receivedItem.count
|
||||
}?: itemRate.receivedItems.addLast(receivedItem)
|
||||
}
|
||||
val existingEnrichedCurrencies = itemRate.receivedCurrencies.associateBy { receivedCurrency -> receivedCurrency.id }
|
||||
item.receivedCurrencies.forEach{receivedCurrency ->
|
||||
existingEnrichedCurrencies[receivedCurrency.id]?.let{
|
||||
it.amount += receivedCurrency.amount
|
||||
}?: itemRate.receivedCurrencies.addLast(receivedCurrency)
|
||||
}
|
||||
itemRate.item.count += item.item.count
|
||||
}?: itemRateMap.put(item.item.id, item)
|
||||
}
|
||||
return ItemRates(itemRateMap.values.toList())
|
||||
}
|
||||
|
||||
private fun getListOfContainersFromOpening(opening: Opening): List<OpeningItem> {
|
||||
return opening.items?.filter { item -> item.count < 0 && item.item.type == Gw2TItemType.CONTAINER.name } ?: listOf()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package dev.sheldan.gw2.tools.service
|
||||
|
||||
import dev.sheldan.gw2.tools.ItemNotFoundException
|
||||
import dev.sheldan.gw2.tools.model.ItemDisplay
|
||||
import dev.sheldan.gw2.tools.model.SubmissionTemplateDisplay
|
||||
import dev.sheldan.gw2.tools.model.ItemSubmissionTemplate
|
||||
import dev.sheldan.gw2.tools.model.ItemSubmissionTemplateList
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class SubmissionTemplateService(
|
||||
val submissionTemplateManagement: SubmissionTemplateManagement,
|
||||
val itemManagement: ItemManagement
|
||||
) {
|
||||
fun getSubmissionTemplateForItem(itemId: Int): ItemSubmissionTemplate {
|
||||
val item = itemManagement.getItem(itemId)?: throw ItemNotFoundException("Item not found.")
|
||||
val submissionTemplates = submissionTemplateManagement.getSubmissionTemplatesForItem(item)
|
||||
val itemDisplay = ItemDisplay(item.id, item.name, item.iconUrl, item.description, item.rarity)
|
||||
val templateDisplays = submissionTemplates.map {
|
||||
SubmissionTemplateDisplay(it.name, it.description, it.templateText)
|
||||
}
|
||||
return ItemSubmissionTemplate(templateDisplays, itemDisplay)
|
||||
}
|
||||
|
||||
fun getSubmissionTemplates(): ItemSubmissionTemplateList {
|
||||
val submissionTemplates = submissionTemplateManagement.getAllSubmissionTemplates()
|
||||
val items = submissionTemplates.associateBy { it.item }.keys
|
||||
val itemSubmissionTemplates = items.map { item ->
|
||||
val itemDisplay = ItemDisplay(item.id, item.name, item.iconUrl, item.description, item.rarity)
|
||||
val submissionTemplatesOfItem = submissionTemplates.filter { it.item.id == item.id }
|
||||
val templateDisplays = submissionTemplatesOfItem.map {
|
||||
SubmissionTemplateDisplay(it.name, it.description, it.templateText)
|
||||
}
|
||||
ItemSubmissionTemplate(templateDisplays, itemDisplay)
|
||||
}
|
||||
return ItemSubmissionTemplateList(itemSubmissionTemplates)
|
||||
}
|
||||
}
|
||||
19
gw2-tools-backend/settings.xml
Normal file
19
gw2-tools-backend/settings.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
|
||||
http://maven.apache.org/xsd/settings-1.0.0.xsd">
|
||||
|
||||
<servers>
|
||||
<server>
|
||||
<id>github</id>
|
||||
<configuration>
|
||||
<httpHeaders>
|
||||
<property>
|
||||
<name>Authorization</name>
|
||||
<value>Bearer ${env.GITHUB_TOKEN}</value>
|
||||
</property>
|
||||
</httpHeaders>
|
||||
</configuration>
|
||||
</server>
|
||||
</servers>
|
||||
</settings>
|
||||
Reference in New Issue
Block a user