initial commit

This commit is contained in:
Cadey Ratio 2017-05-10 14:30:31 -07:00
commit 92e328314a
3 changed files with 113 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.env
*.so

15
README.md Normal file
View File

@ -0,0 +1,15 @@
# ircsuite
Like tootsuite but for IRC.
This basically connects to Mastodon and then relays public, home, and optionally hashtag searches to your IRC client, bot or script can react to toots in real time.
## TODO
- [ ] Hashtag streaming by joining `#hashtag`
- [ ] Multiple mastodon account support
`#/<accname>/<hashtag>` ?
- [ ] Multiple user support
- [ ] Full text searches by joining `?terms+in+query+syntax`
Common paginated contextual UI concepts that people have been talking about for chatbots might be amazing here, as that is what this would basically be.
- [ ]

96
main.go Normal file
View File

@ -0,0 +1,96 @@
package main
import (
"context"
"net"
"github.com/Xe/ln"
"github.com/caarlos0/env"
"gopkg.in/irc.v1"
)
type Config struct {
ServerName string `env:"SERVER_NAME" envDefault:"to.ot"`
ServerAddr string `env:"SERVER_ADDR" envDefault:"127.0.0.1:42069"`
// XXX RIP HACK TODO fix once user accounts exist
UserPassword string `env:"USER_PASSWORD" envDefault:"hunter2"`
MastodonInstance string `env:"MASTODON_INSTANCE,required"`
MastodonToken string `env:"MASTODON_TOKEN,required"`
MastodonClientID string `env:"MASTODON_CLIENT_ID,required"`
MastodonClientSecret string `env:"MASTODON_CLIENT_SECRET,required"`
}
func main() {
cfg := Config{}
err := env.Parse(&cfg)
if err != nil {
ln.Fatal(ln.F{"err": err})
}
l, err := net.Listen(cfg.ServerAddr)
if err != nil {
ln.Fatal(ln.F{"err": err, "addr": cfg.ServerAddr})
}
for {
ctx := context.Context()
conn, err := l.Accept()
if err != nil {
ln.Error(err, ln.F{"addr": cfg.ServerAddr})
}
ir := irc.NewReader(conn)
iw := irc.NewWriter(conn)
msg, err := ir.ReadMessage()
if err != nil {
ln.Error(err, ln.F{"client_addr": conn.RemoteAddr().String()})
conn.Close()
continue
}
if msg.Command != "PASS" {
ln.Log(ln.F{"action": "auth_failed", "client_addr": conn.RemoteAddr().String()})
iw.Writef(":%s ERROR :authentication failed", cfg.ServerName)
conn.Close()
continue
}
if msg.Params[0] != cfg.UserPassword {
ln.Log(ln.F{"action": "wrong_password", "client_addr": conn.RemoteAddr().String()})
iw.Writef(":%s ERROR :authentication failed", cfg.ServerName)
conn.Close()
continue
}
mc, err := madon.RestoreApp("ircsuite", cfg.MastodonInstance, cfg.MastodonClientID, cfg.MastodonClientSecret, &madon.UserToken{AccessToken: cfg.MastodonToken})
if err != nil {
ln.Error(ln.F{"action": "madon.RestoreApp"})
iw.Writef(":%s ERROR :authentication failed", cfg.ServerName)
conn.Close()
continue
}
_ = mc
s := &Server{
channels: map[string]struct{}{},
mc: mc,
iw: iw,
ir: ir,
}
go s.HandleConn(ctx, conn)
}
}
type Server struct {
sync.Mutex // locked at per line execution
channels map[string]struct{} // channels the client has joined
mc *madon.Client
iw *irc.Writer
ir *irc.Reader
}