diff --git a/cmd/ogamed/main.go b/cmd/ogamed/main.go index 3090ee3d..7b447f83 100644 --- a/cmd/ogamed/main.go +++ b/cmd/ogamed/main.go @@ -250,9 +250,9 @@ func start(c *cli.Context) error { e.GET("/bot/fleets", ogame.GetFleetsHandler) e.GET("/bot/fleets/slots", ogame.GetSlotsHandler) e.POST("/bot/fleets/:fleetID/cancel", ogame.CancelFleetHandler) - e.GET("/bot/espionage-report/:msgid", ogame.GetEspionageReportHandler) - e.GET("/bot/espionage-report/:galaxy/:system/:position", ogame.GetEspionageReportForHandler) - e.GET("/bot/espionage-report", ogame.GetEspionageReportMessagesHandler) + e.GET("/bot/espionage-report/:msgid", ogame.GetEspionageReportHandler) // returns EspionageReport + e.GET("/bot/espionage-report/:galaxy/:system/:position", ogame.GetEspionageReportForHandler) // returns EspionageReport + e.GET("/bot/espionage-report", ogame.GetEspionageReportMessagesHandler) // returns []EspionageReportSummary 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) diff --git a/extractor_v71.go b/extractor_v71.go index 13997412..54dc3358 100644 --- a/extractor_v71.go +++ b/extractor_v71.go @@ -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) } + +// ExtractEspionageReportMessageIDs ... +func (e ExtractorV71) ExtractEspionageReportMessageIDs(pageHTML []byte) ([]EspionageReportSummary, int64) { + doc, _ := goquery.NewDocumentFromReader(bytes.NewReader(pageHTML)) + return e.ExtractEspionageReportMessageIDsFromDoc(doc) +} + +// ExtractEspionageReportMessageIDsFromDoc ... +func (e ExtractorV71) ExtractEspionageReportMessageIDsFromDoc(doc *goquery.Document) ([]EspionageReportSummary, int64) { + return extractEspionageReportMessageIDsFromDocV71(doc) +} diff --git a/extracts_v6.go b/extracts_v6.go index 8137348e..8132c6a2 100644 --- a/extracts_v6.go +++ b/extracts_v6.go @@ -11,6 +11,8 @@ import ( "strings" "time" + "log" + "github.com/PuerkitoBio/goquery" "github.com/alaingilbert/clockwork" lua "github.com/yuin/gopher-lua" @@ -644,6 +646,8 @@ func extractEspionageReportMessageIDsFromDocV6(doc *goquery.Document) ([]Espiona } report := EspionageReportSummary{ID: id, Type: messageType} report.From = s.Find("span.msg_sender").Text() + + // Find target coordinate spanLink := s.Find("span.msg_title a") targetStr := spanLink.Text() report.Target = extractCoordV6(targetStr) @@ -651,6 +655,8 @@ func extractEspionageReportMessageIDsFromDocV6(doc *goquery.Document) ([]Espiona if spanLink.Find("figure").HasClass("moon") { report.Target.Type = MoonType } + + // Find LootPercentage if messageType == Report { s.Find("div.compacting").Each(func(i int, s *goquery.Selection) { if regexp.MustCompile(`%`).MatchString(s.Text()) { @@ -659,14 +665,155 @@ func extractEspionageReportMessageIDsFromDocV6(doc *goquery.Document) ([]Espiona } }) } - msgs = append(msgs, report) + // LastActivity + log.SetFlags(log.LstdFlags | log.Lshortfile) + report.LastActivity = 0 + + activity := s.Find("span.msg_content").First().Find("span.ctn.ctn4.fright").First().Text() + activity = strings.TrimSpace(activity) + + m := regexp.MustCompile(`(\d{2})`).FindStringSubmatch(activity) + + if len(m) > 0 { + minutes := ParseInt(m[1]) + + if len(m) == 2 { + report.LastActivity = minutes + } + } + + // IsBandit, IsStarlord + report.IsBandit = false + report.IsStarlord = false + + banditstarlord := s.Find("span.honorRank") + if banditstarlord.Size() > 0 { + if banditstarlord.HasClass("rank_bandit1") || banditstarlord.HasClass("rank_bandit2") || banditstarlord.HasClass("rank_bandit3") { + report.IsBandit = true + } else if banditstarlord.HasClass("rank_starlord1") || banditstarlord.HasClass("rank_starlord2") || banditstarlord.HasClass("rank_starlord3") { + report.IsStarlord = true + } + } + + // IsInactive, IsLongInactive + report.IsInactive = false + report.IsLongInactive = false + + if s.Find("span.status_abbr_longinactive").Size() > 0 { + report.IsInactive = true + report.IsLongInactive = true + } else if s.Find("span.status_abbr_inactive").Size() > 0 { + report.IsInactive = true + } + + // HasFleet, FleetValue + report.HasFleet = false + report.FleetValue = -1 + + fleet := s.Find("div.compacting").Last().Find("span").Eq(0).AttrOr("title", "-1") + + if strings.Contains(fleet, ":") { + fleet = strings.Split(fleet, ":")[1] + fleet = strings.TrimSpace(fleet) + report.FleetValue = ParseInt(fleet) + } + + if report.FleetValue > -1 { + report.HasFleet = true + } + + // HasDefenses, DefenseValue + report.HasDefenses = false + report.DefenseValue = -1 + + defense := s.Find("div.compacting").Last().Find("span").Eq(1).AttrOr("title", "-1") + report.DefenseValue = ParseInt(defense) + + if report.DefenseValue > -1 { + report.HasDefenses = true + } + + // Metal, Crystal, Deuterium + log.SetFlags(log.LstdFlags | log.Lshortfile) + + // res := s.Find("div.compacting").Eq(2).Find("span") + res := s.Find("span.resspan").Parent() + + metal := res.Find("span.resspan").Eq(0).Text() + crystal := res.Find("span.resspan").Eq(1).Text() + deuterium := res.Find("span.resspan").Eq(2).Text() + + log.Print("preParseres = ", metal, crystal, deuterium) + + report.Metal = parseRes(metal) + report.Crystal = parseRes(crystal) + report.Deuterium = parseRes(deuterium) + + log.Print(report.Metal, report.Crystal, report.Deuterium) + + // APIKey + apikey, _ := s.Find("span.icon_apikey").Attr("title") + blaat, _ := goquery.NewDocumentFromReader(strings.NewReader(apikey)) + snarfzonk, _ := blaat.Find("input").First().Attr("value") + + report.APIKey = snarfzonk + + // CreatedAt + // 09.02.2019 23:25:56 + msgDate, _ := time.Parse("02.01.2006 15:04:05", s.Find("span.msg_date").Text()) + report.CreatedAt = msgDate + +//log.Fatal("--end--") + msgs = append(msgs, report) } } }) return msgs, nbPage } +func parseRes(input string) (res int64) { + // Metaal: 2,4M + // Kristal: 3,6M + // Deuterium: 4,8M + // Deuterium: 140.000 + + if strings.Contains(input, ":") { + input = strings.Split(input, ":")[1] + } + + if strings.Contains(input, ",") { + input = strings.Replace(input, ",", ".", 1) + } + + if strings.Contains(input, "Miljard") || strings.Contains(input, "B") { // Miljard (NL) = Billion (EN) + if strings.Contains(input, "Miljard") { + input = strings.Split(input, "M")[0] + } else if strings.Contains(input, "B") { + input = strings.Split(input, "B")[0] + } + input = strings.TrimSpace(input) + input, _ := strconv.ParseFloat(input, 64) + inputres := input * 1e9 + inputres2 := int64(inputres) + return inputres2 + } else if strings.Contains(input, "M") { + input = strings.Split(input, "M")[0] + input = strings.TrimSpace(input) + input, _ := strconv.ParseFloat(input, 64) + inputres := input * 1e6 + inputres2 := int64(inputres) + return inputres2 + } else { + input = strings.Replace(input, ".", "", 1) + input = strings.TrimSpace(input) + inputint, _ := strconv.ParseInt(input, 10, 64) + return inputint + } + + return int64(-1) +} + func extractCombatReportMessagesFromDocV6(doc *goquery.Document) ([]CombatReportSummary, int64) { msgs := make([]CombatReportSummary, 0) nbPage, _ := strconv.ParseInt(doc.Find("ul.pagination li").Last().AttrOr("data-page", "1"), 10, 64) diff --git a/extracts_v71.go b/extracts_v71.go index ae2d6d06..be6b1abd 100644 --- a/extracts_v71.go +++ b/extracts_v71.go @@ -10,6 +10,8 @@ import ( "strings" "time" + "log" + "github.com/PuerkitoBio/goquery" "github.com/alaingilbert/clockwork" "golang.org/x/net/html" @@ -822,3 +824,152 @@ func extractBuffActivationFromDocV71(doc *goquery.Document) (token string, items } return } + +// This function was initially created to extract MessageIDs from EspionageReportSummary messages. It has since been extended to include all fields, but kept it original name. +func extractEspionageReportMessageIDsFromDocV71(doc *goquery.Document) ([]EspionageReportSummary, int64) { + msgs := make([]EspionageReportSummary, 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 { + messageType := Report + if s.Find("span.espionageDefText").Size() > 0 { + messageType = Action + } + report := EspionageReportSummary{ID: id, Type: messageType} + report.From = s.Find("span.msg_sender").Text() + + // Added extra logging information (timestamp + linenumbers) + log.SetFlags(log.LstdFlags | log.Lshortfile) + + // Username + report.Username = strings.TrimSpace(s.Find("div.compacting").First().Find("span").Eq(1).Text()) + + // Find PlayerClass + playerClass := s.Find("div.compacting").Eq(1).Text() + if len(playerClass) > 0 && strings.Contains(playerClass, ":") { + report.PlayerClass = strings.TrimSpace(strings.Split(playerClass, ":")[1]) + } + + // Find target coordinate + spanLink := s.Find("span.msg_title a") + targetStr := spanLink.Text() + report.Target = extractCoordV6(targetStr) + report.Target.Type = PlanetType + if spanLink.Find("figure").HasClass("moon") { + report.Target.Type = MoonType + } + + // Find LootPercentage + if messageType == Report { + s.Find("div.compacting").Each(func(i int, s *goquery.Selection) { + if regexp.MustCompile(`%`).MatchString(s.Text()) { + report.LootPercentage, _ = strconv.ParseFloat(regexp.MustCompile(`: (\d+)%`).FindStringSubmatch(s.Text())[1], 64) + report.LootPercentage /= 100 + } + }) + } + + // LastActivity + report.LastActivity = 0 + activity := s.Find("span.msg_content").First().Find("span.ctn.ctn4.fright").First().Text() + activity = strings.TrimSpace(activity) + m := regexp.MustCompile(`(\d{2})`).FindStringSubmatch(activity) + if len(m) > 0 { + minutes := ParseInt(m[1]) + + if len(m) == 2 { + report.LastActivity = minutes + } + } + + // CounterEspionage + ceTxt := s.Find("span.msg_content div.compacting").Eq(3).Find("span.fright").Text() + ceTxtRegexp := regexp.MustCompile(`: (\d+)%`).FindStringSubmatch(ceTxt) + if len(ceTxtRegexp) == 2 { + report.CounterEspionage, _ = strconv.ParseInt(ceTxtRegexp[1], 10, 64) + } + + // IsBandit, IsStarlord + report.IsBandit = false + report.IsStarlord = false + + banditstarlord := s.Find("span.honorRank") + if banditstarlord.Size() > 0 { + if banditstarlord.HasClass("rank_bandit1") || banditstarlord.HasClass("rank_bandit2") || banditstarlord.HasClass("rank_bandit3") { + report.IsBandit = true + } else if banditstarlord.HasClass("rank_starlord1") || banditstarlord.HasClass("rank_starlord2") || banditstarlord.HasClass("rank_starlord3") { + report.IsStarlord = true + } + } + + // IsInactive, IsLongInactive + report.IsInactive = false + report.IsLongInactive = false + + if s.Find("span.status_abbr_longinactive").Size() > 0 { + report.IsInactive = true + report.IsLongInactive = true + } else if s.Find("span.status_abbr_inactive").Size() > 0 { + report.IsInactive = true + } + + // HasFleet, FleetValue + report.HasFleet = false + report.FleetValue = -1 + + fleet := s.Find("div.compacting").Last().Find("span").Eq(0).AttrOr("title", "-1") + + if strings.Contains(fleet, ":") { + fleet = strings.Split(fleet, ":")[1] + fleet = strings.TrimSpace(fleet) + report.FleetValue = ParseInt(fleet) + } + + if report.FleetValue > -1 { + report.HasFleet = true + } + + // HasDefenses, DefenseValue + report.HasDefenses = false + report.DefenseValue = -1 + + defense := s.Find("div.compacting").Last().Find("span").Eq(1).AttrOr("title", "-1") + report.DefenseValue = ParseInt(defense) + + if report.DefenseValue > -1 { + report.HasDefenses = true + } + + // Metal, Crystal, Deuterium + res := s.Find("span.resspan").Parent() + + metal := res.Find("span.resspan").Eq(0).Text() + crystal := res.Find("span.resspan").Eq(1).Text() + deuterium := res.Find("span.resspan").Eq(2).Text() + + //log.Print("preParseres = ", metal, crystal, deuterium) + + report.Metal = parseRes(metal) + report.Crystal = parseRes(crystal) + report.Deuterium = parseRes(deuterium) + + //log.Print(report.Metal, report.Crystal, report.Deuterium) + + // APIKey + apikey, _ := s.Find("span.icon_apikey").Attr("title") + blaat, _ := goquery.NewDocumentFromReader(strings.NewReader(apikey)) + snarfzonk := blaat.Find("input").First().AttrOr("value", "") + report.APIKey = snarfzonk + + // CreatedAt + // 09.02.2019 23:25:56 + msgDate, _ := time.Parse("02.01.2006 15:04:05", s.Find("span.msg_date").Text()) + report.CreatedAt = msgDate + + msgs = append(msgs, report) + } + } + }) + return msgs, nbPage +} diff --git a/ogame.go b/ogame.go index c7c71391..a99389b9 100644 --- a/ogame.go +++ b/ogame.go @@ -3357,7 +3357,7 @@ func (b *OGame) sendFleetV6(celestialID CelestialID, ships []Quantifiable, speed } // EspionageReportType type of espionage report (action or report) -type EspionageReportType int +type EspionageReportType int64 // Action message received when an enemy is seen naer your planet const Action EspionageReportType = 0 @@ -3387,7 +3387,24 @@ type EspionageReportSummary struct { Type EspionageReportType From string Target Coordinate + PlayerClass string + Username string LootPercentage float64 + LastActivity int64 + CounterEspionage int64 + IsInactive bool + IsLongInactive bool + IsBandit bool + IsStarlord bool + HasDefenses bool + DefenseValue int64 + HasFleet bool + FleetValue int64 + Metal int64 + Crystal int64 + Deuterium int64 + APIKey string + CreatedAt time.Time } func (b *OGame) getPageMessages(page, tabid int64) ([]byte, error) { diff --git a/ogame_test.go b/ogame_test.go index 022404af..d054554e 100644 --- a/ogame_test.go +++ b/ogame_test.go @@ -898,6 +898,25 @@ func TestExtractEspionageReportMessageIDs(t *testing.T) { assert.Equal(t, Coordinate{4, 117, 9, PlanetType}, msgs[1].Target) } + +func TestExtractEspionageReportMessageIDsParseResMillions(t *testing.T) { + pageHTMLBytes, _ := ioutil.ReadFile("samples/messages_loot_percentage.html") + msgs, _ := NewExtractorV6().ExtractEspionageReportMessageIDs(pageHTMLBytes) + + assert.Equal(t, int64(32393000), msgs[1].Metal) // Metal: 32.393Mn + assert.Equal(t, int64(20919000), msgs[1].Crystal) // Crystal: 20.919Mn + assert.Equal(t, int64(6186000), msgs[1].Deuterium) // Deuterium: 6.186Mn + assert.Equal(t, true, msgs[1].HasDefenses) // true + assert.Equal(t, int64(448862000), msgs[1].DefenseValue) // 448.862.000 + assert.Equal(t, true, msgs[1].HasFleet) // true + assert.Equal(t, int64(1950500), msgs[1].FleetValue) // Fleets: 1.950.500 + assert.Equal(t, int64(1950500), msgs[1].FleetValue) // Fleets: 1.950.500 + + assert.Equal(t, int64(2920000), msgs[2].Metal) + assert.Equal(t, int64(1590000), msgs[2].Crystal) + assert.Equal(t, int64(713855), msgs[2].Deuterium) +} + func TestExtractEspionageReportMessageIDsLootPercentage(t *testing.T) { pageHTMLBytes, _ := ioutil.ReadFile("samples/messages_loot_percentage.html") msgs, _ := NewExtractorV6().ExtractEspionageReportMessageIDs(pageHTMLBytes) @@ -2887,3 +2906,133 @@ func TestExtractOGameSession(t *testing.T) { session = NewExtractorV6().ExtractOGameSession(pageHTMLBytes) assert.Equal(t, "c1626ce8228ac5986e3808a7d42d4afc764c1b68", session) } + +func TestV72ExtractEspionageReportMessageIDs(t *testing.T) { + pageHTMLBytes, _ := ioutil.ReadFile("samples/v7.2/en/messages.html") + msgs, _ := NewExtractorV71().ExtractEspionageReportMessageIDs(pageHTMLBytes) + + /* + type EspionageReportSummary struct { + ID int64 + Type EspionageReportType + From string + Target Coordinate + PlayerClass string + Username string + LootPercentage float64 + LastActivity int64 + CounterEspionage int64 + IsInactive bool + IsLongInactive bool + IsBandit bool + IsStarlord bool + HasDefenses bool + DefenseValue int64 + HasFleet bool + FleetValue int64 + Metal int64 + Crystal int64 + Deuterium int64 + APIKey string + CreatedAt time.Time + } + */ + + assert.Equal(t, int64(12692941), msgs[0].ID) + assert.Equal(t, int64(12692938), msgs[1].ID) + assert.Equal(t, int64(12692934), msgs[2].ID) + assert.Equal(t, int64(12692933), msgs[3].ID) + assert.Equal(t, int64(12692932), msgs[4].ID) + assert.Equal(t, int64(12692929), msgs[5].ID) + + + assert.Equal(t, "ChuckBiscuits", msgs[0].Username) + assert.Equal(t, "ChuckBiscuits", msgs[1].Username) + assert.Equal(t, "Hermes73", msgs[2].Username) + assert.Equal(t, "InquisitoZ", msgs[3].Username) + assert.Equal(t, "blondie", msgs[4].Username) + assert.Equal(t, "blondie", msgs[5].Username) + + assert.Equal(t, "sr-en-152-ec0ae9f598948a42b23bf8a45caf818eb02c5198", msgs[0].APIKey) + assert.Equal(t, "sr-en-152-f8286f9a8d053ad7df343d0873a98429e656f9e9", msgs[1].APIKey) + assert.Equal(t, "sr-en-152-55b7de6f4cd4772fd6c881fb3ea689f2f8d697d9", msgs[2].APIKey) + assert.Equal(t, "sr-en-152-08f7014551e9717de500fa2d52f4e19566a44299", msgs[3].APIKey) + assert.Equal(t, "sr-en-152-2fa03c5e6d96ffaf745d92abc0a44b5ad2d2c29b", msgs[4].APIKey) + assert.Equal(t, "sr-en-152-e7eb3f47e7e64df22ec8f96bd3232645321a727d", msgs[5].APIKey) + + assert.Equal(t, float64(1), msgs[0].LootPercentage) + assert.Equal(t, float64(1), msgs[1].LootPercentage) + assert.Equal(t, float64(0.75), msgs[2].LootPercentage) + + assert.Equal(t, "2020-03-26 03:56:40", msgs[0].CreatedAt.Format("2006-01-02 15:04:05")) + assert.Equal(t, "2020-03-26 03:54:29", msgs[5].CreatedAt.Format("2006-01-02 15:04:05")) + + assert.Equal(t, Coordinate{Galaxy:4, System:49, Position: 9, Type:3}, msgs[0].Target) + assert.Equal(t, Coordinate{Galaxy:4, System:49, Position: 9, Type:1}, msgs[1].Target) + + assert.Equal(t, int64(0), msgs[0].Metal) + assert.Equal(t, int64(0), msgs[0].Crystal) + assert.Equal(t, int64(0), msgs[0].Deuterium) + + assert.Equal(t, int64(20159000), msgs[1].Metal) + assert.Equal(t, int64(4363000), msgs[1].Crystal) + assert.Equal(t, int64(4127000), msgs[1].Deuterium) + + assert.True(t, msgs[0].IsBandit) + assert.False(t, msgs[0].IsStarlord) + assert.True(t, msgs[1].IsBandit) + assert.False(t, msgs[1].IsStarlord) + assert.False(t, msgs[2].IsBandit) + assert.False(t, msgs[2].IsStarlord) + assert.False(t, msgs[3].IsBandit) + assert.True(t, msgs[3].IsStarlord) + assert.False(t, msgs[4].IsBandit) + assert.True(t, msgs[5].IsStarlord) + assert.False(t, msgs[5].IsBandit) + assert.True(t, msgs[5].IsStarlord) + + assert.Equal(t, int64(0), msgs[0].DefenseValue) + assert.Equal(t, int64(0), msgs[0].FleetValue) + assert.True(t, msgs[0].HasDefenses) + assert.Equal(t, int64(230692000), msgs[1].DefenseValue) + assert.Equal(t, int64(21985000), msgs[1].FleetValue) + assert.True(t, msgs[0].HasDefenses) + assert.Equal(t, int64(46000), msgs[4].DefenseValue) + assert.Equal(t, int64(0), msgs[4].FleetValue) + assert.True(t, msgs[0].HasDefenses) + assert.Equal(t, int64(1148000), msgs[5].DefenseValue) + assert.Equal(t, int64(5000000), msgs[5].FleetValue) + + + assert.True(t, msgs[0].HasDefenses) + assert.True(t, msgs[0].HasFleet) + + assert.Equal(t, int64(0), msgs[0].CounterEspionage) + assert.Equal(t, int64(100), msgs[1].CounterEspionage) + assert.Equal(t, int64(98), msgs[5].CounterEspionage) + + assert.Equal(t, int64(60), msgs[0].LastActivity) + assert.Equal(t, int64(60), msgs[1].LastActivity) + + assert.False(t, msgs[0].IsInactive) + assert.False(t, msgs[0].IsLongInactive) + assert.False(t, msgs[1].IsInactive) + assert.False(t, msgs[1].IsLongInactive) + assert.True(t, msgs[2].IsInactive) + assert.True(t, msgs[2].IsLongInactive) + assert.True(t, msgs[3].IsInactive) + assert.True(t, msgs[3].IsLongInactive) + assert.False(t, msgs[4].IsInactive) + assert.False(t, msgs[4].IsLongInactive) + assert.False(t, msgs[5].IsInactive) + assert.False(t, msgs[5].IsLongInactive) + + assert.Equal(t, EspionageReportType(1), msgs[0].Type) + assert.Equal(t, EspionageReportType(1), msgs[1].Type) + + assert.Equal(t, "Fleet Command", msgs[0].From) + + assert.Equal(t, "Discoverer", msgs[0].PlayerClass) + assert.Equal(t, "No class selected", msgs[2].PlayerClass) + assert.Equal(t, "Discoverer", msgs[5].PlayerClass) +}