add the ability to send / receive responses over mail

This commit is contained in:
Aaron Bieber 2024-06-21 14:16:55 -06:00
parent 2ea5b0c1ae
commit bbf122597c
No known key found for this signature in database
5 changed files with 342 additions and 84 deletions

286
chats/mail.go Normal file
View File

@ -0,0 +1,286 @@
package chats
import (
"bytes"
"crypto/tls"
"fmt"
"io"
"log"
"net/smtp"
"strings"
"time"
"github.com/emersion/go-imap"
"github.com/emersion/go-imap/client"
"github.com/emersion/go-message/mail"
"suah.dev/mcchunkie/plugins"
)
type mmail struct {
smtpUser string
smtpServer string
password string
imapClient *client.Client
updateChan chan client.Update
}
func (m *mmail) buildFancyReply(msgID, to, from, originalSubject, resp string) error {
buf := new(bytes.Buffer)
w, err := mail.CreateWriter(buf, mail.HeaderFromMap(map[string][]string{
"From": {to},
"To": {from},
"Subject": {"Re: " + originalSubject},
"References": {msgID},
"In-Reply-To": {msgID},
}))
if err != nil {
return err
}
textHeader := mail.InlineHeader{}
textPart, err := w.CreateSingleInline(textHeader)
if err != nil {
return err
}
_, err = textPart.Write([]byte(resp + "\r\n"))
if err != nil {
return err
}
if err := textPart.Close(); err != nil {
return err
}
if err := w.Close(); err != nil {
return err
}
return m.send(to, from, buf.Bytes())
}
func (m *mmail) send(to, from string, data []byte) error {
conn, err := tls.Dial("tcp", m.smtpServer, &tls.Config{})
if err != nil {
log.Println(err)
return err
}
defer conn.Close()
host := strings.TrimRight(m.smtpServer, ":")
sc, err := smtp.NewClient(conn, host)
if err != nil {
log.Println(err)
return err
}
defer sc.Close()
sc.Auth(smtp.PlainAuth("", m.smtpUser, m.password, host))
if err := sc.Mail(to); err != nil {
log.Println(err)
return err
}
if err := sc.Rcpt(from); err != nil {
log.Println(err)
return err
}
wc, err := sc.Data()
if err != nil {
log.Println(err)
return err
}
fmt.Fprint(wc, string(data))
err = wc.Close()
if err != nil {
log.Println(err)
return err
}
return sc.Quit()
}
func (m *mmail) buildReply(msgID, subj, to, from, resp string) error {
log.Printf("Mail: smtp sending mail to: %q, from: %q", from, to)
reSubj := fmt.Sprintf("Re: %s", subj)
wc := new(bytes.Buffer)
fmt.Fprintf(wc, fmt.Sprintf("To: %s\r\n", from))
fmt.Fprintf(wc, fmt.Sprintf("From: %s\r\n", to))
fmt.Fprintf(wc, fmt.Sprintf("Subject: %s\r\n", reSubj))
fmt.Fprintf(wc, fmt.Sprintf("References: %s\r\n", msgID))
fmt.Fprintf(wc, fmt.Sprintf("In-Reply-To: %s\r\n", msgID))
fmt.Fprintf(wc, "\r\n"+resp+"\r\n")
return m.send(to, from, wc.Bytes())
}
func MailListen(store ChatStore, plugins *plugins.Plugins) error {
var (
smtpUser, _ = store.Get("smtp_user")
smtpServer, _ = store.Get("smtp_server")
imapServer, _ = store.Get("imap_server")
imapUser, _ = store.Get("imap_user")
mailPass, _ = store.Get("mail_password")
)
m := mmail{
smtpUser: smtpUser,
smtpServer: smtpServer,
password: mailPass,
updateChan: make(chan client.Update),
}
c, err := client.DialTLS(imapServer, nil)
if err != nil {
return err
}
log.Printf("Mail: connected to %q", imapServer)
m.imapClient = c
defer m.imapClient.Logout()
if err = m.imapClient.Login(imapUser, mailPass); err != nil {
return err
}
log.Printf("Mail: logged in as %q", imapUser)
_, err = m.imapClient.Select("INBOX", false)
if err != nil {
return err
}
m.imapClient.Updates = m.updateChan
go func() {
for update := range m.updateChan {
switch update.(type) {
case *client.MessageUpdate:
log.Println("Mail: received new message")
crit := imap.NewSearchCriteria()
crit.WithoutFlags = []string{imap.SeenFlag}
ids, err := m.imapClient.Search(crit)
if err != nil {
log.Println(err)
continue
}
if len(ids) == 0 {
log.Println(len(ids))
continue
}
seq := &imap.SeqSet{}
seq.AddNum(ids...)
messages := make(chan *imap.Message, 10)
done := make(chan error, 1)
// Mark the messages as read
bodySeq := &imap.BodySectionName{
Peek: false,
}
go func() {
done <- c.Fetch(seq, []imap.FetchItem{bodySeq.FetchItem()}, messages)
}()
for msg := range messages {
fullMsg := msg.GetBody(bodySeq)
to, from, subj, msg, msgID := "", "", "", "", ""
mr, err := mail.CreateReader(fullMsg)
if err != nil {
log.Println(err)
continue
}
for {
part, err := mr.NextPart()
if err == io.EOF {
break
} else if err != nil {
log.Println(err)
continue
}
maybeSubj := part.Header.Get("Subject")
if maybeSubj != "" {
subj = maybeSubj
}
maybeTo := part.Header.Get("To")
if maybeTo != "" {
to = maybeTo
}
maybeFrom := part.Header.Get("From")
if maybeFrom != "" {
from = maybeFrom
}
maybeID := part.Header.Get("Message-ID")
if maybeID != "" {
msgID = maybeID
}
switch part.Header.(type) {
case *mail.InlineHeader:
b, _ := io.ReadAll(part.Body)
msg = strings.TrimSpace(string(b))
}
log.Printf("to: %q, from: %q, subj: %q, msg: %q", to, from, subj, msg)
}
if to != "" && from != "" && msg != "" && subj != "" {
for _, p := range *plugins {
if p.Match(from, msg) {
log.Printf("%s: responding to '%s'", p.Name(), from)
p.SetStore(store)
resp := p.Process(from, msg)
log.Println(resp)
/*
err := m.buildReply(msgID, subj, to, from, resp)
if err != nil {
log.Println(err)
continue
}
*/
err := m.buildFancyReply(msgID, to, from, subj, resp)
if err != nil {
log.Println(err)
continue
}
}
}
}
}
if err := <-done; err != nil {
log.Fatal(err)
}
}
}
}()
for {
if err := m.imapClient.Noop(); err != nil {
return err
}
time.Sleep(1 * time.Second)
}
}

