|
@@ -0,0 +1,325 @@
|
|
|
|
|
+package main
|
|
|
|
|
+
|
|
|
|
|
+import (
|
|
|
|
|
+ "bytes"
|
|
|
|
|
+ "database/sql"
|
|
|
|
|
+ "encoding/json"
|
|
|
|
|
+ "fmt"
|
|
|
|
|
+ "log"
|
|
|
|
|
+ "net/http"
|
|
|
|
|
+ "regexp"
|
|
|
|
|
+ "strconv"
|
|
|
|
|
+ "strings"
|
|
|
|
|
+ "time"
|
|
|
|
|
+
|
|
|
|
|
+ // https://golang.org/ref/spec#Import_declarations
|
|
|
|
|
+ _ "github.com/lib/pq"
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+// Faction is a struct that holds data about a faction
|
|
|
|
|
+type Faction struct {
|
|
|
|
|
+ webhookGeneral string
|
|
|
|
|
+ webhookWar string
|
|
|
|
|
+ name string
|
|
|
|
|
+ id int
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Event from http://api.orn.com/user
|
|
|
|
|
+type Event struct {
|
|
|
|
|
+ id int
|
|
|
|
|
+ timestamp time.Time
|
|
|
|
|
+ news string
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Events array of Event
|
|
|
|
|
+type Events []Event
|
|
|
|
|
+
|
|
|
|
|
+// Attack struct
|
|
|
|
|
+type Attack struct {
|
|
|
|
|
+ id int
|
|
|
|
|
+ timestamp time.Time
|
|
|
|
|
+ news string
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Attacks array of Attack
|
|
|
|
|
+type Attacks []Attack
|
|
|
|
|
+
|
|
|
|
|
+// News to be broadcast
|
|
|
|
|
+type News struct {
|
|
|
|
|
+ Content string `json:"content"`
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func main() {
|
|
|
|
|
+ duration := time.Duration(10) * time.Second
|
|
|
|
|
+ time.Sleep(duration)
|
|
|
|
|
+ var err error
|
|
|
|
|
+ var e Event
|
|
|
|
|
+ timeFormat := "2006-01-02 15:04:05"
|
|
|
|
|
+ relentless := Faction{
|
|
|
|
|
+ webhookGeneral: "https://discordapp.com/api/webhooks/330506556820946946/gzReDE9EKFei05twvoFSZgRkAdAG523YTNLy2T_c5NDwagapwgGyhTrjFq_Y2_zu1fOK",
|
|
|
|
|
+ webhookWar: "https://discordapp.com/api/webhooks/330163061573025792/m9qS_4FawQwaWN11Y-qDKC2CeBlcR2r7Q9muISiVjW7LVpKrPNcYudNkPf2Y_ZD3sWf6",
|
|
|
|
|
+ name: "Relentless",
|
|
|
|
|
+ id: 8336}
|
|
|
|
|
+ unrelenting := Faction{
|
|
|
|
|
+ webhookGeneral: "https://discordapp.com/api/webhooks/330303142367461376/R9v8SQqZz8J-nyQuDAcU-xA7GNt_DsMzZ30LI6qJmebDJzLOfQoCLvX07YBrjoZTHAVI",
|
|
|
|
|
+ webhookWar: "https://discordapp.com/api/webhooks/330303142367461376/R9v8SQqZz8J-nyQuDAcU-xA7GNt_DsMzZ30LI6qJmebDJzLOfQoCLvX07YBrjoZTHAVI",
|
|
|
|
|
+ name: "Unrelenting",
|
|
|
|
|
+ id: 20747}
|
|
|
|
|
+ factions := []Faction{relentless, unrelenting}
|
|
|
|
|
+ for _, faction := range factions {
|
|
|
|
|
+ e, err = getEventsFromDatabase(faction.name)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ log.Println("Database error:", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ if e.id > 0 {
|
|
|
|
|
+ fmt.Println("*** Processing: " + faction.name)
|
|
|
|
|
+ var code int
|
|
|
|
|
+ e.news = strings.Replace(e.news, "[", "\\[", -1)
|
|
|
|
|
+ news := replaceLinks(e.news)
|
|
|
|
|
+ news = strings.Replace(news, "http:", "https:", -1)
|
|
|
|
|
+ news = "`" + e.timestamp.UTC().Format(timeFormat) + "`: " + news
|
|
|
|
|
+ fmt.Println(faction.name + ": " + news)
|
|
|
|
|
+ code, err = broadcastNews(news, faction.webhookGeneral) // general
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ log.Println("broadcast error:", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ fmt.Println(faction.name + ": " + strconv.Itoa(code))
|
|
|
|
|
+ if code == 204 {
|
|
|
|
|
+ // Assuming sent
|
|
|
|
|
+ setBroadcastTrue(e.id)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Attacks
|
|
|
|
|
+ attacks, err := getAttackFromDatabase(faction.name)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ log.Println("Database error:", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ for key, attack := range attacks {
|
|
|
|
|
+ fmt.Printf("attacks[%d].id: %d\n", key, attack.id)
|
|
|
|
|
+ err = broadcastSingleAttack(attack, faction)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ log.Println(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ //a := attacks[0]
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func getEventsFromDatabase(factionName string) (Event, error) {
|
|
|
|
|
+ var err error
|
|
|
|
|
+ var e Event
|
|
|
|
|
+ db, err := sql.Open("postgres", "user="+pgUser+" dbname="+pgTable+" password="+pgPasswd)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return e, err
|
|
|
|
|
+ }
|
|
|
|
|
+ defer db.Close()
|
|
|
|
|
+
|
|
|
|
|
+ rows, err := db.Query(`SELECT id, timestamp, news FROM events WHERE faction = '` +
|
|
|
|
|
+ factionName + `' AND broadcast = FALSE ORDER BY id ASC LIMIT 1;`)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return e, err
|
|
|
|
|
+ }
|
|
|
|
|
+ defer rows.Close()
|
|
|
|
|
+ for rows.Next() {
|
|
|
|
|
+ rows.Scan(&e.id, &e.timestamp, &e.news)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return e, err
|
|
|
|
|
+ }
|
|
|
|
|
+ fmt.Println(e)
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := rows.Err(); err != nil {
|
|
|
|
|
+ return e, err
|
|
|
|
|
+ }
|
|
|
|
|
+ return e, nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func getAttackFromDatabase(factionName string) (Attacks, error) {
|
|
|
|
|
+ var err error
|
|
|
|
|
+ var a Attack
|
|
|
|
|
+ var attacks Attacks
|
|
|
|
|
+ db, err := sql.Open("postgres", "user="+pgUser+" dbname="+pgTable+" password="+pgPasswd)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return attacks, err
|
|
|
|
|
+ }
|
|
|
|
|
+ defer db.Close()
|
|
|
|
|
+
|
|
|
|
|
+ rows, err := db.Query("SELECT id, timestamp, news FROM attacks WHERE faction = '" +
|
|
|
|
|
+ factionName + "' AND broadcast = FALSE ORDER BY id ASC;")
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return attacks, err
|
|
|
|
|
+ }
|
|
|
|
|
+ defer rows.Close()
|
|
|
|
|
+ for rows.Next() {
|
|
|
|
|
+ rows.Scan(&a.id, &a.timestamp, &a.news)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return attacks, err
|
|
|
|
|
+ }
|
|
|
|
|
+ attacks = append(attacks, a)
|
|
|
|
|
+ fmt.Println(a)
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := rows.Err(); err != nil {
|
|
|
|
|
+ return attacks, err
|
|
|
|
|
+ }
|
|
|
|
|
+ return attacks, nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (e Event) String() string {
|
|
|
|
|
+ line := fmt.Sprintf("{\n\t\"id\": %d,", e.id)
|
|
|
|
|
+ line += fmt.Sprintf("\n\t\"timestamp\": %s,", e.timestamp)
|
|
|
|
|
+ line += fmt.Sprintf("\n\t\"news\": %s", e.news)
|
|
|
|
|
+ line += fmt.Sprintf("\n}")
|
|
|
|
|
+ return line
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (a Attack) String() string {
|
|
|
|
|
+ line := fmt.Sprintf("{\n\t\"id\": %d,", a.id)
|
|
|
|
|
+ line += fmt.Sprintf("\n\t\"timestamp\": %s,", a.timestamp)
|
|
|
|
|
+ line += fmt.Sprintf("\n\t\"news\": %s", a.news)
|
|
|
|
|
+ line += fmt.Sprintf("\n}")
|
|
|
|
|
+ return line
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func replaceLinks(news string) string {
|
|
|
|
|
+ re := regexp.MustCompile(`<[aA].*?href\s?=\s?"?(.*?)[ "]?(?: .*?)?>(.*?)<\/a>`)
|
|
|
|
|
+ fmt.Println(re.FindAllStringSubmatch(news, -1))
|
|
|
|
|
+ return re.ReplaceAllString(news, "[${2}](${1})")
|
|
|
|
|
+ //return news
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func broadcastNews(new string, webhook string) (int, error) {
|
|
|
|
|
+ // var err error
|
|
|
|
|
+ var news News
|
|
|
|
|
+ news.Content = new
|
|
|
|
|
+ jsonValue, err := json.Marshal(news)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return -1, err
|
|
|
|
|
+ }
|
|
|
|
|
+ fmt.Println(string(jsonValue))
|
|
|
|
|
+ resp, err := http.Post(webhook, "application/json", bytes.NewBuffer(jsonValue))
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return -1, err
|
|
|
|
|
+ }
|
|
|
|
|
+ return resp.StatusCode, nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func broadcastSingleAttack(attack Attack, faction Faction) error {
|
|
|
|
|
+ timeFormat := "2006-01-02 15:04:05"
|
|
|
|
|
+ if attack.id > 0 {
|
|
|
|
|
+ members, err := getRelentlessMembers()
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ log.Println("Database error:", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ news := replaceLinks(attack.news)
|
|
|
|
|
+ news = strings.Replace(news, "http:", "https:", -1)
|
|
|
|
|
+ for _, val := range members {
|
|
|
|
|
+ news = strings.Replace(news, val, "**"+val+"**", -1)
|
|
|
|
|
+ }
|
|
|
|
|
+ news = strings.Replace(news, "_", "\\_", -1)
|
|
|
|
|
+ news = attack.timestamp.UTC().Format(timeFormat) + ": " + news
|
|
|
|
|
+ code, err := broadcastNews(news, faction.webhookWar) // war
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ log.Println("broadcast error:", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ fmt.Println(faction.name + ": " + strconv.Itoa(code))
|
|
|
|
|
+ if code == 204 {
|
|
|
|
|
+ // Assuming sent
|
|
|
|
|
+ setAttackBroadcastTrue(attack.id)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func setBroadcastTrue(id int) error {
|
|
|
|
|
+ fmt.Println(id)
|
|
|
|
|
+ var err error
|
|
|
|
|
+ db, err := sql.Open("postgres", "user="+pgUser+" dbname="+pgTable+" password="+pgPasswd)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return err
|
|
|
|
|
+ }
|
|
|
|
|
+ defer db.Close()
|
|
|
|
|
+
|
|
|
|
|
+ tx, err := db.Begin()
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ log.Fatal(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ defer tx.Rollback()
|
|
|
|
|
+
|
|
|
|
|
+ tx.Exec(`SET TIME ZONE 'utc'`)
|
|
|
|
|
+ stmt, err := tx.Prepare("UPDATE events SET broadcast = TRUE WHERE id = $1;")
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return err
|
|
|
|
|
+ }
|
|
|
|
|
+ _, err = stmt.Exec(fmt.Sprintf("%d", id))
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return err
|
|
|
|
|
+ }
|
|
|
|
|
+ err = tx.Commit()
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return err
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func setAttackBroadcastTrue(id int) error {
|
|
|
|
|
+ fmt.Println(id)
|
|
|
|
|
+ var err error
|
|
|
|
|
+ db, err := sql.Open("postgres", "user="+pgUser+" dbname="+pgTable+" password="+pgPasswd)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return err
|
|
|
|
|
+ }
|
|
|
|
|
+ defer db.Close()
|
|
|
|
|
+
|
|
|
|
|
+ tx, err := db.Begin()
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ log.Fatal(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ defer tx.Rollback()
|
|
|
|
|
+
|
|
|
|
|
+ tx.Exec(`SET TIME ZONE 'utc'`)
|
|
|
|
|
+ stmt, err := tx.Prepare("UPDATE attacks SET broadcast = TRUE WHERE id = $1;")
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return err
|
|
|
|
|
+ }
|
|
|
|
|
+ _, err = stmt.Exec(fmt.Sprintf("%d", id))
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return err
|
|
|
|
|
+ }
|
|
|
|
|
+ err = tx.Commit()
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return err
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func getRelentlessMembers() ([]string, error) {
|
|
|
|
|
+ var members []string
|
|
|
|
|
+ var err error
|
|
|
|
|
+ db, err := sql.Open("postgres", "user="+pgUser+" dbname="+pgTable+" password="+pgPasswd)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return members, err
|
|
|
|
|
+ }
|
|
|
|
|
+ defer db.Close()
|
|
|
|
|
+
|
|
|
|
|
+ rows, err := db.Query("SELECT member_name FROM members WHERE status = 'joined';")
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return members, err
|
|
|
|
|
+ }
|
|
|
|
|
+ defer rows.Close()
|
|
|
|
|
+ var name string
|
|
|
|
|
+ for rows.Next() {
|
|
|
|
|
+ rows.Scan(&name)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return members, err
|
|
|
|
|
+ }
|
|
|
|
|
+ members = append(members, name)
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := rows.Err(); err != nil {
|
|
|
|
|
+ return members, err
|
|
|
|
|
+ }
|
|
|
|
|
+ return members, nil
|
|
|
|
|
+
|
|
|
|
|
+}
|