Compare commits

...

2 commits

Author SHA1 Message Date
2cd84df2ba go fmt 2025-01-25 00:23:42 +01:00
41c1c27b1f toml to parameters 2025-01-25 00:23:22 +01:00
6 changed files with 122 additions and 114 deletions

View file

@ -1,21 +1,19 @@
package main
import (
"strings"
"fmt"
"regexp"
"database/sql"
"math/rand"
"fmt"
_ "github.com/mattn/go-sqlite3"
"math/rand"
"net"
"regexp"
"strings"
)
var begin_char = []byte{'-'}
var db *sql.DB
var err error
// function to split advise message correctly
func filter(msg string, foo bot) cmd {
func filter(msg string, conn net.Conn, db *sql.DB, nickname string) cmd {
var c cmd
if len(msg) <= 0 {
@ -34,7 +32,7 @@ func filter(msg string, foo bot) cmd {
c.add = false
}
if (strings.Contains(msg, "[") && strings.Contains(msg, "]")) {
if strings.Contains(msg, "[") && strings.Contains(msg, "]") {
re, _ := regexp.Compile(`\s*(\w*)\s*\[(.+)\]\s*(.*)\s*`)
res := re.FindStringSubmatch(msg)
if len(res) < 4 {
@ -66,7 +64,7 @@ func filter(msg string, foo bot) cmd {
c.groups = append(c.groups, fmt.Sprintf("%d", group_id))
} else {
if c.add {
c.groups = append(c.groups, addgroups([]string{group}, nil)...)
c.groups = append(c.groups, addgroups(db, []string{group}, nil)...)
}
}
rows.Close()
@ -101,16 +99,16 @@ func filter(msg string, foo bot) cmd {
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 := "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 += " 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 {
func addgroups(db *sql.DB, 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 (?)")
@ -141,7 +139,7 @@ func addgroups(new_groups []string, msg *irc_msg) []string {
return groupids_added
}
func checkSorter(msg *irc_msg, c *cmd) bool {
func checkSorter(db *sql.DB, 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)
@ -170,7 +168,7 @@ func checkSorter(msg *irc_msg, c *cmd) bool {
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))
//sorter_groups_row, err := foo.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
@ -199,7 +197,7 @@ func checkSorter(msg *irc_msg, c *cmd) bool {
return true
}
func chooseEntry(msg *irc_msg, c *cmd) {
func chooseEntry(db *sql.DB, msg *irc_msg, c *cmd) {
task := getRandomEntry(*c)
LOG_INFO.Printf(task)
@ -218,7 +216,7 @@ func chooseEntry(msg *irc_msg, c *cmd) {
}
}
func addLine(msg *irc_msg, line string, groups []string, cmd string) string {
func addLine(db *sql.DB, 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)
@ -226,7 +224,7 @@ func addLine(msg *irc_msg, line string, groups []string, cmd string) string {
LOG_WARN.Printf("added line to table.\n")
// get ID of content...
line_id, err := res.LastInsertId();
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, "-"))
@ -247,12 +245,13 @@ func addLine(msg *irc_msg, line string, groups []string, cmd string) string {
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,","))
return fmt.Sprintf("new line: > %s < (ID %d), into groups %s", line, line_id, strings.Join(groups, ","))
}
// line:
// >befehl <[groups]> <name>
// befehl ist genau ein wort
func parsemsg(msg *irc_msg, foo bot) bool {
func parsemsg(msg *irc_msg, conn net.Conn, db *sql.DB, nickname string) bool {
if len((*msg).msg) <= 0 {
return false
}
@ -265,7 +264,7 @@ func parsemsg(msg *irc_msg, foo bot) bool {
}
(*msg).msg = (*msg).msg[1:]
c := filter((*msg).msg, foo)
c := filter((*msg).msg, conn, db, nickname)
if !c.valid {
LOG_WARN.Printf("non valid input found.\n")
if c.error != "" {
@ -284,7 +283,7 @@ func parsemsg(msg *irc_msg, foo bot) bool {
}
if c.cmd == "slap" {
who := []string{(*msg).author, "\x01ACTION"}
whom := []string{(*msg).author, foo.Conf.Name}
whom := []string{(*msg).author, nickname}
LOG_WARN.Printf("suffix: " + c.suffix)
if c.suffix != "" {
who = append(who, strings.Split(c.suffix, " ")...)
@ -295,28 +294,28 @@ func parsemsg(msg *irc_msg, foo bot) bool {
}
// hard code 'groups' to add new groups to the groups-table
if c.add && (c.cmd == "groups" || c.cmd == "group") {
if (c.groups != nil) {
if c.groups != nil {
(*msg).retmsg = "Ignoring groups for the groups-adding. Well, what were you expecting...?"
}
addgroups(strings.Fields((&c).suffix), msg)
addgroups(db, strings.Fields((&c).suffix), msg)
return false
}
// have a look at sorter table if command is valid
if !checkSorter(msg, &c) {
if !checkSorter(db, 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;
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))
c.suffix = strings.Replace(c.suffix, "\"", "'", -1)
sendmsg(conn, "horscchtey", addLine(db, msg, c.suffix, c.groups, c.cmd))
} else {
chooseEntry(msg, &c)
chooseEntry(db, msg, &c)
}
return true
}

122
bot.go
View file

@ -1,24 +1,23 @@
package main
import (
"log"
"fmt"
"net"
"time"
"bufio"
"strings"
"database/sql"
configo "github.com/distributedio/configo"
"flag"
"fmt"
_ "github.com/mattn/go-sqlite3"
"net"
"strings"
"time"
)
func sendmsg (conn net.Conn, channel string, msg string) {
func sendmsg(conn net.Conn, channel string, msg string) {
mesg := fmt.Sprintf("PRIVMSG %s :%s\r\n", channel, msg)
fmt.Printf(mesg)
conn.Write([]byte(mesg))
}
func scanline_privmsg (msg string, irc *irc_msg) {
func scanline_privmsg(msg string, irc *irc_msg) {
LOG_ERR.Printf(msg)
msg = msg[1:]
@ -30,38 +29,36 @@ func scanline_privmsg (msg string, irc *irc_msg) {
(*irc).channel, (*irc).msg = t[0], t[1]
t = strings.Split((*irc).msg, "\r\n")
(*irc).msg = strings.TrimSpace(t[0])
if ! strings.HasPrefix((*irc).channel, "#") {
if !strings.HasPrefix((*irc).channel, "#") {
(*irc).channel = (*irc).author
}
(*irc).retmsg = ""
}
func bot_connect(bot *bot) {
conn, err := net.Dial("tcp", (*bot).Conf.Server)
func bot_connect(server string) net.Conn {
conn, err := net.Dial("tcp", server)
if err != nil {
LOG_ERR.Printf("Error while dialing server.")
(*bot).conn = nil
return
LOG_ERR.Printf("Error while dialing server: %s.", server)
return nil
}
(*bot).conn = conn
fmt.Fprintf((*bot).conn, "USER %s 1 1 1:%s\r\n", (*bot).Conf.Name, (*bot).Conf.Name)
return conn
}
func bot_register(bot *bot) {
func bot_register(conn net.Conn, nickname string, channels []string) {
/* connect to irc */
fmt.Fprintf((*bot).conn, "NICK %s\r\n", (*bot).Conf.Name)
for _, channel := range((*bot).Conf.Channels) {
fmt.Fprintf((*bot).conn, "JOIN %s\r\n", channel)
fmt.Fprintf(conn, "USER %s 1 1 1:%s\r\n", nickname, nickname)
fmt.Fprintf(conn, "NICK %s\r\n", nickname)
for _, channel := range channels {
fmt.Fprintf(conn, "JOIN %s\r\n", channel)
}
}
func bot_listen(bot *bot) <-chan string {
func bot_listen(conn net.Conn, db *sql.DB, nickname string, channels []string) <-chan string {
c := make(chan string)
bot_register(bot)
bot_register(conn, nickname, channels)
go func(timeoutNormal time.Duration, timeoutVersion time.Duration) {
bufReader := bufio.NewReader((*bot).conn)
bufReader := bufio.NewReader(conn)
timeoutDuration := timeoutNormal
waitversion := false
@ -69,11 +66,11 @@ func bot_listen(bot *bot) <-chan string {
defer func() {
fmt.Println("Closing connection...")
close(c)
(*bot).conn.Close()
conn.Close()
}()
for {
(*bot).conn.SetReadDeadline(time.Now().Add(timeoutDuration))
conn.SetReadDeadline(time.Now().Add(timeoutDuration))
line, err := bufReader.ReadString('\n')
if err != nil {
@ -84,7 +81,7 @@ func bot_listen(bot *bot) <-chan string {
return
}
n, err := (*bot).conn.Write([]byte("VERSION\n"))
n, err := conn.Write([]byte("VERSION\n"))
fmt.Printf("n: %d, err: %s\n", n, err)
if err != nil {
fmt.Println("Writing to channel failed.")
@ -106,56 +103,93 @@ func bot_listen(bot *bot) <-chan string {
c <- line
if strings.Contains(line, "PING") {
(*bot).conn.Write([]byte(strings.Replace(line, "PING", "PONG", 1)))
conn.Write([]byte(strings.Replace(line, "PING", "PONG", 1)))
} else if strings.Contains(line, "You have not registered") {
// set nickname
time.Sleep(10 * time.Second)
bot_register(bot)
bot_register(conn, nickname, channels)
} else if strings.Contains(line, "PRIVMSG") {
var msg irc_msg
scanline_privmsg(line, &msg)
LOG_ERR.Printf(msg.author)
parsemsg(&msg, (*bot))
parsemsg(&msg, conn, db, nickname)
if msg.retmsg != "" {
sendmsg((*bot).conn, msg.channel, msg.retmsg)
sendmsg(conn, msg.channel, msg.retmsg)
}
}
}
} (4 * time.Minute, 1 * time.Minute)
}(4*time.Minute, 1*time.Minute)
return c
}
func bot_run(bot *bot) {
func db_open(info string) *sql.DB {
LOG_INFO.Printf("Opening database: %s", info)
var db *sql.DB = nil
var err error
parts := strings.SplitN(info, ":", 2)
if len(parts) == 2 {
db, err = sql.Open(parts[0], parts[1])
} else {
db, err = sql.Open("sqlite3", info)
}
if err != nil {
return nil
}
return db
}
func bot_run(server string, nickname string, database string, channels []string) {
LOG_INFO.Println("Bot ready to run.")
LOG_INFO.Println("Opening database.")
db, err = sql.Open("sqlite3", (*bot).Conf.Database)
if err != nil {
db := db_open(database)
if db == nil {
LOG_ERR.Println("Opening database failed.")
return
}
for {
bot_connect(bot)
if bot.conn == nil {
conn := bot_connect(server)
if conn == nil {
LOG_INFO.Printf("Bot is nil. Try to connect again.")
time.Sleep(10 * time.Second)
continue
}
for val := range bot_listen(bot) {
for val := range bot_listen(conn, db, nickname, channels) {
LOG_INFO.Printf("%s", val)
}
}
}
type stringList []string
func (i *stringList) String() string {
return fmt.Sprintf("%v", *i)
}
func (i *stringList) Set(value string) error {
*i = append(*i, value)
return nil
}
func main() {
LOG_init()
var boddle bot
if err := configo.Load("./boddle.toml", &boddle.Conf); err != nil {
log.Fatal(err)
}
var channels stringList
bot_run(&boddle)
flag.Var(&channels, "channel", "channels to connect")
server := flag.String("server", "irc.ircnet.com:6667", "domain:port for irc-server")
nickname := flag.String("nick", "boddle", "nickname to use for bot")
database := flag.String("database", "./boddle.db", "database to use")
flag.Parse()
LOG_INFO.Printf("server: %s", *server)
LOG_INFO.Printf("nick: %s", *nickname)
bot_run(*server, *nickname, *database, channels)
}

View file

@ -1,8 +0,0 @@
package main
type Boddle struct {
name string `cfg:"name; boddle; printableascii; IRC nick of bot"`
channels []string `cfg:"channels; required; printableascii; Channel list to join to"`
server string `cfg:"server; required; netaddr; Server name to connect to"`
database string `cfg:"database; ./boddle.db; path; Path to database"`
}

View file

@ -11,7 +11,7 @@ func checkErr(err error) {
}
}
func in (a byte, arr []byte) bool {
func in(a byte, arr []byte) bool {
for _, x := range arr {
if x == a {
return true

View file

@ -6,9 +6,9 @@ import (
)
var (
LOG_WARN *log.Logger
LOG_INFO *log.Logger
LOG_ERR *log.Logger
LOG_WARN *log.Logger
LOG_INFO *log.Logger
LOG_ERR *log.Logger
)
func LOG_init() {
@ -16,5 +16,5 @@ func LOG_init() {
LOG_INFO = log.New(file, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)
LOG_WARN = log.New(file, "WARNING: ", log.Ldate|log.Ltime|log.Lshortfile)
LOG_ERR = log.New(file, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)
LOG_ERR = log.New(file, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)
}

View file

@ -1,34 +1,17 @@
package main
import (
"net"
)
type Config struct {
Name string `cfg:"name; boddle; printableascii; IRC nick of bot"`
Channels []string `cfg:"channels; required; printableascii; Channel list to join to"`
Server string `cfg:"server; required; netaddr; Server name to connect to"`
Database string `cfg:"database; ./boddle.db; path; Path to database"`
}
type irc_msg struct {
channel string
msg string
author string
retmsg string
channel string
msg string
author string
retmsg string
}
type cmd struct {
valid bool
add bool
cmd string
groups []string
suffix string
error string
valid bool
add bool
cmd string
groups []string
suffix string
error string
}
type bot struct {
Conf Config
conn net.Conn
}