328 lines
12 KiB
Go
328 lines
12 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"log"
|
|
"regexp"
|
|
"strconv"
|
|
)
|
|
|
|
func initDB() {
|
|
log.Println("Setting up database...")
|
|
|
|
tx, err := db.Begin()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer tx.Rollback()
|
|
|
|
_, err = tx.Exec("set foreign_key_checks = 0")
|
|
failOnError(err, "initDB : set foreign_key_checks = 0")
|
|
|
|
var name string
|
|
rows, err := db.Query("show tables")
|
|
failOnError(err, "initDB : show tables")
|
|
|
|
for rows.Next() {
|
|
err = rows.Scan(&name)
|
|
failOnError(err, "initDB : show tables listing")
|
|
|
|
_, err = tx.Exec("drop table " + name)
|
|
failOnError(err, "initDB : drop table "+name)
|
|
}
|
|
err = rows.Err()
|
|
failOnError(err, "initDB : show tables listing end")
|
|
rows.Close()
|
|
|
|
_, err = tx.Exec("set foreign_key_checks = 1")
|
|
failOnError(err, "initDB : set foreign_key_checks = 1")
|
|
|
|
err = tx.Commit()
|
|
failOnError(err, "initDB : commit cleanup")
|
|
|
|
log.Println("Database cleaned up")
|
|
|
|
_, err = db.Exec(`CREATE TABLE code_obj_type (
|
|
id SMALLINT UNSIGNED NOT NULL
|
|
,intl_id VARCHAR(32) NOT NULL
|
|
,name VARCHAR(80) NOT NULL
|
|
,PRIMARY KEY (id)
|
|
) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;`)
|
|
failOnError(err, "initDB : create table code_obj_type")
|
|
|
|
_, err = db.Exec(`CREATE TABLE code_obj_sub_type (
|
|
id SMALLINT UNSIGNED NOT NULL
|
|
,intl_id VARCHAR(32) NOT NULL
|
|
,name VARCHAR(80) NOT NULL
|
|
,obj_type_id SMALLINT UNSIGNED NOT NULL
|
|
,PRIMARY KEY (id)
|
|
,FOREIGN KEY (obj_type_id) REFERENCES code_obj_type(id) ON DELETE CASCADE
|
|
) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;`)
|
|
failOnError(err, "initDB : create table code_obj_sub_type")
|
|
|
|
_, err = db.Exec(`CREATE TABLE obj (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT
|
|
,obj_type_id SMALLINT UNSIGNED NOT NULL
|
|
,obj_sub_type_id SMALLINT UNSIGNED NOT NULL
|
|
,PRIMARY KEY (id)
|
|
,FOREIGN KEY (obj_type_id) REFERENCES code_obj_type(id) ON DELETE CASCADE
|
|
,FOREIGN KEY (obj_sub_type_id) REFERENCES code_obj_sub_type(id) ON DELETE CASCADE
|
|
) ENGINE = InnoDB AUTO_INCREMENT = 0 CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;`)
|
|
failOnError(err, "initDB : create table obj")
|
|
|
|
_, err = db.Exec(`CREATE TABLE obj_user (
|
|
obj_id BIGINT UNSIGNED NOT NULL
|
|
,telegram_id BIGINT UNSIGNED NOT NULL
|
|
,user_id VARCHAR(32) NOT NULL
|
|
,name VARCHAR(80) NOT NULL
|
|
,guild_id BIGINT UNSIGNED
|
|
,last_msg TIMESTAMP
|
|
,busy_until TIMESTAMP
|
|
,role ENUM('commander', 'bartender', 'squire', 'none')
|
|
,FOREIGN KEY (obj_id) REFERENCES obj(id) ON DELETE CASCADE
|
|
) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;`)
|
|
failOnError(err, "initDB : create table obj_user")
|
|
|
|
_, err = db.Exec(`CREATE TABLE obj_guild (
|
|
obj_id BIGINT UNSIGNED NOT NULL
|
|
,tag VARCHAR(32) NOT NULL
|
|
,name VARCHAR(80) NOT NULL
|
|
,chat_id BIGINT NOT NULL
|
|
,deposit_chat_id BIGINT NOT NULL
|
|
,FOREIGN KEY (obj_id) REFERENCES obj(id) ON DELETE CASCADE
|
|
) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;`)
|
|
failOnError(err, "initDB : create table obj_guild")
|
|
|
|
_, err = db.Exec(`CREATE TABLE obj_war (
|
|
obj_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT
|
|
,start_time TIMESTAMP NOT NULL
|
|
,end_time TIMESTAMP NOT NULL
|
|
,FOREIGN KEY (obj_id) REFERENCES obj(id) ON DELETE CASCADE
|
|
) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;`)
|
|
failOnError(err, "initDB : create table obj_war")
|
|
|
|
_, err = db.Exec(`CREATE TABLE obj_msg (
|
|
obj_id BIGINT UNSIGNED NOT NULL
|
|
,msg_id BIGINT NOT NULL
|
|
,chat_id BIGINT NOT NULL
|
|
,user_id BIGINT NOT NULL
|
|
,sender_user_id BIGINT NOT NULL
|
|
,date TIMESTAMP NOT NULL
|
|
,text VARCHAR(4096) NOT NULL
|
|
,FOREIGN KEY (obj_id) REFERENCES obj(id) ON DELETE CASCADE
|
|
,UNIQUE KEY (msg_id, chat_id, sender_user_id)
|
|
) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;`)
|
|
failOnError(err, "initDB : create table obj_msg")
|
|
|
|
_, err = db.Exec(`CREATE TABLE obj_msg_report (
|
|
obj_id BIGINT UNSIGNED NOT NULL
|
|
,war_id BIGINT UNSIGNED NOT NULL
|
|
,FOREIGN KEY (obj_id) REFERENCES obj(id) ON DELETE CASCADE
|
|
,FOREIGN KEY (war_id) REFERENCES obj(id) ON DELETE CASCADE
|
|
) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;`)
|
|
failOnError(err, "initDB : create table obj_msg_report")
|
|
|
|
_, err = db.Exec(`CREATE TABLE obj_war_report (
|
|
obj_id BIGINT UNSIGNED NOT NULL
|
|
,user_id BIGINT UNSIGNED NOT NULL
|
|
,war_id BIGINT UNSIGNED NOT NULL
|
|
,attack SMALLINT UNSIGNED NOT NULL
|
|
,defense SMALLINT UNSIGNED NOT NULL
|
|
,gold SMALLINT UNSIGNED NOT NULL
|
|
,stock SMALLINT UNSIGNED NOT NULL
|
|
,exp SMALLINT UNSIGNED NOT NULL
|
|
,stamina TINYINT NOT NULL
|
|
,crit TINYINT NOT NULL
|
|
,FOREIGN KEY (obj_id) REFERENCES obj(id) ON DELETE CASCADE
|
|
,FOREIGN KEY (war_id) REFERENCES obj(id) ON DELETE CASCADE
|
|
,UNIQUE KEY (user_id, war_id)
|
|
) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;`)
|
|
failOnError(err, "initDB : create table obj_msg_report")
|
|
|
|
_, err = db.Exec(`CREATE TABLE msg_rules (
|
|
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT
|
|
,prio SMALLINT NOT NULL
|
|
,descn VARCHAR(32) NOT NULL
|
|
,rule VARCHAR(4096) NOT NULL
|
|
,msg_type_id SMALLINT UNSIGNED NOT NULL
|
|
,UNIQUE KEY (id)
|
|
) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;`)
|
|
failOnError(err, "initDB : create table msg_rules")
|
|
|
|
_, err = db.Exec(`INSERT INTO code_obj_type (id, intl_id, name)
|
|
VALUES (` + strconv.Itoa(objTypeUser) + `, "user", "User")
|
|
,(` + strconv.Itoa(objTypeGuild) + `, "guild", "Guild")
|
|
,(` + strconv.Itoa(objTypeMessage) + `, "msg", "Message")
|
|
,(` + strconv.Itoa(objTypeWar) + `, "war", "War")
|
|
,(` + strconv.Itoa(objTypeWarReport) + `, "war_report", "War Report")
|
|
,(` + strconv.Itoa(objTypeJob) + `, "job", "Job")
|
|
;`)
|
|
failOnError(err, "initDB : populate table code_obj_type")
|
|
|
|
_, err = db.Exec(`INSERT INTO code_obj_sub_type (id, intl_id, name, obj_type_id)
|
|
VALUES (` + strconv.Itoa(objSubTypeMessageUnknown) + `, "unknown", "Unknown", ` + strconv.Itoa(objTypeMessage) + `)
|
|
,(` + strconv.Itoa(objSubTypeMessageWar) + `, "war", "War report", ` + strconv.Itoa(objTypeMessage) + `)
|
|
,(` + strconv.Itoa(objSubTypeMessageMiniWar) + `, "mini_war", "Mini war reprot", ` + strconv.Itoa(objTypeMessage) + `)
|
|
,(` + strconv.Itoa(objSubTypeMessageGuildWar) + `, "guild_war", "Guilds war report", ` + strconv.Itoa(objTypeMessage) + `)
|
|
,(` + strconv.Itoa(objSubTypeMessageReport) + `, "report", "Player war report", ` + strconv.Itoa(objTypeMessage) + `)
|
|
,(` + strconv.Itoa(objSubTypeMessageGReport) + `, "g_report", "Player guilds war report", ` + strconv.Itoa(objTypeMessage) + `)
|
|
,(` + strconv.Itoa(objSubTypeMessageQuest) + `, "quest", "Quest result", ` + strconv.Itoa(objTypeMessage) + `)
|
|
,(` + strconv.Itoa(objSubTypeMessageFight) + `, "fight", "Fight result", ` + strconv.Itoa(objTypeMessage) + `)
|
|
,(` + strconv.Itoa(objSubTypeMessageHero) + `, "hero", "Hero summary", ` + strconv.Itoa(objTypeMessage) + `)
|
|
,(` + strconv.Itoa(objSubTypeMessageMe) + `, "me", "Hero short summary", ` + strconv.Itoa(objTypeMessage) + `)
|
|
,(` + strconv.Itoa(objSubTypeMessageInventory) + `, "inv", "Inventory", ` + strconv.Itoa(objTypeMessage) + `)
|
|
,(` + strconv.Itoa(objSubTypeMessagePillageInc) + `, "pillage_inc", "Pillage incoming", ` + strconv.Itoa(objTypeMessage) + `)
|
|
,(` + strconv.Itoa(objSubTypeMessageTributeInc) + `, "tribute_inc", "Request incoming", ` + strconv.Itoa(objTypeMessage) + `)
|
|
,(` + strconv.Itoa(objSubTypeMessagePillageAck) + `, "pillage_ack", "Pillage acknoledged", ` + strconv.Itoa(objTypeMessage) + `)
|
|
,(` + strconv.Itoa(objSubTypeMessageTributeAck) + `, "tribute_ack", "Request acknoledged", ` + strconv.Itoa(objTypeMessage) + `);`)
|
|
failOnError(err, "initDB : populate table code_obj_sub_type")
|
|
|
|
_, err = db.Exec(`INSERT INTO msg_rules (prio, descn, rule, msg_type_id)
|
|
VALUES (5000, "Player war report", "^(?P<Castle>[🐉🦅🐺🦈🦌🥔🌑])(?P<Guild>(\[[A-Z]{3}\]){0,1})(?P<User>([A-Za-z0-9 ]*)) ⚔:(?P<Attack>[0-9]+)(?P<AttackMod>\((-|\+)[0-9]+\)){0,1} 🛡:(?P<Defense>[0-9]+) Lvl: (?P<Level>[0-9]+)\nYour result on the battlefield:\n🔥Exp: (?P<Exp>[0-9]+)\n💰Gold: (?P<Gold>-{0,1}[0-9]+)\n📦Stock: (?P<Stock>-{0,1}[0-9]+)\n\n(?P<Stamina>(🔋Stamina restored)){0,1}(\n)*(?P<Crit>(⚡Critical strike)){0,1}(\n)*(?s:.*)$", ` + strconv.Itoa(objSubTypeMessageReport) + `);`)
|
|
failOnError(err, "initDB : populate table msg_rules")
|
|
|
|
log.Println("Database set up")
|
|
}
|
|
|
|
func putUnprocessedMsg(m ChatWarsMessage) (int64, error) {
|
|
res, err := db.Exec(`INSERT INTO obj (obj_type_id, obj_sub_type_id)
|
|
VALUES (` + strconv.Itoa(objTypeMessage) + `,` + strconv.Itoa(objSubTypeMessageUnknown) + `);`)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
objId, err := res.LastInsertId()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
stmt, err := db.Prepare(`INSERT INTO obj_msg (obj_id, msg_id, chat_id, user_id, sender_user_id, date , text)
|
|
VALUES (?, ?, ?, ?, ?, FROM_UNIXTIME(?), ?);`)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
defer stmt.Close()
|
|
|
|
_, err = stmt.Exec(objId, m.ID64, m.ChatID64, m.UserID64, m.SenderUserID64, m.Date, m.Text)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return objId, nil
|
|
}
|
|
|
|
func getMsg(objId int64) (ChatWarsMessage, error) {
|
|
var m ChatWarsMessage
|
|
|
|
stmt, err := db.Prepare(`SELECT om.msg_id, om.chat_id, om.sender_user_id, UNIX_TIMESTAMP(om.date), om.text FROM obj_msg om WHERE om.obj_id = ?`)
|
|
if err != nil {
|
|
return m, err
|
|
}
|
|
defer stmt.Close()
|
|
|
|
err = stmt.QueryRow(objId).Scan(&m.ID64, &m.ChatID64, &m.SenderUserID64, &m.Date, &m.Text)
|
|
if err != nil {
|
|
return m, err
|
|
}
|
|
|
|
return m, nil
|
|
}
|
|
|
|
func getObjSubTypeId(objId int64) (int64, error) {
|
|
var objSubTypeId int64
|
|
|
|
stmt, err := db.Prepare(`SELECT o.sub_type_id FROM obj o WHERE o.id = ?`)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
defer stmt.Close()
|
|
|
|
err = stmt.QueryRow(1).Scan(&objSubTypeId)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return objSubTypeId, nil
|
|
}
|
|
|
|
func insertMsgReport(objId int64, war_date int32, atk int32, def int32, exp int32, gold int32, stock int32, crit bool, stamina bool) error {
|
|
objSubTypeId, err := getObjSubTypeId(objId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if objSubTypeId != objSubTypeMessageUnknown {
|
|
return errors.New("Message is not of type Unknown")
|
|
}
|
|
/*
|
|
obj_id BIGINT UNSIGNED NOT NULL
|
|
,war_date TIMESTAMP NOT NULL
|
|
,attack SMALLINT UNSIGNED NOT NULL
|
|
,defense SMALLINT UNSIGNED NOT NULL
|
|
,gold SMALLINT UNSIGNED NOT NULL
|
|
,stock MALLINT UNSIGNED NOT NULL
|
|
,exp SMALLINT UNSIGNED NOT NULL
|
|
,stamina TINYINT NOT NULL
|
|
,crit TINYINT NOT NULL
|
|
|
|
stmt, err := db.Prepare(`INSERT INTO obj_msg_report (obj_id, war_date, attack, defense, gold, stock, exp, stamina, crit)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?FROM_UNIXTIME(?), ?);`)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer stmt.Close()
|
|
|
|
_, err = stmt.Exec(objId, m.ID64, m.ChatID64, m.UserID64, m.SenderUserID64, m.Date, m.Text)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*/
|
|
return nil
|
|
}
|
|
|
|
func loadMsgParsingRules() (map[int]MessageParsingRule, error) {
|
|
var (
|
|
id int32
|
|
priority int32
|
|
descn string
|
|
rule string
|
|
msgTypeID int32
|
|
)
|
|
|
|
log.Println("Loading message parsing rules...")
|
|
m := make(map[int]MessageParsingRule)
|
|
count := int(0)
|
|
|
|
defer func() {
|
|
if rec := recover(); rec != nil {
|
|
log.Printf("loadMsgParsingRules : panic (%s) \n", rec)
|
|
err := error.New("Can't load message parsing rules.")
|
|
return m, err
|
|
}
|
|
}()
|
|
|
|
rules, err := db.Query(`SELECT r.id, r.prio, r.descn, r.rule, r.msg_type_id FROM msg_rules r ORDER BY r.prio DESC;`)
|
|
if err != nil {
|
|
return m, err
|
|
}
|
|
defer rules.Close()
|
|
|
|
for rules.Next() {
|
|
err = rules.Scan(&id, &priority, &descn, &rule, &msgTypeID)
|
|
if err != nil {
|
|
return m, err
|
|
}
|
|
i := new(MessageParsingRule)
|
|
i.ID = id
|
|
i.Priority = priority
|
|
i.Description = descn
|
|
i.Rule = rule
|
|
i.MsgTypeID = msgTypeID
|
|
i.re = regexp.MustCompile(rule)
|
|
m[count] = *i
|
|
count++
|
|
|
|
}
|
|
|
|
return m, nil
|
|
}
|