A Go wrapper for querying open ElasticSearch (ES) service from Shroud of the Avatar: Forsaken Virtues (SotA) events log.
Inspired by rthompsonj/SotAPublicStatsQuery.
- go ^= v1.14
- go-elasticsearch ^= v7.8
Add Gosta to your go.mod
file by adding this line:
require github.com/wisn/gosta
Or simply run go get github.com/wisn/gosta
command.
Don't forget to run go mod tidy
and go mod verify
.
Currently, there are two methods available. Another method will be coming shortly after I have conducted some research with the events log data. After all, we need a library with a good documentation so we can use it with ease.
The RawQuery
method use map[string]interface{}
as the input and will
returns (map[string]interface{}, error)
pair. We can freely query ES events
log as long as we understand how to do it. Here is an example for querying
all kind of LocationEvent
types and sort the records by @timeline
in the
descending manner.
package main
import (
"log"
"github.com/wisn/gosta"
)
func main() {
cfg := gosta.Config{
Host: "http://shroudoftheavatar.com",
Port: 9200,
}
gst, err := gosta.New(cfg)
if err != nil {
log.Fatal(err)
}
qry := map[string]interface{}{
"size": 2,
"sort": []map[string]interface{}{
map[string]interface{}{
"@timestamp": map[string]interface{}{
"order": "desc",
"unmapped_type": "boolean",
},
},
},
"query": map[string]interface{}{
"bool": map[string]interface{}{
"must": []map[string]interface{}{
map[string]interface{}{
"query_string": map[string]interface{}{
"analyze_wildcard": true,
"query": "LocationEvent:*", // here is the query
},
},
},
},
},
}
res, err := gst.RawQuery(qry)
if err != nil {
log.Fatal(err)
}
// print as map[string]interface{} type
log.Println(res)
// print as a JSON in the string form
json, err := gst.JSON(res)
if err != nil {
log.Fatal(err)
}
log.Println(json)
}
The RawQuery
method might be annoying for some people. Hence, there is
RawQueryStr
method that use JSON format (in the form of string
) as
the input and will returns (map[string]interface{}, error)
pair. The
input argument used below is equivalent with the one that used by
RawQuery
above.
package main
import (
"log"
"github.com/wisn/gosta"
)
func main() {
cfg := gosta.Config{
Host: "http://shroudoftheavatar.com",
Port: 9200,
}
gst, err := gosta.New(cfg)
if err != nil {
log.Fatal(err)
}
qry := `
{
"size": 2,
"sort": [
{
"@timestamp": {
"order": "desc",
"unmapped_type": "boolean"
}
}
],
"query": {
"bool": {
"must": [
{
"query_string": {
"analyze_wildcard": true,
"query": "LocationEvent:*"
}
}
]
}
}
}
`
res, err := gst.RawQueryStr(qry)
if err != nil {
log.Fatal(err)
}
// print as map[string]interface{} type
log.Println(res)
// print as a JSON in the string form
json, err := gst.JSON(res)
if err != nil {
log.Fatal(err)
}
log.Println(json)
}
map[_shards:map[failed:0 skipped:0 successful:152 total:152] hits:map[hits:[map[_id:NUaNxHMB9DlaFXTY4AYT _index:logstash-2020.08.06 _score:<nil> _source:map[@timestamp:2020-08-06T16:15:00.000Z Archetype:Consumables/Potions/ItemPotion_Haste EconomyGoldDelta:10 GoldValue:10 ItemId:5f2c2c7e4d97a54074436337 LocationEvent:ItemGained_Loot Quantity:1 SceneName:The Rise timestamp:Aug 06 11:15:00 xpos:-1.318 ypos:10.095 zpos:73.121] _type:doc sort:[1.5967305e+12]] map[_id:VUaNxHMB9DlaFXTY5QYc _index:logstash-2020.08.06 _score:<nil> _source:map[@timestamp:2020-08-06T16:15:00.000Z Archetype:Consumables/Misc/ItemConsume_Recall EconomyGoldDelta:15 GoldValue:15 ItemId:5f2c2c854d97a54074436408 LocationEvent:ItemGained_Loot Quantity:1 SceneName:PlayerDungeon_GreyStone timestamp:Aug 06 11:15:00 xpos:75.351 ypos:0.008 zpos:-83.72] _type:doc sort:[1.5967305e+12]]] max_score:<nil> total:1.5974755e+07] timed_out:false took:327]
{"_shards":{"failed":0,"skipped":0,"successful":152,"total":152},"hits":{"hits":[{"_id":"NUaNxHMB9DlaFXTY4AYT","_index":"logstash-2020.08.06","_score":null,"_source":{"@timestamp":"2020-08-06T16:15:00.000Z","Archetype":"Consumables/Potions/ItemPotion_Haste","EconomyGoldDelta":"10","GoldValue":"10","ItemId":"5f2c2c7e4d97a54074436337","LocationEvent":"ItemGained_Loot","Quantity":"1","SceneName":"The Rise","timestamp":"Aug 06 11:15:00","xpos":"-1.318","ypos":"10.095","zpos":"73.121"},"_type":"doc","sort":[1596730500000]},{"_id":"VUaNxHMB9DlaFXTY5QYc","_index":"logstash-2020.08.06","_score":null,"_source":{"@timestamp":"2020-08-06T16:15:00.000Z","Archetype":"Consumables/Misc/ItemConsume_Recall","EconomyGoldDelta":"15","GoldValue":"15","ItemId":"5f2c2c854d97a54074436408","LocationEvent":"ItemGained_Loot","Quantity":"1","SceneName":"PlayerDungeon_GreyStone","timestamp":"Aug 06 11:15:00","xpos":"75.351","ypos":"0.008","zpos":"-83.72"},"_type":"doc","sort":[1596730500000]}],"max_score":null,"total":15976177},"timed_out":false,"took":325}
Gosta following the Semantic Versioning 2.0.0.
Here is the roadmap that I could thought so far. Of course this roadmap is subject to change in the future.
Initial release.
First minor release for v1 will adding some features such as:
QueryGainedLoot
, targetingLocationEvent:ItemGained_Loot
event log. There will be some arguments for building the query so we can fetch a specific records.QueryPvEDeaths
, targetingLocationEvent:PlayerKilledByMonster
event log.QueryPvEKills
, targetingLocationEvent:MonsterKilledByPlayer
event log.
This minor release will be focusing on merchant related stuff. At least two of them will be covered.
QueryItemSold
, targetingLocationEvent:ItemGained_Merchant
event log.QueryItemForSale
, targetingLocationEvent:ItemDestroyed_Merchant
event log.
This minor release will be focusing on crafting related stuff. Something like:
QueryCraftedItem
, targetingLocationEvent:ItemGained_Crafting
event log. As forLocationEvent:ItemDestroyed_Crafting
, I need to conduct a research before designing the method so this will be updated later on.
This minor release will be focusing on PvP related stuff.
QueryPvPDeaths
, targetingLocationEvent:PlayerKilledByPlayer
event log.QueryPvPKills
, targetingLocationEvent:PlayerKilledByPlayer
event log.
Since there are a lot of things to do, a pull request will be ignored at the moment. However, an issue will be welcomed!
The pull request will be opened after the contributing guideline is ready.
The code itself licensed under The MIT License.