Compare commits

..

3 Commits

4
.gitignore vendored

@ -5,3 +5,7 @@ plugins
squirssi*.log
vendor/
config.toml
*-packr.go
node_modules
yarn.lock
package-lock.json

@ -1,35 +1,42 @@
FROM veonik/squirssi:build-amd64 AS build
FROM golang:alpine AS build
ARG race
ARG plugin_type=shared
FROM debian:buster-slim
RUN apk update && apk add yarn alpine-sdk upx
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y ca-certificates curl gnupg && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && \
apt-get install -y yarn
RUN go get -v github.com/gobuffalo/packr/v2/packr2
COPY config.toml.dist /home/squirssi/.squirssi/config.toml
WORKDIR /squirssi
COPY . .
RUN go get -v ./...
RUN export SQUIRCY3_REVISION=$(cat go.mod | grep squircy3 | cut -d' ' -f2 | cut -d'-' -f3) && \
git clone https://code.dopame.me/veonik/squircy3 ../squircy3 && \
cd ../squircy3 && \
git checkout $SQUIRCY3_REVISION
RUN make clean dist RACE=${race} PLUGIN_TYPE=${plugin_type}
COPY package.json /home/squirssi/.squirssi/scripts/package.json
RUN cd /home/squirssi/.squirssi/scripts && \
yarn install
FROM alpine:latest
RUN apk update && \
apk add yarn alpine-sdk upx
COPY --from=build /squirssi/out/squirssi_linux_amd64 /bin/squirssi
COPY --from=build /squirssi/out/*.so /squirssi/plugins/
COPY --from=build /squirssi/out/*.so /home/squirssi/.squirssi/plugins
RUN cd /squirssi/plugins && \
RUN cd /home/squirssi/.squirssi/plugins && \
for f in `ls`; do ln -sf $f `echo $f | sed -e 's/_linux_amd64//'`; done
RUN useradd -d /home/squirssi squirssi && \
chown -R squirssi: /home/squirssi /squirssi
RUN adduser -D -h /home/squirssi squirssi && \
chown -R squirssi: /home/squirssi
USER squirssi
WORKDIR /squirssi
CMD /bin/squirssi

@ -1,30 +0,0 @@
FROM golang:buster AS build
ARG race
ARG goarch
ARG goarm
WORKDIR /squirssi
COPY . .
RUN go get -v ./...
RUN export SQUIRCY3_REVISION=$(cat go.mod | grep squircy3 | cut -d' ' -f2 | cut -d'-' -f3) && \
git clone https://github.com/veonik/squircy3 ../squircy3 && \
cd ../squircy3 && \
git checkout $SQUIRCY3_REVISION
RUN apt-get update && \
if [ "${goarch}" = "arm" ]; then \
apt-get install -y gcc-arm-linux-gnueabihf; \
elif [ "${goarch}" = "arm64" ]; then \
apt-get install -y gcc-aarch64-linux-gnu; \
fi;
RUN if [ "${goarch}" = "arm" ]; then \
CC=arm-linux-gnueabihf-gcc; \
elif [ "${goarch}" = "arm64" ]; then \
CC=aarch64-linux-gnu-gcc; \
fi; \
make clean dist RACE=${race} GOARCH=${goarch} GOARM=${goarm} CC=$CC

@ -18,33 +18,46 @@ OUTPUT_BASE := out
RACE ?= -race
TEST_ARGS ?= -count 1
PLUGIN_TYPE ?= shared
GOOS ?= $(shell go env GOOS)
GOARCH ?= $(shell go env GOARCH)
GOARM ?= $(shell go env GOARM)
CC ?= $(shell go env CC)
PACKR ?= $(shell which packr2)
PLUGIN_TARGETS := $(patsubst %,$(OUTPUT_BASE)/%.so,$(PLUGINS))
SQUIRSSI_TARGET := $(OUTPUT_BASE)/squirssi
SQUIRSSI_DIST := $(OUTPUT_BASE)/squirssi_$(GOOS)_$(GOARCH)$(GOARM)
PLUGIN_DIST := $(patsubst %,$(OUTPUT_BASE)/%_$(GOOS)_$(GOARCH)$(GOARM).so,$(PLUGINS))
DIST_TARGETS := $(SQUIRSSI_DIST) $(PLUGIN_DIST)
SQUIRSSI_VERSION := $(if $(shell test -d .git && echo "1"),$(shell git describe --always --tags),SNAPSHOT)
SQUIRCY3_VERSION := $(if $(shell test -d $(SQUIRCY3_ROOT)/.git && echo "1"),$(shell cd $(SQUIRCY3_ROOT) && git describe --always --tags),SNAPSHOT)
ifeq ($(PLUGIN_TYPE),linked)
PLUGIN_TARGETS :=
EXTRA_TAGS := -tags linked_plugins
DIST_TARGETS := $(SQUIRSSI_DIST)
LINKED_PLUGINS_FILE := cmd/squirssi/linked_plugins.go
else
PLUGIN_TARGETS := $(patsubst %,$(OUTPUT_BASE)/%.so,$(PLUGINS))
EXTRA_TAGS :=
DIST_TARGETS := $(SQUIRSSI_DIST) $(PLUGIN_DIST)
LINKED_PLUGINS_FILE := cmd/squirssi/shared_plugins.go
endif
SQUIRSSI_VERSION ?= $(if $(shell test -d .git && echo "1"),$(shell git describe --always --tags),)
SQUIRCY3_VERSION ?= $(if $(shell test -d $(SQUIRCY3_ROOT)/.git && echo "1"),$(shell cd $(SQUIRCY3_ROOT) && git describe --always --tags),)
.PHONY: all build generate run squirssi plugins clean
.PHONY: all build run squirssi plugins clean dist
all: build plugins
clean:
cd cmd/squirssi && \
$(PACKR) clean
rm -rf $(OUTPUT_BASE)
build: squirssi
build: $(SQUIRSSI_TARGET)
dist: $(DIST_TARGETS)
squirssi: $(SQUIRSSI_TARGET)
plugins: $(PLUGIN_TARGETS)
run: build
@ -58,25 +71,30 @@ $(OUTPUT_BASE)/plugins: $(OUTPUT_BASE)
$(SQUIRSSI_TARGET): $(SOURCES)
GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) CC=$(CC) CGO_ENABLED=1 \
go build -tags netgo $(RACE) \
-ldflags "-s -w -X code.dopame.me/veonik/squirssi.Version=$(SQUIRSSI_VERSION)-SNAPSHOT -X main.Squircy3Version=$(SQUIRCY3_VERSION)-SNAPSHOT" \
-o $@ cmd/squirssi/*.go
go build -tags netgo $(EXTRA_TAGS) $(RACE) \
-ldflags "-s -w -X main.SquirssiVersion=$(SQUIRSSI_VERSION)-dev -X main.Squircy3Version=$(SQUIRCY3_VERSION)-dev" \
-o $@ cmd/squirssi/main*.go $(LINKED_PLUGINS_FILE)
$(SQUIRSSI_DIST): $(OUTPUT_BASE) $(SOURCES)
cd cmd/squirssi/defconf && \
yarn install
cd cmd/squirssi && \
$(PACKR)
GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) CC=$(CC) CGO_ENABLED=1 \
go build -tags netgo \
-ldflags "-s -w -X code.dopame.me/veonik/squirssi.Version=$(SQUIRSSI_VERSION) -X main.Squircy3Version=$(SQUIRCY3_VERSION)" \
-o $@ cmd/squirssi/*.go
go build -tags netgo $(EXTRA_TAGS) \
-ldflags "-s -w -X main.SquirssiVersion=$(SQUIRSSI_VERSION) -X main.Squircy3Version=$(SQUIRCY3_VERSION)" \
-o $@ cmd/squirssi/main*.go $(LINKED_PLUGINS_FILE)
upx $@
.SECONDEXPANSION:
$(PLUGIN_TARGETS): $(OUTPUT_BASE)/%.so: $$(wildcard plugins/%/*) $(OUTPUT_BASE)/plugins $(SOURCES)
GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) CC=$(CC) CGO_ENABLED=1 \
go build -tags netgo $(RACE) -o $@ -buildmode=plugin $(OUTPUT_BASE)/plugins/$*/*.go
go build -tags netgo $(RACE) -o $@ -buildmode=plugin $(OUTPUT_BASE)/plugins/$*/plugin/*.go
.SECONDEXPANSION:
$(PLUGIN_DIST): $(OUTPUT_BASE)/%_$(GOOS)_$(GOARCH)$(GOARM).so: $$(wildcard plugins/%/*) $(OUTPUT_BASE)/plugins $(SOURCES)
GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) CC=$(CC) CGO_ENABLED=1 \
go build -tags netgo -o $@ -buildmode=plugin $(OUTPUT_BASE)/plugins/$*/*.go
go build -tags netgo -o $@ -buildmode=plugin $(OUTPUT_BASE)/plugins/$*/plugin/*.go
$(OUTPUT_BASE):
mkdir -p $(OUTPUT_BASE)

@ -3,6 +3,7 @@ package squirssi
import (
"strconv"
"strings"
"time"
"code.dopame.me/veonik/squircy3/event"
"code.dopame.me/veonik/squircy3/irc"
@ -18,6 +19,8 @@ func modeHandler(mode string) Command {
}
}
// builtInsOrdered is ordered in that it is in the desired order with
// related commands grouped together.
var builtInsOrdered = []string{
"exit",
"connect",
@ -26,6 +29,7 @@ var builtInsOrdered = []string{
"wc",
"join",
"part",
"invite",
"topic",
"whois",
"names",
@ -46,6 +50,7 @@ var builtInsOrdered = []string{
"unmute",
"echo",
"raw",
"eval",
"help",
}
@ -57,6 +62,7 @@ var builtIns = map[string]Command{
"wc": closeWindow,
"join": joinChannel,
"part": partChannel,
"invite": inviteTarget,
"topic": topicChange,
"whois": whoisNick,
"names": namesChannel,
@ -82,19 +88,32 @@ var builtIns = map[string]Command{
"quit": disconnectServer,
"echo": func(srv *Server, args []string) {
win := srv.wm.Active()
win := srv.windows.Active()
_, _ = win.WriteString(strings.Join(args[1:], " "))
},
"raw": func(srv *Server, args []string) {
srv.IRCDoAsync(func(conn *irc.Connection) error {
conn.SendRaw(strings.Join(args[1:], " "))
win := srv.wm.Active()
win := srv.windows.Active()
if win != nil {
WriteRaw(win, "-> " + strings.Join(args[1:], " "))
WriteRaw(win, "-> "+strings.Join(args[1:], " "))
}
return nil
})
},
"eval": func(srv *Server, args []string) {
win := srv.windows.Active()
script := strings.Join(args[1:], " ")
go func() {
WriteEval(win, script)
res, err := srv.vm.RunString(script).Await()
if err != nil {
WriteEvalError(win, err.Error())
return
}
WriteEvalResult(win, res.ToString().String())
}()
},
}
var builtInDescriptions = map[string]string{
@ -104,6 +123,7 @@ var builtInDescriptions = map[string]string{
"wc": "Closes the given window by number, or the currently active window.",
"join": "Attempts to join the given channel.",
"part": "Parts the given channel.",
"invite": "Invites a user to the given channel.",
"topic": "Sets the topic for the given channel, or the currently active window.",
"whois": "Runs a WHOIS query on the given nickname.",
"names": "Runs a NAMES query on the given channel.",
@ -126,10 +146,11 @@ var builtInDescriptions = map[string]string{
"disconnect": "Disconnects from the connected IRC server.",
"echo": "Writes any arguments given to the currently active window.",
"raw": "Sends a raw IRC command.",
"eval": "Evaluate some javascript in the embedded runtime.",
}
func helpCmd(srv *Server, args []string) {
win := srv.wm.Active()
win := srv.windows.Active()
if win == nil {
return
}
@ -174,14 +195,7 @@ func exitProgram(srv *Server, _ []string) {
}
func topicChange(srv *Server, args []string) {
if len(args) < 2 || !strings.HasPrefix("#", args[1]) {
win := srv.wm.Active()
if win == nil || !strings.HasPrefix(win.Title(), "#") {
logrus.Warnln("topic: unable to determine current channel")
return
}
args = append(append([]string{}, args[0], win.Title()), args[1:]...)
}
args = guessTargetInArgs(srv, args, 1)
target := args[1]
if len(args) == 2 {
srv.IRCDoAsync(func(conn *irc.Connection) error {
@ -198,16 +212,7 @@ func topicChange(srv *Server, args []string) {
}
func kickTarget(srv *Server, args []string) {
if len(args) < 2 || !strings.HasPrefix(args[1], "#") {
win := srv.wm.Active()
t := ""
if win == nil || win.Title() == "status" {
t = srv.CurrentNick()
} else {
t = win.Title()
}
args = append(append([]string{}, args[0], t), args[1:]...)
}
args = guessTargetInArgs(srv, args, 1)
target := args[1]
if len(target) > 0 && target[0] != '#' {
logrus.Warnln("kick: unable to determine current channel")
@ -223,7 +228,7 @@ func kickTarget(srv *Server, args []string) {
func modeChange(srv *Server, args []string) {
if len(args) < 2 || strings.HasPrefix(args[1], "+") || strings.HasPrefix(args[1], "-") {
win := srv.wm.Active()
win := srv.windows.Active()
t := ""
if win == nil || win.Title() == "status" {
t = srv.CurrentNick()
@ -234,7 +239,35 @@ func modeChange(srv *Server, args []string) {
}
target := args[1]
modes := args[2:]
var irc324Handler event.Handler
var irc329Handler event.Handler
if len(modes) == 0 || len(modes[0]) == 0 {
irc324Handler = event.HandlerFunc(func(ev *event.Event) {
args := ev.Data["Args"].([]string)
modes := strings.Join(args[2:], " ")
win := srv.windows.Named(args[1])
WriteModes(win, modes)
srv.events.Unbind("irc.324", irc324Handler)
})
irc329Handler = event.HandlerFunc(func(ev *event.Event) {
args := ev.Data["Args"].([]string)
target := args[1]
win := srv.windows.Named(target)
if _, ok := win.(*Channel); ok {
created, _ := strconv.Atoi(args[2])
t := time.Unix(int64(created), 0)
Write329(win, t)
}
srv.events.Unbind("irc.329", irc329Handler)
})
}
srv.IRCDoAsync(func(conn *irc.Connection) error {
if irc324Handler != nil {
srv.events.Bind("irc.324", irc324Handler)
}
if irc329Handler != nil {
srv.events.Bind("irc.329", irc329Handler)
}
conn.Mode(target, modes...)
return nil
})
@ -251,13 +284,13 @@ func selectWindow(srv *Server, args []string) {
logrus.Warnln("window: expected first argument to be an integer")
return
}
srv.wm.SelectIndex(ch)
srv.windows.SelectIndex(ch)
}
func closeWindow(srv *Server, args []string) {
var ch int
if len(args) < 2 {
ch = srv.wm.ActiveIndex()
ch = srv.windows.ActiveIndex()
} else {
var err error
ch, err = strconv.Atoi(args[1])
@ -266,7 +299,7 @@ func closeWindow(srv *Server, args []string) {
return
}
}
win := srv.wm.Index(ch)
win := srv.windows.Index(ch)
if ch, ok := win.(*Channel); ok {
myNick := srv.CurrentNick()
if ch.HasUser(myNick) {
@ -276,27 +309,60 @@ func closeWindow(srv *Server, args []string) {
})
}
}
srv.wm.CloseIndex(ch)
srv.windows.CloseIndex(ch)
}
func guessTargetInArgs(srv *Server, args []string, targetIndex int) []string {
if targetIndex < 0 {
return args
}
if len(args) < targetIndex+1 || !strings.HasPrefix(args[targetIndex], "#") {
win := srv.windows.Active()
t := ""
if win != nil && win.Title() != "status" {
t = win.Title()
}
args = append(append([]string{}, args[targetIndex-1], t), args[targetIndex:]...)
}
return args
}
func joinChannel(srv *Server, args []string) {
if len(args) < 2 {
logrus.Warnln("join: expected one argument")
args = guessTargetInArgs(srv, args, 1)
target := args[1]
if len(target) > 0 && target[0] != '#' {
logrus.Warnln("join: unable to determine current channel")
return
}
srv.IRCDoAsync(func(conn *irc.Connection) error {
conn.Join(args[1])
conn.Join(target)
return nil
})
}
func partChannel(srv *Server, args []string) {
if len(args) < 2 {
logrus.Warnln("part: expected one argument")
args = guessTargetInArgs(srv, args, 1)
target := args[1]
if len(target) > 0 && target[0] != '#' {
logrus.Warnln("part: unable to determine current channel")
return
}
srv.IRCDoAsync(func(conn *irc.Connection) error {
conn.Part(target)
return nil
})
}
func inviteTarget(srv *Server, args []string) {
args = guessTargetInArgs(srv, args, 1)
target := args[1]
if len(target) > 0 && target[0] != '#' {
logrus.Warnln("invite: unable to determine current channel")
return
}
nick := args[2]
srv.IRCDoAsync(func(conn *irc.Connection) error {
conn.Part(args[1])
conn.SendRawf("INVITE %s :%s", nick, target)
return nil
})
}
@ -313,14 +379,15 @@ func whoisNick(srv *Server, args []string) {
}
func namesChannel(srv *Server, args []string) {
if len(args) < 2 {
logrus.Warnln("names: expected one argument")
args = guessTargetInArgs(srv, args, 1)
target := args[1]
if len(target) > 0 && target[0] != '#' {
logrus.Warnln("names: unable to determine current channel")
return
}
channel := args[1]
win := srv.wm.Named(channel)
win := srv.windows.Named(target)
if win == nil {
logrus.Warnln("names: no window named", channel)
logrus.Warnln("names: no window named", target)
return
}
irc353Handler := event.HandlerFunc(func(ev *event.Event) {
@ -340,7 +407,7 @@ func namesChannel(srv *Server, args []string) {
srv.events.Bind("irc.353", irc353Handler)
srv.events.Bind("irc.366", irc366Handler)
srv.IRCDoAsync(func(conn *irc.Connection) error {
conn.SendRawf("NAMES :%s", channel)
conn.SendRawf("NAMES :%s", target)
return nil
})
}
@ -358,7 +425,7 @@ func changeNick(srv *Server, args []string) {
func actionTarget(srv *Server, args []string) {
message := strings.Join(args[1:], " ")
window := srv.wm.Active()
window := srv.windows.Active()
if window == nil || window.Title() == "status" {
return
}
@ -384,21 +451,21 @@ func msgTarget(srv *Server, args []string) {
conn.Privmsg(target, message)
return nil
})
window := srv.wm.Named(target)
window := srv.windows.Named(target)
if !strings.HasPrefix(target, "#") {
// direct message!
if window == nil {
dm := &DirectMessage{
newBufferedWindow(target, srv.events),
}
srv.wm.Append(dm)
srv.windows.Append(dm)
window = dm
}
}
myNick := MyNick(srv.CurrentNick())
if window == nil {
// no window for this but we might still have sent the message, so write it to the status window
window = srv.wm.Index(0)
window = srv.windows.Index(0)
message = target + " -> " + message
}
WritePrivmsg(window, myNick, MyMessage(message))
@ -418,10 +485,10 @@ func noticeTarget(srv *Server, args []string) {
conn.Notice(target, message)
return nil
})
window := srv.wm.Named(target)
window := srv.windows.Named(target)
if window == nil {
// no window for this but we might still have sent the message, so write it to the status window
window = srv.wm.Index(0)
window = srv.windows.Index(0)
}
WriteNotice(window, SomeTarget(target, srv.CurrentNick()), true, message)
}
@ -440,10 +507,10 @@ func ctcpTarget(srv *Server, args []string) {
conn.SendRawf("PRIVMSG %s :\x01%s\x01", target, message)
return nil
})
window := srv.wm.Named(target)
window := srv.windows.Named(target)
if window == nil {
// no window for this but we might still have sent the message, so write it to the status window
window = srv.wm.Index(0)
window = srv.windows.Index(0)
}
WriteCTCP(window, SomeTarget(target, srv.CurrentNick()), true, message)
}

@ -0,0 +1,19 @@
{
"name": "squirssi-scripts",
"version": "0.0.1",
"license": "MIT",
"private": true,
"dependencies": {
"@babel/standalone": "7.5.5",
"assert": "2.0.0",
"assert-polyfill": "0.0.0",
"buffer": "5.2.1",
"core-js-bundle": "3.1.4",
"process": "0.11.10",
"regenerator-runtime": "0.13.3",
"regenerator-transform": "0.14.1"
},
"resolutions": {
"util": "0.12.1"
}
}

@ -0,0 +1,21 @@
// +build linked_plugins
package main
import (
"code.dopame.me/veonik/squircy3/plugin"
"code.dopame.me/veonik/squirssi"
babel "code.dopame.me/veonik/squircy3/plugins/babel"
node_compat "code.dopame.me/veonik/squircy3/plugins/node_compat"
script "code.dopame.me/veonik/squircy3/plugins/script"
squircy2_compat "code.dopame.me/veonik/squircy3/plugins/squircy2_compat"
)
var linkedPlugins = []plugin.Initializer{
plugin.InitializerFunc(babel.Initialize),
plugin.InitializerFunc(node_compat.Initialize),
plugin.InitializerFunc(script.Initialize),
plugin.InitializerFunc(squircy2_compat.Initialize),
plugin.InitializerFunc(squirssi.Initialize)}

@ -3,52 +3,65 @@ package main
import (
"flag"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sort"
"strings"
"code.dopame.me/veonik/squircy3/cli"
"code.dopame.me/veonik/squircy3/plugin"
"github.com/gobuffalo/packr/v2"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
tilde "gopkg.in/mattes/go-expand-tilde.v1"
_ "gopkg.in/mattes/go-expand-tilde.v1"
"code.dopame.me/veonik/squircy3/cli"
"code.dopame.me/veonik/squircy3/irc"
"code.dopame.me/veonik/squircy3/plugin"
"code.dopame.me/veonik/squirssi"
)
type stringsFlag []string
var SquirssiVersion = "SNAPSHOT"
var Squircy3Version = "SNAPSHOT"
func (s stringsFlag) String() string {
return strings.Join(s, "")
}
func (s *stringsFlag) Set(str string) error {
*s = append(*s, str)
return nil
type Manager struct {
*cli.Manager
}
type stringLevel logrus.Level
func (s stringLevel) String() string {
return logrus.Level(s).String()
}
func (s *stringLevel) Set(str string) error {
l, err := logrus.ParseLevel(str)
func (m *Manager) Start() (err error) {
if err := m.Manager.Start(); err != nil {
return err
}
logrus.Infof("Starting squirssi (version %s, built with squircy3-%s)", SquirssiVersion, Squircy3Version)
plugins := m.Plugins()
printPluginsLoaded(plugins)
ircp, err := irc.FromPlugins(plugins)
if err != nil {
return err
}
*s = stringLevel(l)
return nil
ircp.SetVersionString(fmt.Sprintf("squirssi %s", SquirssiVersion))
srv, err := squirssi.FromPlugins(plugins)
if err != nil {
return err
}
srv.OnInterrupt(m.Stop)
return srv.Start()
}
var rootDir string
var extraPlugins stringsFlag
var logLevel = stringLevel(logrus.InfoLevel)
var Squircy3Version = "SNAPSHOT"
func NewManager() (*Manager, error) {
cm, err := cli.NewManager()
if err != nil {
return nil, err
}
cm.LinkedPlugins = append(cm.LinkedPlugins, linkedPlugins...)
return &Manager{cm}, nil
}
func init() {
flag.StringVar(&rootDir, "root", "~/.squirssi", "path to folder containing squirssi data")
flag.Var(&logLevel, "log-level", "controls verbosity of logging output")
flag.Var(&extraPlugins, "plugin", "path to shared plugin .so file, multiple plugins may be given")
printVersion := false
cli.CoreFlags(flag.CommandLine, "~/.squirssi")
cli.IRCFlags(flag.CommandLine)
cli.VMFlags(flag.CommandLine)
flag.BoolVar(&printVersion, "version", false, "print version information")
flag.Usage = func() {
fmt.Println("Usage: ", os.Args[0], "[options]")
@ -59,15 +72,11 @@ func init() {
flag.PrintDefaults()
}
flag.Parse()
bp, err := tilde.Expand(rootDir)
if err != nil {
logrus.Fatalln(err)
}
err = os.MkdirAll(bp, 0644)
if err != nil {
logrus.Fatalln(err)
if printVersion {
fmt.Printf("squirssi (version %s, built with squircy3-%s)\n", SquirssiVersion, Squircy3Version)
os.Exit(0)
}
rootDir = bp
}
func printPluginsLoaded(plugins *plugin.Manager) {
@ -76,44 +85,55 @@ func printPluginsLoaded(plugins *plugin.Manager) {
logrus.Infoln("Loaded plugins:", strings.Join(pls, ", "))
}
type Manager struct {
*cli.Manager
}
func (m *Manager) Start() (err error) {
if err := m.Manager.Start(); err != nil {
return err
func unboxAll(rootDir string) (modified bool, err error) {
if _, err = os.Stat(filepath.Join(rootDir, "config.toml")); err == nil {
// root directory already exists, don't muck with it
return false, nil
}
logrus.Infof("Starting squirssi (version %s, built with squircy3-%s)", squirssi.Version, Squircy3Version)
plugins := m.Plugins()
printPluginsLoaded(plugins)
srv, err := squirssi.FromPlugins(plugins)
if err != nil {
return err
if err = os.MkdirAll(rootDir, 0755); err != nil {
return false, errors.Wrap(err, "failed to create root directory")
}
srv.OnInterrupt(m.Stop)
return srv.Start()
}
func NewManager(rootDir string, extraPlugins ...string) (*Manager, error) {
cm, err := cli.NewManager(rootDir, extraPlugins...)
if err != nil {
return nil, err
box := packr.New("defconf", "./defconf")
for _, f := range box.List() {
dst := filepath.Join(rootDir, f)
if _, err := os.Stat(dst); os.IsNotExist(err) {
if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
return true, errors.Wrap(err, "failed to recreate directory")
}
logrus.Infof("Creating default %s", dst)
d, err := box.Find(f)
if err != nil {
return true, errors.Wrapf(err, "failed to get contents of boxed %s", f)
}
if err := ioutil.WriteFile(dst, d, 0644); err != nil {
return true, errors.Wrapf(err, "failed to write unboxed file %s", f)
}
}
}
cm.LinkedPlugins = append(cm.LinkedPlugins, plugin.InitializerFunc(squirssi.Initialize))
return &Manager{cm}, nil
return true, nil
}
func main() {
logrus.SetLevel(logrus.Level(logLevel))
m, err := NewManager(rootDir, extraPlugins...)
logrus.SetLevel(logrus.InfoLevel)
m, err := NewManager()
if err != nil {
logrus.Fatalln("error initializing squirssi:", err)
logrus.Fatalln("core: error initializing squirssi:", err)
}
logrus.SetLevel(m.LogLevel)
if modified, err := unboxAll(m.RootDir); err != nil {
logrus.Fatalln("core: failed to unbox defaults:", err)
} else if modified {
// re-initialize the manager so that plugins load
m, err = NewManager()
if err != nil {
logrus.Fatalln("core: error initializing squirssi:", err)
}
logrus.SetLevel(m.LogLevel)
}
if err := m.Start(); err != nil {
logrus.Fatalln("error starting squirssi:", err)
logrus.Fatalln("core: error starting squirssi:", err)
}
if err = m.Loop(); err != nil {
logrus.Fatalln("exiting main loop with error:", err)
logrus.Fatalln("core: exiting main loop with error:", err)
}
}

@ -0,0 +1,12 @@
// +build !linked_plugins
package main
import (
"code.dopame.me/veonik/squircy3/plugin"
"code.dopame.me/veonik/squirssi"
)
var linkedPlugins = []plugin.Initializer{
plugin.InitializerFunc(squirssi.Initialize)}

@ -31,7 +31,7 @@ const (
var ircToUIMap = map[IRC]ui.Color{
IRCWhite: White,
IRCBlack: Black,
IRCBlack: Grey53,
IRCBlue: Blue,
IRCGreen: Green,
IRCRed: Red,

@ -3,14 +3,14 @@ module code.dopame.me/veonik/squirssi
go 1.14
require (
code.dopame.me/veonik/squircy3 v0.9.0
code.dopame.me/veonik/squircy3 v0.11.2
github.com/gizak/termui/v3 v3.1.0
github.com/mattn/go-runewidth v0.0.9
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d
github.com/gobuffalo/packr/v2 v2.8.1
github.com/mattn/go-runewidth v0.0.13
github.com/mitchellh/go-wordwrap v1.0.1
github.com/nsf/termbox-go v1.1.1
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.6.0
github.com/thoj/go-ircevent v0.0.0-20190807115034-8e7ce4b5a1eb
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff // indirect
github.com/sirupsen/logrus v1.8.1
github.com/thoj/go-ircevent v0.0.0-20210419090348-35410aa86c49
gopkg.in/mattes/go-expand-tilde.v1 v1.0.0-20150330173918-cb884138e64c
)

229
go.sum

@ -1,67 +1,226 @@
code.dopame.me/veonik/squircy3 v0.9.0 h1:Ggtq0TaIhkW0N+XcfA+7YaQ4E0B0RemkjsK2mBCob80=
code.dopame.me/veonik/squircy3 v0.9.0/go.mod h1:D0PZ58ANI0zuFIgCLrhmBSZQmLeKFd0vL+6YP2AamYc=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
code.dopame.me/veonik/squircy3 v0.11.2 h1:f0Z0g4eE8b+pKpCLYJZhbcCVt2CL8PDKzkrBnhnXWSM=
code.dopame.me/veonik/squircy3 v0.11.2/go.mod h1:9LRZ7a6BfN37K0n12U7S11xmEJyQOnr1is4/PpyWYPI=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dop251/goja v0.0.0-20200526165454-f1752421c432 h1:EIY1hqp9O08saJ41t7aQy0o1hhq3ByOy61AACthST5M=
github.com/dop251/goja v0.0.0-20200526165454-f1752421c432/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
github.com/fatih/structtag v1.0.0 h1:pTHj65+u3RKWYPSGaU290FpI/dXxTaHdVwVwbcPKmEc=
github.com/fatih/structtag v1.0.0/go.mod h1:IKitwq45uXL/yqi5mYghiD3w9H6eTOvI9vnk8tXMphA=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 h1:Izz0+t1Z5nI16/II7vuEo/nHjodOg0p7+OiDpjX5t1E=
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dop251/goja v0.0.0-20210630164231-8f81471d5d0b h1:rnfefjbv6blIje+eurnj8yffNiNAeuF5XbplLwgYNxk=
github.com/dop251/goja v0.0.0-20210630164231-8f81471d5d0b/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gizak/termui/v3 v3.1.0 h1:ZZmVDgwHl7gR7elfKf1xc4IudXZ5qqfDh4wExk4Iajc=
github.com/gizak/termui/v3 v3.1.0/go.mod h1:bXQEBkJpzxUAKf0+xq9MSWAvWZlE7c+aidmyFlkYTrY=
github.com/go-sourcemap/sourcemap v2.1.2+incompatible h1:0b/xya7BKGhXuqFESKM4oIiRo9WOt2ebz7KxfreD6ug=
github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobuffalo/logger v1.0.3/go.mod h1:SoeejUwldiS7ZsyCBphOGURmWdwUFXs0J7TCjEhjKxM=
github.com/gobuffalo/logger v1.0.4 h1:HFJRqL7AmL4QNvQb9Grss9sDz+3u02VBgAoR03A7q4o=
github.com/gobuffalo/logger v1.0.4/go.mod h1:/GRUdWb+gM3shxj0P5jiV6ecVS3X0aboJvl+hBu0HeE=
github.com/gobuffalo/packd v1.0.0 h1:6ERZvJHfe24rfFmA9OaoKBdC7+c9sydrytMg8SdFGBM=
github.com/gobuffalo/packd v1.0.0/go.mod h1:6VTc4htmJRFB7u1m/4LeMTWjFoYrUiBkU9Fdec9hrhI=
github.com/gobuffalo/packr/v2 v2.8.1 h1:tkQpju6i3EtMXJ9uoF5GT6kB+LMTimDWD8Xvbz6zDVA=
github.com/gobuffalo/packr/v2 v2.8.1/go.mod h1:c/PLlOuTU+p3SybaJATW3H6lX/iK7xEz5OeMf+NnJpg=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/karrick/godirwalk v1.15.8/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw=
github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI=
github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc=
github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY=
github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI=
github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d h1:x3S6kxmy49zXVVyhcnrFqxvNVCBPb2KZ9hV2RBdS840=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
github.com/peterh/liner v1.1.0 h1:f+aAedNJA6uk7+6rXsYBnhdo4Xux7ESLe+kcuVUF5os=
github.com/peterh/liner v1.1.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/nsf/termbox-go v1.1.1 h1:nksUPLCb73Q++DwbYUBEglYBRPZyoXJdrj5L+TkjyZY=
github.com/nsf/termbox-go v1.1.1/go.mod h1:T0cTdVuOwf7pHQNtfhnEbzHbcNyCEcVU4YPpouCbVxo=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterh/liner v1.2.1/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.5.2 h1:qLvObTrvO/XRCqmkKxUlOBc48bI3efyDuAZe25QiF0w=
github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/thoj/go-ircevent v0.0.0-20190807115034-8e7ce4b5a1eb h1:EavwSqheIJl3nb91HhkL73DwnT2Fk8W3yM7T7TuLZvA=
github.com/thoj/go-ircevent v0.0.0-20190807115034-8e7ce4b5a1eb/go.mod h1:I0ZT9x8wStY6VOxtNOrLpnDURFs7HS0z1e1vhuKUEVc=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/thoj/go-ircevent v0.0.0-20210419090348-35410aa86c49 h1:yi0zALyFXLtL91w/IvB2U/ZsnesbncMvD+0jDE9vQLw=
github.com/thoj/go-ircevent v0.0.0-20210419090348-35410aa86c49/go.mod h1:I0ZT9x8wStY6VOxtNOrLpnDURFs7HS0z1e1vhuKUEVc=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/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-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190913121621-c3b328c6e5a7 h1:wYqz/tQaWUgGKyx+B/rssSE6wkIKdY5Ee6ryOmzarIg=
golang.org/x/sys v0.0.0-20190913121621-c3b328c6e5a7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff h1:1CPUrky56AcgSpxz/KfgzQWzfG09u5YOL8MvPYBlrL8=
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/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-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200308013534-11ec41452d41/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/mattes/go-expand-tilde.v1 v1.0.0-20150330173918-cb884138e64c h1:/Onz8dZtKBCmB8P0JU7+WSCfMekXry7BflVO0SQQrCU=
gopkg.in/mattes/go-expand-tilde.v1 v1.0.0-20150330173918-cb884138e64c/go.mod h1:j6QavCO5cYWud1+2/PFTXL1y6tjjkhSs+qcWgibOIc0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

@ -1,7 +1,6 @@
package squirssi
import (
"math"
"strings"
"code.dopame.me/veonik/squircy3/event"
@ -37,28 +36,51 @@ func onUIKeyPress(srv *Server, key string) {
}
switch key {
case "<C-c>":
srv.inputTextBox.Append(string(0x03))
srv.inputTextBox.Append(string(rune(0x03)))
srv.RenderOnly(InputTextBox)
case "<C-u>":
srv.inputTextBox.Append(string(0x1F))
srv.inputTextBox.Append(string(rune(0x1F)))
srv.RenderOnly(InputTextBox)
case "<C-b>":
srv.inputTextBox.Append(string(0x02))
srv.inputTextBox.Append(string(rune(0x02)))
srv.RenderOnly(InputTextBox)
case "<M-b>":
srv.inputTextBox.CursorPrevWord()
srv.RenderOnly(InputTextBox)
case "<M-f>":
srv.inputTextBox.CursorNextWord()
srv.RenderOnly(InputTextBox)
case "<Home>":
srv.inputTextBox.CursorStartLine()
srv.RenderOnly(InputTextBox)
case "<End>":
srv.inputTextBox.CursorEndLine()
srv.RenderOnly(InputTextBox)
case "<PageUp>":
srv.mu.RLock()
h := srv.pageHeight - 2
h := srv.pageSize - 2
srv.mu.RUnlock()
srv.wm.ScrollOffset(-h)
srv.windows.ScrollOffset(-h)
case "<PageDown>":
srv.mu.RLock()
h := srv.pageHeight - 2
h := srv.pageSize - 2
srv.mu.RUnlock()
srv.wm.ScrollOffset(h)
case "<Home>":
srv.wm.ScrollTo(0)
case "<End>":
srv.wm.ScrollTo(math.MaxInt32)
srv.windows.ScrollOffset(h)
case "<M-<PageUp>>":
srv.mu.Lock()
h := srv.pageSize - 2
srv.userListPane.SelectedRow -= h
srv.mu.Unlock()
srv.events.Emit("ui.DIRTY", nil)
case "<M-<PageDown>>":
srv.mu.Lock()
h := srv.pageSize - 2
if srv.userListPane.SelectedRow == 0 {
srv.userListPane.SelectedRow = h
}
srv.userListPane.SelectedRow += h
srv.mu.Unlock()
srv.events.Emit("ui.DIRTY", nil)
case "<Space>":
srv.inputTextBox.Append(" ")
srv.RenderOnly(InputTextBox)
@ -69,11 +91,11 @@ func onUIKeyPress(srv *Server, key string) {
srv.inputTextBox.DeleteNext()
srv.RenderOnly(InputTextBox)
case "<C-5>":
srv.wm.SelectNext()
srv.windows.SelectNext()
case "<Escape>":
srv.wm.SelectPrev()
srv.windows.SelectPrev()
case "<Up>":
win := srv.wm.Active()
win := srv.windows.Active()
if win == nil {
return
}
@ -85,7 +107,7 @@ func onUIKeyPress(srv *Server, key string) {
srv.inputTextBox.Set(msg)
srv.RenderOnly(InputTextBox)
case "<Down>":
win := srv.wm.Active()
win := srv.windows.Active()
if win == nil {
return
}
@ -103,7 +125,7 @@ func onUIKeyPress(srv *Server, key string) {
srv.inputTextBox.CursorNext()
srv.RenderOnly(InputTextBox)
case "<Tab>":
win := srv.wm.Active()
win := srv.windows.Active()
if ch, ok := win.(*Channel); ok {
var tabbed string
if srv.tabber.Active() {
@ -116,8 +138,8 @@ func onUIKeyPress(srv *Server, key string) {
srv.RenderOnly(InputTextBox)
case "<Enter>":
in := srv.inputTextBox.Consume()
active := srv.wm.ActiveIndex()
channel := srv.wm.Active()
active := srv.windows.ActiveIndex()
channel := srv.windows.Active()
if channel == nil {
return
}
@ -150,7 +172,7 @@ func onUIKeyPress(srv *Server, key string) {
logrus.Debugln("received unhandled keypress:", key)
return
}
if key == "/" && srv.inputTextBox.Len() == 0 {
if key == "/" && srv.inputTextBox.Pos() == 0 {
srv.inputTextBox.ToggleMode()
} else {
srv.inputTextBox.Append(key)

@ -106,6 +106,7 @@ var debugIgnore = map[string]struct{}{
"366": {},
"353": {},
"324": {},
"329": {},
"331": {},
"332": {},
"001": {},
@ -119,6 +120,13 @@ var debugIgnore = map[string]struct{}{
"250": {},
"265": {},
"266": {},
"311": {},
"312": {},
"313": {},
"317": {},
"318": {},
"319": {},
"369": {},
"375": {},
"372": {},
"376": {},
@ -161,29 +169,17 @@ func HandleIRCEvent(srv *Server, h IRCEventHandler) event.Handler {
func onIRC324(srv *Server, ev *IRCEvent) {
modes := strings.Join(ev.Args[2:], " ")
win := srv.wm.Named(ev.Args[1])
blankBefore := false
win := srv.windows.Named(ev.Args[1])
if ch, ok := win.(*Channel); ok {
ch.mu.Lock()
if ch.modes == "" {
blankBefore = true
}
ch.modes = modes
ch.mu.Unlock()
}
if win == nil {
logrus.Warnln("received MODES for something without a window:", ev.Args[1], ev.Args[2:])
return
}
// dont write the message the first time we get modes since that is done automatically on join
if !blankBefore {
WriteModes(win, modes)
}
}
func onIRC331(srv *Server, ev *IRCEvent) {
target := ev.Args[1]
win := srv.wm.Named(target)
win := srv.windows.Named(target)
if ch, ok := win.(*Channel); ok {
ch.mu.Lock()
ch.topic = ""
@ -194,7 +190,7 @@ func onIRC331(srv *Server, ev *IRCEvent) {
func onIRC332(srv *Server, ev *IRCEvent) {
target := ev.Args[1]
win := srv.wm.Named(target)
win := srv.windows.Named(target)
if ch, ok := win.(*Channel); ok {
topic := strings.Join(ev.Args[2:], " ")
ch.mu.Lock()
@ -231,11 +227,16 @@ func onIRCMode(srv *Server, ev *IRCEvent) {
} else if target == currNick {
nick = MyNick(target)
}
win := srv.wm.Named(target)
win := srv.windows.Named(target)
if win != nil {
WriteMode(win, nick, mode)
onIRCNames(srv, ev)
srv.IRCDoAsync(func(conn *irc.Connection) error {
conn.Mode(target)
return nil
})
} else {
WriteMode(srv.wm.Index(0), nick, mode)
WriteMode(srv.windows.Index(0), nick, mode)
}
}
@ -246,7 +247,7 @@ func onIRCTopic(srv *Server, ev *IRCEvent) {
if ev.Nick == srv.CurrentNick() {
nick.me = true
}
win := srv.wm.Named(target)
win := srv.windows.Named(target)
if win != nil {
WriteTopic(win, nick, topic)
} else {
@ -269,15 +270,20 @@ func onIRCNick(srv *Server, ev *IRCEvent) {
newNick.me = true
srv.setCurrentNick(newNick.string)
}
WriteNick(srv.wm, nick, newNick)
WriteNick(srv.windows, nick, newNick)
}
func onIRCKick(srv *Server, ev *IRCEvent) {
channel := ev.Target
kicker := SomeNick(ev.Nick)
kicked := SomeNick(ev.Args[1])
if kicked.string == srv.CurrentNick() {
myNick := srv.CurrentNick()
if kicked.string == myNick {
kicked.me = true
}
if kicker.string == myNick {
kicker.me = true
}
if kicked.me {
go func() {
<-time.After(2 * time.Second)
@ -289,7 +295,7 @@ func onIRCKick(srv *Server, ev *IRCEvent) {
}
}()
}
win := srv.wm.Named(channel)
win := srv.windows.Named(channel)
if win == nil {
logrus.Errorln("received kick with no Window:", channel, ev.Message, ev.Nick)
return
@ -297,7 +303,7 @@ func onIRCKick(srv *Server, ev *IRCEvent) {
if ch, ok := win.(*Channel); ok {
ch.DeleteUser(kicked.string)
}
WriteKick(win, kicked, ev.Message)
WriteKick(win, kicker, kicked, ev.Message)
}
var namesCache = &struct {
@ -309,7 +315,7 @@ func onIRC353(srv *Server, ev *IRCEvent) {
// NAMES
chanName := ev.Args[2]
nicks := strings.Split(ev.Args[3