Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extra fields in CombatReportSummary and new object FullCombatReport #65

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cmd/ogamed/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@ func start(c *cli.Context) error {
e.POST("/bot/delete-report/:messageID", ogame.DeleteMessageHandler)
e.POST("/bot/delete-all-espionage-reports", ogame.DeleteEspionageMessagesHandler)
e.POST("/bot/delete-all-reports/:tabIndex", ogame.DeleteMessagesFromTabHandler)
e.GET("/bot/combat-report/:msgid", ogame.GetCombatReportHandler) // returns FullCombatReport, it returns the JSON from inside the CombatReport. There is no JSON in EspionageReport.
e.GET("/bot/combat-report/:galaxy/:system/:position", ogame.GetCombatReportForHandler) // returns []CombatReportSummary
e.GET("/bot/combat-report", ogame.GetCombatReportMessagesHandler) // returns []CombatReportSummary
e.GET("/bot/attacks", ogame.GetAttacksHandler)
e.GET("/bot/get-auction", ogame.GetAuctionHandler)
e.POST("/bot/do-auction", ogame.DoAuctionHandler)
Expand Down
6 changes: 6 additions & 0 deletions extractor_v6.go
Original file line number Diff line number Diff line change
Expand Up @@ -781,3 +781,9 @@ func (e ExtractorV6) ExtractDMCosts(pageHTML []byte) (DMCosts, error) {
func (e ExtractorV6) ExtractBuffActivation(pageHTML []byte) (string, []Item, error) {
panic("not implemented")
}

// ExtractFullCombatReport ...
func (e ExtractorV6) ExtractFullCombatReport(pageHTML []byte, msgID int64) (FullCombatReport, error) {
doc, _ := goquery.NewDocumentFromReader(bytes.NewReader(pageHTML))
return extractFullCombatReportFromDoc(doc, msgID)
}
11 changes: 11 additions & 0 deletions extractor_v71.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,14 @@ func (e ExtractorV71) ExtractBuffActivation(pageHTML []byte) (string, []Item, er
func (e ExtractorV71) ExtractBuffActivationFromDoc(doc *goquery.Document) (string, []Item, error) {
return extractBuffActivationFromDocV71(doc)
}

// ExtractCombatReportMessagesSummary ...
func (e ExtractorV71) ExtractCombatReportMessagesSummary(pageHTML []byte) ([]CombatReportSummary, int64) {
doc, _ := goquery.NewDocumentFromReader(bytes.NewReader(pageHTML))
return e.ExtractCombatReportMessagesSummaryFromDoc(doc)
}

// ExtractCombatReportMessagesSummaryFromDoc ...
func (e ExtractorV71) ExtractCombatReportMessagesSummaryFromDoc(doc *goquery.Document) ([]CombatReportSummary, int64) {
return extractCombatReportMessagesSummaryFromDocV71(doc)
}
1 change: 1 addition & 0 deletions extracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ type Extractor interface {
ExtractAllResources(pageHTML []byte) (map[CelestialID]Resources, error)
ExtractDMCosts(pageHTML []byte) (DMCosts, error)
ExtractBuffActivation(pageHTML []byte) (string, []Item, error)
ExtractFullCombatReport(pageHTML []byte, msgID int64) (FullCombatReport, error)
}

// Compile time checks to ensure type satisfies Extractor interface
Expand Down
53 changes: 53 additions & 0 deletions extracts_v6.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"strings"
"time"

"log"

"github.com/PuerkitoBio/goquery"
"github.com/alaingilbert/clockwork"
lua "github.com/yuin/gopher-lua"
Expand Down Expand Up @@ -662,6 +664,8 @@ func extractCombatReportMessagesFromDocV6(doc *goquery.Document) ([]CombatReport
if idStr, exists := s.Attr("data-msg-id"); exists {
if id, err := strconv.ParseInt(idStr, 10, 64); err == nil {
report := CombatReportSummary{ID: id}

// Find destination coordinate
report.Destination = extractCoordV6(s.Find("div.msg_head a").Text())
if s.Find("div.msg_head figure").HasClass("planet") {
report.Destination.Type = PlanetType
Expand All @@ -670,23 +674,50 @@ func extractCombatReportMessagesFromDocV6(doc *goquery.Document) ([]CombatReport
} else {
report.Destination.Type = PlanetType
}

// Find looted resources {Metal, Crystal, Deuterium}
resTitle := s.Find("span.msg_content div.combatLeftSide span").Eq(1).AttrOr("title", "")
m := regexp.MustCompile(`([\d.]+)<br/>[^\d]*([\d.]+)<br/>[^\d]*([\d.]+)`).FindStringSubmatch(resTitle)
if len(m) == 4 {
report.Metal = ParseInt(m[1])
report.Crystal = ParseInt(m[2])
report.Deuterium = ParseInt(m[3])
}

// Find debris field
debrisFieldTitle := s.Find("span.msg_content div.combatLeftSide span").Eq(2).AttrOr("title", "0")
report.DebrisField = ParseInt(debrisFieldTitle)

// Find Loot (%) or Total Looted resources TODO
resText := s.Find("span.msg_content div.combatLeftSide span").Eq(1).Text()
m = regexp.MustCompile(`[\d.]+[^\d]*([\d.]+)`).FindStringSubmatch(resText)
if len(m) == 2 {
report.Loot = ParseInt(m[1])
}

// Find Date
msgDate, _ := time.Parse("02.01.2006 15:04:05", s.Find("span.msg_date").Text())
report.CreatedAt = msgDate

// Find: attacker name
report.AttackerName = ""
attacker := s.Find("span.msg_content div.combatLeftSide span").Eq(0).Text()
m = regexp.MustCompile(`\((.*)\)`).FindStringSubmatch(attacker)

if len(m) > 0 {
report.AttackerName = m[1]
}

// Find: Defender name
report.DefenderName = ""
defender := s.Find("span.msg_content div.combatRightSide span").Eq(0).Text()
m = regexp.MustCompile(`\((.*)\)`).FindStringSubmatch(defender)

if len(m) > 0 {
report.DefenderName = m[1]
}

// Find origin coordinate
link := s.Find("div.msg_actions a span.icon_attack").Parent().AttrOr("href", "")
m = regexp.MustCompile(`page=fleet1&galaxy=(\d+)&system=(\d+)&position=(\d+)&type=(\d+)&`).FindStringSubmatch(link)
if len(m) != 5 {
Expand All @@ -697,6 +728,7 @@ func extractCombatReportMessagesFromDocV6(doc *goquery.Document) ([]CombatReport
position, _ := strconv.ParseInt(m[3], 10, 64)
planetType, _ := strconv.ParseInt(m[4], 10, 64)
report.Origin = &Coordinate{galaxy, system, position, CelestialType(planetType)}

if report.Origin.Equal(report.Destination) {
report.Origin = nil
}
Expand Down Expand Up @@ -2122,3 +2154,24 @@ func extractAuctionFromDoc(doc *goquery.Document) (Auction, error) {

return auction, nil
}

func extractFullCombatReportFromDoc(doc *goquery.Document, msgID int64) (FullCombatReport, error) {
log.SetFlags(log.LstdFlags | log.Lshortfile)

report := FullCombatReport{}
report.ID = msgID

scriptHTMLText := doc.Find("script").First().Text()

m := regexp.MustCompile(`parseJSON\(\'(.*)\'\);`).FindStringSubmatch(scriptHTMLText)

if len(m) == 2 {
if err := json.Unmarshal([]byte(m[1]), &report.Content); err != nil {
return FullCombatReport{}, err
}

return report, nil
}

return FullCombatReport{}, errors.New("Unable to find JSON in this CombatReport")
}
98 changes: 98 additions & 0 deletions extracts_v71.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"strings"
"time"

"log"

"github.com/PuerkitoBio/goquery"
"github.com/alaingilbert/clockwork"
"golang.org/x/net/html"
Expand Down Expand Up @@ -806,3 +808,99 @@ func extractBuffActivationFromDocV71(doc *goquery.Document) (token string, items
}
return
}

func extractCombatReportMessagesSummaryFromDocV71(doc *goquery.Document) ([]CombatReportSummary, int64) {
log.SetFlags(log.LstdFlags | log.Lshortfile)
msgs := make([]CombatReportSummary, 0)
nbPage, _ := strconv.ParseInt(doc.Find("ul.pagination li").Last().AttrOr("data-page", "1"), 10, 64)
doc.Find("li.msg").Each(func(i int, s *goquery.Selection) {
if idStr, exists := s.Attr("data-msg-id"); exists {
if id, err := strconv.ParseInt(idStr, 10, 64); err == nil {
report := CombatReportSummary{ID: id}

// Find destination coordinate
report.Destination = extractCoordV6(s.Find("div.msg_head a").Text())
if s.Find("div.msg_head figure").HasClass("planet") {
report.Destination.Type = PlanetType
} else if s.Find("div.msg_head figure").HasClass("moon") {
report.Destination.Type = MoonType
} else {
report.Destination.Type = PlanetType
}

// Find looted resources {Metal, Crystal, Deuterium}
resTitle := s.Find("span.msg_content div.combatLeftSide span").Eq(1).AttrOr("title", "")
m := regexp.MustCompile(`([\d.]+)<br/>[^\d]*([\d.]+)<br/>[^\d]*([\d.]+)`).FindStringSubmatch(resTitle)
if len(m) == 4 {
report.Metal = ParseInt(m[1])
report.Crystal = ParseInt(m[2])
report.Deuterium = ParseInt(m[3])
}

// Find debris field
report.DebrisField = ParseInt(s.Find("span.msg_content div.combatLeftSide span").Eq(2).AttrOr("title", "0"))

// Find Loot (%)
resText := s.Find("span.msg_content div.combatLeftSide span").Eq(1).Text()
m = regexp.MustCompile(`(\d+)\%`).FindStringSubmatch(resText)
if len(m) > 0 {
// NL = Grondstoffen: 4,883M, buit: 50%
// EN = Resources: 1.958Mn, Loot: 50%
report.Loot = ParseInt(m[len(m)-1]) // Find last item , as NL language uses "," as thousand-separator instead of "." in EN.
}

// Find Date
msgDate, _ := time.Parse("02.01.2006 15:04:05", s.Find("span.msg_date").Text())
report.CreatedAt = msgDate

// Find: AttackerName and AttackerLostValue
attacker := s.Find("span.msg_content div.combatLeftSide span").Eq(0)
report.AttackerLostValue = ParseInt(attacker.AttrOr("title", "0"))
m = regexp.MustCompile(`\((.*)\)`).FindStringSubmatch(attacker.Text())
if len(m) == 2 {
report.AttackerName = m[1]
}

// Find: DefenderName and DefenderLostValue
defender := s.Find("span.msg_content div.combatRightSide span").Eq(0)
report.DefenderLostValue = ParseInt(defender.AttrOr("title", "0"))
m = regexp.MustCompile(`\((.*)\)`).FindStringSubmatch(defender.Text())
if len(m) == 2 {
report.DefenderName = m[1]
}

// Find origin coordinate
link := s.Find("div.msg_actions a span.icon_attack").Parent().AttrOr("href", "")
m = regexp.MustCompile(`page=ingame&component=fleetdispatch&galaxy=(\d+)&system=(\d+)&position=(\d+)&type=(\d+)&`).FindStringSubmatch(link)
if len(m) == 5 {
galaxy := ParseInt(m[1])
system := ParseInt(m[2])
position := ParseInt(m[3])
planetType := ParseInt(m[4])
report.Origin = &Coordinate{galaxy, system, position, CelestialType(planetType)}

if report.Origin.Equal(report.Destination) {
report.Origin = nil
}
}

// Find APIKey
apikey := s.Find("span.icon_apikey").AttrOr("title", "")
if len(apikey) > 0 {
apiDoc, _ := goquery.NewDocumentFromReader(strings.NewReader(apikey))
report.APIKey = apiDoc.Find("input").First().AttrOr("value", "")
}

// Find Repaired
// Actually repaired: 0
repaired := s.Find("div.combatRightSide").Find("span.msg_ctn3").First().AttrOr("title", "")
if len(repaired) > 0 {
report.Repaired = ParseInt(repaired)
}

msgs = append(msgs, report)
}
}
})
return msgs, nbPage
}
50 changes: 50 additions & 0 deletions handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -1160,3 +1160,53 @@ func PhalanxHandler(c echo.Context) error {
}
return c.JSON(http.StatusOK, SuccessResp(fleets))
}

// GetCombatReportMessagesHandler ...
func GetCombatReportMessagesHandler(c echo.Context) error {
bot := c.Get("bot").(*OGame)

report, err := bot.getCombatReportMessages()
if err != nil {
return c.JSON(http.StatusInternalServerError, ErrorResp(500, err.Error()))
}
return c.JSON(http.StatusOK, SuccessResp(report))
}

// FullCombatReport, takes JSON from CR message. There is no JSON in EspionageReport.
func GetCombatReportHandler(c echo.Context) error {
bot := c.Get("bot").(*OGame)

msgID, err := strconv.ParseInt(c.Param("msgid"), 10, 64)
if err != nil {
return c.JSON(http.StatusBadRequest, ErrorResp(400, "invalid msgid id"))
}
combatReport, err := bot.GetFullCombatReport(msgID)
if err != nil {
return c.JSON(http.StatusInternalServerError, ErrorResp(500, err.Error()))
}
return c.JSON(http.StatusOK, SuccessResp(combatReport))
}

// GetCombatReportForHandler ...
func GetCombatReportForHandler(c echo.Context) error {
bot := c.Get("bot").(*OGame)

galaxy, err := strconv.ParseInt(c.Param("galaxy"), 10, 64)
if err != nil {
return c.JSON(http.StatusBadRequest, ErrorResp(400, "invalid galaxy"))
}
system, err := strconv.ParseInt(c.Param("system"), 10, 64)
if err != nil {
return c.JSON(http.StatusBadRequest, ErrorResp(400, "invalid system"))
}
position, err := strconv.ParseInt(c.Param("position"), 10, 64)
if err != nil {
return c.JSON(http.StatusBadRequest, ErrorResp(400, "invalid position"))
}

planet, err := bot.getCombatReportFor(Coordinate{Type: PlanetType, Galaxy: galaxy, System: system, Position: position})
if err != nil {
return c.JSON(http.StatusInternalServerError, ErrorResp(500, err.Error()))
}
return c.JSON(http.StatusOK, SuccessResp(planet))
}
13 changes: 13 additions & 0 deletions ogame.go
Original file line number Diff line number Diff line change
Expand Up @@ -3344,11 +3344,14 @@ type CombatReportSummary struct {
Destination Coordinate
AttackerName string
DefenderName string
AttackerLostValue int64
DefenderLostValue int64
Loot int64
Metal int64
Crystal int64
Deuterium int64
DebrisField int64
Repaired int64
CreatedAt time.Time
}

Expand Down Expand Up @@ -4381,6 +4384,16 @@ func (b *OGame) GetEmpire(nbr int64) (interface{}, error) {
return b.WithPriority(Normal).GetEmpire(nbr)
}

type FullCombatReport struct {
ID int64
Content interface{}
}

func (b *OGame) GetFullCombatReport(msgID int64) (FullCombatReport, error) {
pageHTML, _ := b.getPageContent(url.Values{"page": {"messages"}, "messageId": {strconv.FormatInt(msgID, 10)}, "tabid": {"21"}, "ajax": {"1"}})
return b.extractor.ExtractFullCombatReport(pageHTML, msgID)
}

// CharacterClass returns the bot character class
func (b *OGame) CharacterClass() CharacterClass {
return b.characterClass
Expand Down
Loading