package main import ( "strings" "fmt" "regexp" "database/sql" _ "github.com/mattn/go-sqlite3" ) var begin_char = []byte{'-', '<'} var db *sql.DB var err error // function to split advise message correctly func filter(msg string, foo bot) cmd { var c cmd if len(msg) <= 0 { c.error = "Message is too short." c.valid = false return c } c.cmd = "" c.valid = false if strings.HasPrefix(msg, "add ") { c.add = true msg = msg[4:] } else { c.add = false } if (strings.Contains(msg, "[") && strings.Contains(msg, "]")) { re, _ := regexp.Compile(`\s*(\w*)\s*\[(.+)\]\s*(.*)\s*`) res := re.FindStringSubmatch(msg) if len(res) < 4 { c.error = "You entered weird stuff, please try again." return c } c.cmd = res[1] if c.cmd == "" { LOG_WARN.Printf("empty cmd\n") c.error = "The command was empty. A non-empty command is needed." return c } // substitute group names with ids groups := strings.Fields(res[2]) stmt, err := db.Prepare("select id from groups where name = ?") checkErr(err) for _, group := range groups { rows, err := stmt.Query(group) if err != nil { LOG_WARN.Printf("invalid query.") return c } if rows.Next() { group_id := 0 rows.Scan(&group_id) c.groups = append(c.groups, fmt.Sprintf("%d", group_id)) } else { if c.add { c.groups = append(c.groups, addgroups([]string{group}, nil)...) } } rows.Close() defer stmt.Close() } c.suffix = res[3] c.valid = true } else { c.groups = nil re, _ := regexp.Compile(`\s*(\w*)\s*(.*)\s*`) res := re.FindStringSubmatch(msg) if len(res) < 3 { c.error = "You entered weird stuff, please try again." return c } c.cmd = res[1] if c.cmd == "" { c.error = "The command was empty. A non-empty command is needed." return c } c.suffix = res[2] c.valid = true } c.cmd = strings.TrimSpace(c.cmd) c.suffix = strings.TrimSpace(c.suffix) c.groups = unique_str(c.groups) return c } func getRandomEntry(c cmd) string { // TODO: increment counter // if database entry exists: set tag / group and run query task := "select distinct l.content from line l, brain b, tag t" task += " where l.id = b.line_id and t.id = b.tag_id and t.id = " + c.cmd if len(c.groups) > 0 { task += " and l.id in (select line_id from brain where group_id = " + strings.Join(c.groups," intersect select line_id from brain where group_id = ") + ")" } task += " ORDER BY RANDOM() LIMIT 1" return task } func addgroups(new_groups []string, msg *irc_msg) []string { stat_sel, err := db.Prepare("select id from groups where name = ?") checkErr(err) stat_ins, err := db.Prepare("insert into groups(name) values (?)") checkErr(err) var groups_added []string var groupids_added []string for _, group := range new_groups { ret, err := stat_sel.Query(group) if ret.Next() { ret.Close() continue } groupid_res, err := stat_ins.Exec(group) checkErr(err) defer stat_ins.Close() groupid, err := groupid_res.LastInsertId() checkErr(err) groupids_added = append(groupids_added, fmt.Sprintf("%d", groupid)) groups_added = append(groups_added, group) } if msg != nil { if len(groups_added) > 0 { (*msg).retmsg = "Added " + strings.Join(groups_added, ", ") + " to groups-table!" } else { (*msg).retmsg = "Added nothing to groups-table! :(" } } return groupids_added } func checkSorter(msg *irc_msg, c *cmd) bool { sorter_row_sel, err := db.Prepare("select id, tag_id, groups_allow, name_allow, has_groups from sorter where name = ?") checkErr(err) sorter_row, err := sorter_row_sel.Query((*c).cmd) checkErr(err) if sorter_row.Next() { var sorter_id string var tag_id string var groups_allow int var name_allow int var has_groups int sorter_row.Scan(&sorter_id, &tag_id, &groups_allow, &name_allow, &has_groups) sorter_row.Close() if groups_allow != 0 { (*msg).retmsg = "This command does not allow groups. :(" return false } if name_allow != 0 && !(*c).add { // warning: not allowed (*c).suffix = "" } (*c).cmd = tag_id if has_groups == 0 { group_sel, err := db.Prepare("select group_id from sorter_groups where sorter_id = ?") checkErr(err) sorter_groups_row, err := group_sel.Query(sorter_id) //sorter_groups_row, err := db.Query(fmt.Sprintf("select group_id from sorter_groups where sorter_id = '%s'", sorter_id)) checkErr(err) if sorter_groups_row.Next() { var group_id int sorter_groups_row.Scan(&group_id) (*c).groups = append((*c).groups, fmt.Sprintf("%d", group_id)) } sorter_groups_row.Close() if (*c).add { var tag_name string tag_name_row, err := db.Query(fmt.Sprintf("select name from tag where id = %s", tag_id)) checkErr(err) if tag_name_row.Next() { tag_name_row.Scan(&tag_name) } tag_name_row.Close() LOG_WARN.Printf("Alias used. Tell the user about that.\n") (*msg).retmsg = "You're using an alias. Please try again with 'add " + tag_name + " [" + strings.Join((*c).groups, " ") + "]. Thanks!" return false } } } else { LOG_WARN.Printf("no sorter entry, no translation possible\n") (*msg).retmsg = "No entry found, sorry..." return false } return true } func chooseEntry(msg *irc_msg, c *cmd) { task := getRandomEntry(*c) LOG_INFO.Printf(task) row, err := db.Query(task) checkErr(err) if row.Next() { row.Scan(&((*msg).retmsg)) } row.Close() if len((*msg).retmsg) <= 0 { LOG_WARN.Printf("no entry found\n") (*msg).retmsg = "No matching entry found :(" } else if len((*c).suffix) > 0 { (*msg).retmsg = fmt.Sprintf("%s... %s", (*c).suffix, (*msg).retmsg) } } func addLine(msg *irc_msg, line string, groups []string, cmd string) string { LOG_WARN.Printf("adding new stuff: %s from %s.\n", line, (*msg).author) res, err := db.Exec("insert into line (content, author) values (?,?)", line, (*msg).author) checkErr(err) LOG_WARN.Printf("added line to table.\n") // get ID of content... line_id, err := res.LastInsertId(); checkErr(err) LOG_WARN.Printf("line_id: %d, tag_id: %s, groups: %s\n", line_id, cmd, strings.Join(groups, "-")) // for tag and all groups if len(groups) == 0 { stat, err := db.Prepare("insert into brain(line_id, tag_id) values (?,?)") checkErr(err) _, err = stat.Exec(line_id, cmd) checkErr(err) defer stat.Close() } else { stat, err := db.Prepare("insert into brain(line_id, tag_id, group_id) values (?,?,?)") checkErr(err) for _, group := range groups { _, err = stat.Exec(line_id, cmd, group) checkErr(err) } defer stat.Close() } (*msg).retmsg = fmt.Sprintf("success adding new super funny enjoyable line with ID %d!", line_id) return fmt.Sprintf("new line: > %s < (ID %d), into groups %s", line, line_id, strings.Join(groups,",")) } // line: // >befehl <[groups]> // befehl ist genau ein wort func parsemsg(msg *irc_msg, foo bot) bool { if len((*msg).msg) <= 0 { return false } if (*msg).msg == "<3" { (*msg).msg = string(begin_char[0]) + "flirt kreisi" } if !in((*msg).msg[0], begin_char) { return false } (*msg).msg = (*msg).msg[1:] c := filter((*msg).msg, foo) if !c.valid { LOG_WARN.Printf("non valid input found.\n") if c.error != "" { (*msg).retmsg = "Falscher input du SP-Ersti... " + c.error } return false } LOG_WARN.Printf("line was parsed, continue with evaluation.\n") if c.cmd == "" { LOG_WARN.Printf("no command provided.\n") return false } if c.cmd == "help" { return false } // hard code 'groups' to add new groups to the groups-table if c.add && (c.cmd == "groups" || c.cmd == "group") { if (c.groups != nil) { (*msg).retmsg = "Ignoring groups for the groups-adding. Well, what were you expecting...?" } addgroups(strings.Fields((&c).suffix), msg) return false } // have a look at sorter table if command is valid if !checkSorter(msg, &c) { return false } // new line for database if c.add { // if there is nothing to add, just return. :-) if (len(c.suffix) <= 0) { return false; } c.suffix = strings.Replace(c.suffix,"\"","'", -1) sendmsg(foo.conn, "horscchtey", addLine(msg, c.suffix, c.groups, c.cmd)) } else { chooseEntry(msg, &c) } return true }