View File

@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
"net/smtp"
"strings" "strings"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
@ -23,11 +22,9 @@ func smsCanSend(number string, numbers []string) bool {
// SMSListen listens for our incoming sms // SMSListen listens for our incoming sms
func SMSListen(store ChatStore, plugins *plugins.Plugins) { func SMSListen(store ChatStore, plugins *plugins.Plugins) {
var ( var (
smsPort, _ = store.Get("sms_listen") smsPort, _ = store.Get("sms_listen")
smsAllowed, _ = store.Get("sms_users") smsAllowed, _ = store.Get("sms_users")
smtpUser, _ = store.Get("smtp_user") smsUsers = strings.Split(smsAllowed, ",")
smtpReceiver, _ = store.Get("smtp_receiver")
smsUsers = strings.Split(smsAllowed, ",")
) )
if smsPort != "" { if smsPort != "" {
@ -36,8 +33,7 @@ func SMSListen(store ChatStore, plugins *plugins.Plugins) {
log.Printf("SMS: listening on %q\n", smsPort) log.Printf("SMS: listening on %q\n", smsPort)
http.HandleFunc("/_sms", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/_sms", func(w http.ResponseWriter, r *http.Request) {
var msg, from, id string var msg, from string
emailSend := false
user, pass, ok := r.BasicAuth() user, pass, ok := r.BasicAuth()
if !ok { if !ok {
log.Println("SMS: basic auth no ok") log.Println("SMS: basic auth no ok")
@ -72,11 +68,8 @@ func SMSListen(store ChatStore, plugins *plugins.Plugins) {
from = r.Form.Get("From") from = r.Form.Get("From")
case http.MethodGet: case http.MethodGet:
// to={TO}&from={FROM}&message={MESSAGE}&id={ID}&date={TIMESTAMP} // to={TO}&from={FROM}&message={MESSAGE}&id={ID}&date={TIMESTAMP}
id = r.URL.Query().Get("id")
msg = r.URL.Query().Get("message") msg = r.URL.Query().Get("message")
from = r.URL.Query().Get("from") from = r.URL.Query().Get("from")
emailSend = true
default: default:
http.Error( http.Error(
w, w,
@ -100,58 +93,7 @@ func SMSListen(store ChatStore, plugins *plugins.Plugins) {
p.SetStore(store) p.SetStore(store)
resp := p.Process(from, msg) resp := p.Process(from, msg)
fmt.Fprint(w, resp)
if emailSend {
sc, err := smtp.Dial("localhost:25")
if err != nil {
log.Printf("SMS: smtp dial failed: %q\n", err)
http.Error(w, "internal server error", http.StatusInternalServerError)
return
}
if err := sc.Mail(smtpUser); err != nil {
log.Printf("SMS: smtp Mail failed: %q\n", err)
http.Error(w, "internal server error", http.StatusInternalServerError)
return
}
if err := sc.Rcpt(smtpReceiver); err != nil {
log.Printf("SMS: smtp Rcpt failed: %q\n", err)
http.Error(w, "internal server error", http.StatusInternalServerError)
return
}
wc, err := sc.Data()
if err != nil {
log.Printf("SMS: smtp Data failed: %q\n", err)
http.Error(w, "internal server error", http.StatusInternalServerError)
return
}
log.Printf("SMS: smtp sending id: %q to: %q, from: %q", id, smtpReceiver, smtpUser)
fmt.Fprintf(wc, fmt.Sprintf("To: %s\r\n", smtpReceiver))
fmt.Fprintf(wc, fmt.Sprintf("From: %s\r\n", smtpUser))
fmt.Fprintf(wc, fmt.Sprintf("Subject: Message received from number %s to number %s [%s]\r\n", from, from, id))
fmt.Fprintf(wc, resp)
err = wc.Close()
if err != nil {
log.Printf("SMS: smtp Close failed: %q\n", err)
http.Error(w, "internal server error", http.StatusInternalServerError)
return
}
err = sc.Quit()
if err != nil {
log.Printf("SMS: smtp Quit failed: %q\n", err)
http.Error(w, "internal server error", http.StatusInternalServerError)
return
}
} else {
fmt.Fprint(w, resp)
}
} }
} }
} else { } else {

16
go.mod
View File

@ -7,17 +7,21 @@ toolchain go1.22.3
require ( require (
github.com/ProtonMail/go-crypto v1.0.0 github.com/ProtonMail/go-crypto v1.0.0
github.com/caneroj1/stemmer v0.0.0-20170128035808-c9f2ce1504d5 github.com/caneroj1/stemmer v0.0.0-20170128035808-c9f2ce1504d5
github.com/emersion/go-imap v1.2.1
github.com/emersion/go-message v0.18.1
github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2 github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530
github.com/ollama/ollama v0.1.39 github.com/ollama/ollama v0.1.44
golang.org/x/crypto v0.23.0 golang.org/x/crypto v0.24.0
golang.org/x/net v0.25.0 golang.org/x/net v0.26.0
golang.org/x/term v0.20.0 golang.org/x/term v0.21.0
gopkg.in/irc.v3 v3.1.4 gopkg.in/irc.v3 v3.1.4
suah.dev/protect v1.2.3 suah.dev/protect v1.2.4
) )
require ( require (
github.com/cloudflare/circl v1.3.3 // indirect github.com/cloudflare/circl v1.3.3 // indirect
golang.org/x/sys v0.20.0 // indirect github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
) )

36
go.sum
View File

@ -8,12 +8,20 @@ github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUK
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjTA=
github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY=
github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4=
github.com/emersion/go-message v0.18.1 h1:tfTxIoXFSFRwWaZsgnqS1DSZuGpYGzSmCZD8SK3QA2E=
github.com/emersion/go-message v0.18.1/go.mod h1:XpJyL70LwRvq2a8rVbHXikPgKj8+aI0kGdHlg16ibYA=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2 h1:yEt5djSYb4iNtmV9iJGVday+i4e9u6Mrn5iP64HH5QM= github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2 h1:yEt5djSYb4iNtmV9iJGVday+i4e9u6Mrn5iP64HH5QM=
github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U=
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
github.com/ollama/ollama v0.1.39 h1:EYMew3AxWGXSrBycyjHhMEqau0dljg3s334Yfpx9ir8= github.com/ollama/ollama v0.1.44 h1:3Htzf/mn0nNn1oBOm3rdnbSfX6dOTpOW0YRnxYTsqbo=
github.com/ollama/ollama v0.1.39/go.mod h1:dOOmmCPUbZJGdHLPbhghW7HCa8CUA8SP6edbRLqxNBs= github.com/ollama/ollama v0.1.44/go.mod h1:TvVa25PEZI6M0bosiW1sa2XJGq3Xw/OPlpUAkMEntTU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -25,8 +33,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@ -35,8 +43,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -47,24 +55,28 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
@ -78,5 +90,5 @@ gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
suah.dev/protect v1.2.3 h1:aHeoNwZ9YPp64hrYaN0g0djNE1eRujgH63CrfRrUKdc= suah.dev/protect v1.2.4 h1:iVZG/zQB63FKNpITDYM/cXoAeCTIjCiXHuFVByJFDzg=
suah.dev/protect v1.2.3/go.mod h1:n1R3XIbsnryKX7C1PO88i5Wgo0v8OTXm9K9FIKt4rfs= suah.dev/protect v1.2.4/go.mod h1:vVrquYO3u1Ep9Ez2z8x+6N6/czm+TBmWKZfiXU2tb54=

20
main.go
View File

@ -31,11 +31,12 @@ A [Matrix](https://matrix.org) chat bot.`
func main() { func main() {
var username, shortName, password, userID, accessToken, server, db, avatar, botOwner, prof string var username, shortName, password, userID, accessToken, server, db, avatar, botOwner, prof string
var key, value, get string var key, value, get string
var setup, doc, verbose bool var setup, doc, verbose, irc bool
flag.BoolVar(&doc, "doc", false, "print plugin information and exit") flag.BoolVar(&doc, "doc", false, "print plugin information and exit")
flag.BoolVar(&setup, "s", false, "setup account") flag.BoolVar(&setup, "s", false, "setup account")
flag.BoolVar(&verbose, "v", false, "print verbose messages") flag.BoolVar(&verbose, "v", false, "print verbose messages")
flag.BoolVar(&irc, "irc", true, "enable irc")
flag.StringVar(&avatar, "avatar", "", "set the avatar of the bot to specified url") flag.StringVar(&avatar, "avatar", "", "set the avatar of the bot to specified url")
flag.StringVar(&db, "db", "db", "full path to database directory") flag.StringVar(&db, "db", "db", "full path to database directory")
@ -216,15 +217,28 @@ func main() {
go func() { go func() {
for { for {
err := chats.IRCConnect(store, &plugins.Plugs) err := chats.MailListen(store, &plugins.Plugs)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
} }
log.Println("IRC: reconnecting in 60 seconds") log.Println("Mail: reconnecting in 60 seconds")
time.Sleep(time.Second * 60) time.Sleep(time.Second * 60)
} }
}() }()
if irc {
go func() {
for {
err := chats.IRCConnect(store, &plugins.Plugs)
if err != nil {
log.Println(err)
}
log.Println("IRC: reconnecting in 60 seconds")
time.Sleep(time.Second * 60)
}
}()
}
go func() { go func() {
for { for {
errataCount := 0 errataCount := 0