Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b249a495a4 | ||
|
|
f4d324da9b | ||
|
|
fff73cfe44 | ||
|
|
31885d76f0 | ||
|
|
fec21a0045 | ||
|
|
d721112738 | ||
|
|
dd51f7fd59 | ||
|
|
42e6ca8f26 | ||
|
|
304c645043 | ||
|
|
31fd9f9a56 | ||
|
|
e68503c72e | ||
|
|
32b5649465 |
+75
-18
@@ -1,21 +1,78 @@
|
||||
workspace:
|
||||
base: /go
|
||||
path: src/git.aiterp.net/rpdata/logbot3
|
||||
name: logbot3
|
||||
|
||||
pipeline:
|
||||
docker-release:
|
||||
image: plugins/docker
|
||||
repo: vmaple/rpdata-logbot3
|
||||
auto_tag: true
|
||||
secrets: [ docker_username, docker_password ]
|
||||
kind: pipeline
|
||||
type: docker
|
||||
|
||||
steps:
|
||||
- name: go-build-1.11
|
||||
image: golang:1.11
|
||||
commands:
|
||||
- go mod download
|
||||
- CGO_ENABLED=0 go build -ldflags "-w -s" .
|
||||
when:
|
||||
event: tag
|
||||
ref: refs/tags/*
|
||||
docker-release-latest:
|
||||
image: plugins/docker
|
||||
repo: vmaple/rpdata-logbot3
|
||||
tags: latest
|
||||
secrets: [ docker_username, docker_password ]
|
||||
event:
|
||||
exclude:
|
||||
- tag
|
||||
|
||||
- name: go-build-1.12
|
||||
image: golang:1.12
|
||||
commands:
|
||||
- go mod download
|
||||
- CGO_ENABLED=0 go build -ldflags "-w -s" .
|
||||
when:
|
||||
event: tag
|
||||
ref: refs/tags/*
|
||||
event:
|
||||
exclude:
|
||||
- tag
|
||||
|
||||
- name: go-build-1.13
|
||||
image: golang:1.13
|
||||
commands:
|
||||
- go mod download
|
||||
- CGO_ENABLED=0 go build -ldflags "-w -s" .
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- tag
|
||||
|
||||
- name: go-build-1.14
|
||||
image: golang:1.14
|
||||
commands:
|
||||
- go mod download
|
||||
- CGO_ENABLED=0 go build -ldflags "-w -s" .
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- tag
|
||||
|
||||
- name: go-test
|
||||
image: golang:1.14
|
||||
commands:
|
||||
- go test -v ./...
|
||||
|
||||
- name: docker-release-tag
|
||||
image: plugins/docker
|
||||
settings:
|
||||
auto_tag: true
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
repo: r.vmaple.dev/rpdata/logbot3
|
||||
registry: r.vmaple.dev
|
||||
when:
|
||||
event:
|
||||
- tag
|
||||
|
||||
- name: docker-release-latest
|
||||
image: plugins/docker
|
||||
settings:
|
||||
auto_tag: false
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
repo: r.vmaple.dev/rpdata/logbot3
|
||||
registry: r.vmaple.dev
|
||||
when:
|
||||
event:
|
||||
- tag
|
||||
+3
-1
@@ -3,4 +3,6 @@ debug
|
||||
debug.exe
|
||||
logbot3
|
||||
logbot3.exe
|
||||
vendor/
|
||||
|
||||
# Idea
|
||||
/.idea
|
||||
|
||||
+7
-9
@@ -1,29 +1,27 @@
|
||||
## 1. Build Server
|
||||
# Use Go 1.11
|
||||
FROM golang:1.11 AS build
|
||||
# Use Go 1.14
|
||||
FROM golang:1.14 AS build
|
||||
|
||||
# Load repository into docker
|
||||
WORKDIR /go/src/git.aiterp.net/rpdata/logbot3/
|
||||
WORKDIR /project
|
||||
COPY . .
|
||||
RUN rm -rf ./vendor
|
||||
|
||||
# Load and run dependencies
|
||||
RUN go get -u github.com/golang/dep/cmd/dep
|
||||
RUN dep ensure
|
||||
RUN go get
|
||||
|
||||
# Build server and tools (CGO disabled to make them 100% static)
|
||||
ENV CGO_ENABLED 0
|
||||
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o /binaries/logbot3 .
|
||||
RUN go build -a -installsuffix cgo -ldflags="-s -w" -o logbot3 .
|
||||
|
||||
## 2. Distribute
|
||||
# Use alpine linux
|
||||
FROM alpine:3.8 as main-dist
|
||||
FROM alpine:3.12 as main-dist
|
||||
|
||||
# Install certificates to enable HTTPS GET requests
|
||||
RUN apk add --no-cache ca-certificates
|
||||
|
||||
# Copy build files into final container
|
||||
COPY --from=build /binaries/* /usr/local/bin/
|
||||
COPY --from=build /project/logbot3 /usr/local/bin/
|
||||
|
||||
# The server is the main entry point
|
||||
CMD ["/usr/local/bin/logbot3"]
|
||||
|
||||
Generated
-26
@@ -1,26 +0,0 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "git.aiterp.net/gisle/irc"
|
||||
packages = [
|
||||
".",
|
||||
"ircutil",
|
||||
"isupport",
|
||||
"list"
|
||||
]
|
||||
revision = "2dd72f9838d99e084c85de0d8fce290bcc547cbe"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/dgrijalva/jwt-go"
|
||||
packages = ["."]
|
||||
revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
|
||||
version = "v3.2.0"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "7ef4c9d0736b7eb8e596036446cae5d12a8d7485db1559cfa8ade7ba1bf74263"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
#
|
||||
# [prune]
|
||||
# non-go = false
|
||||
# go-tests = true
|
||||
# unused-packages = true
|
||||
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "git.aiterp.net/gisle/irc"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/dgrijalva/jwt-go"
|
||||
version = "3.2.0"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
@@ -0,0 +1,8 @@
|
||||
module git.aiterp.net/rpdata/logbot3
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/gissleh/irc v0.0.0-20200720173331-512ba5aa6fca
|
||||
)
|
||||
@@ -0,0 +1,4 @@
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/gissleh/irc v0.0.0-20200720173331-512ba5aa6fca h1:vTL3kM7PkVnTy77i2/ewaC0VDmSEF7sAOMDTNIs6rKY=
|
||||
github.com/gissleh/irc v0.0.0-20200720173331-512ba5aa6fca/go.mod h1:h2/fPlbnb11gFpitk0HGxYLgK+bCKGh55QSYNo36X8M=
|
||||
+29
-5
@@ -3,9 +3,10 @@ package bot
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.aiterp.net/gisle/irc"
|
||||
"github.com/gissleh/irc"
|
||||
"git.aiterp.net/rpdata/logbot3/internal/models"
|
||||
"git.aiterp.net/rpdata/logbot3/internal/models/channels"
|
||||
)
|
||||
@@ -33,6 +34,8 @@ func New(ctx context.Context, nick string, alternatives []string, user string, r
|
||||
SkipSSLVerification: false,
|
||||
})
|
||||
|
||||
client.AddHandler(handler)
|
||||
|
||||
bot := &Bot{
|
||||
client: client,
|
||||
channels: make(map[string]*Channel),
|
||||
@@ -73,12 +76,16 @@ func (bot *Bot) Connect(server string, ssl bool, maxRetries int) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (bot *Bot) ClientState() irc.ClientState {
|
||||
return bot.client.State()
|
||||
}
|
||||
|
||||
func (bot *Bot) addChannel(channelName string) *Channel {
|
||||
if bot.channels[channelName] != nil {
|
||||
return bot.channels[channelName]
|
||||
}
|
||||
|
||||
channel := newChannel(bot.ctx, channelName, bot.client)
|
||||
channel := newChannel(bot, channelName, bot.client)
|
||||
go channel.loop()
|
||||
|
||||
bot.channels[channelName] = channel
|
||||
@@ -93,6 +100,21 @@ func (bot *Bot) handlePost(channelName string, post ChannelPost) {
|
||||
channel.ch <- post
|
||||
}
|
||||
|
||||
func (bot *Bot) runCommands(commands []string, target irc.Target, replacers map[string]string) {
|
||||
if replacers == nil {
|
||||
replacers = make(map[string]string)
|
||||
}
|
||||
replacers["me"] = bot.client.Nick()
|
||||
|
||||
for _, command := range commands {
|
||||
for from, to := range replacers {
|
||||
command = strings.Replace(command, "%"+from, to, -1)
|
||||
}
|
||||
|
||||
bot.client.EmitInput(command, target)
|
||||
}
|
||||
}
|
||||
|
||||
func (bot *Bot) loop() {
|
||||
bot.loopCtx, bot.loopCancel = context.WithCancel(bot.ctx)
|
||||
|
||||
@@ -138,12 +160,14 @@ func (bot *Bot) loop() {
|
||||
}
|
||||
}
|
||||
|
||||
if len(joins) > 0 {
|
||||
bot.client.Join(joins...)
|
||||
}
|
||||
if len(parts) > 0 {
|
||||
log.Println("Leaving", strings.Join(parts, ", "))
|
||||
bot.client.Part(parts...)
|
||||
}
|
||||
if len(joins) > 0 {
|
||||
log.Println("Joining", strings.Join(joins, ", "))
|
||||
bot.client.Join(joins...)
|
||||
}
|
||||
}
|
||||
|
||||
case <-bot.loopCtx.Done():
|
||||
|
||||
+46
-5
@@ -6,7 +6,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.aiterp.net/gisle/irc"
|
||||
"github.com/gissleh/irc"
|
||||
"git.aiterp.net/rpdata/logbot3/internal/config"
|
||||
"git.aiterp.net/rpdata/logbot3/internal/models/channels"
|
||||
"git.aiterp.net/rpdata/logbot3/internal/models/logs"
|
||||
"git.aiterp.net/rpdata/logbot3/internal/models/posts"
|
||||
@@ -23,15 +24,17 @@ type Channel struct {
|
||||
|
||||
name string
|
||||
parentCtx context.Context
|
||||
parent *Bot
|
||||
client *irc.Client
|
||||
}
|
||||
|
||||
func newChannel(parentCtx context.Context, name string, client *irc.Client) *Channel {
|
||||
func newChannel(parent *Bot, name string, client *irc.Client) *Channel {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
return &Channel{
|
||||
name: name,
|
||||
parentCtx: parentCtx,
|
||||
parent: parent,
|
||||
parentCtx: parent.ctx,
|
||||
client: client,
|
||||
ch: make(chan ChannelPost, 8),
|
||||
|
||||
@@ -47,6 +50,7 @@ func (channel *Channel) loop() {
|
||||
defer channel.cancel()
|
||||
defer minutely.Stop()
|
||||
|
||||
// In case of a crash, it should take ownership of sessions when rejoining.
|
||||
session, err := logs.FindOpen(channel.parentCtx, channel.name)
|
||||
if err == nil {
|
||||
minsUntilDeadline := 1 + int(((time.Hour * 2) - time.Since(session.LatestTime())).Minutes())
|
||||
@@ -60,12 +64,27 @@ func (channel *Channel) loop() {
|
||||
channel.lastPostTime = session.LatestTime()
|
||||
}
|
||||
|
||||
// If the bot is op, run the commands from the configuration.
|
||||
go func() {
|
||||
time.Sleep(time.Second)
|
||||
|
||||
commands := config.Get().Commands.OnJoinOp
|
||||
target := channel.client.Channel(channel.name)
|
||||
|
||||
if len(commands) > 0 && target != nil {
|
||||
me, ok := target.UserList().User(channel.client.Nick())
|
||||
if ok && strings.ContainsRune(me.Modes, 'o') {
|
||||
channel.parent.runCommands(commands, target, map[string]string{
|
||||
"chan": channel.name,
|
||||
})
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case post := <-channel.ch:
|
||||
{
|
||||
log.Printf("Received %s post from %s", post.Kind, post.Nick)
|
||||
|
||||
// Handle bot commands, or add to queue otherwise.
|
||||
if cmd := post.botCommand(); cmd != nil {
|
||||
switch cmd.Verb {
|
||||
@@ -107,6 +126,25 @@ func (channel *Channel) loop() {
|
||||
log.Println("Could not set event name:", err)
|
||||
}
|
||||
}
|
||||
case "register":
|
||||
{
|
||||
target := channel.client.Channel(channel.name)
|
||||
if target != nil {
|
||||
me, ok := target.UserList().User(channel.client.Nick())
|
||||
if !ok || !strings.ContainsRune(me.Modes, 'o') {
|
||||
channel.client.Say(channel.name, "This unit has insufficient privileges.")
|
||||
break
|
||||
}
|
||||
|
||||
chanServNick := config.Get().Names.ChanServ
|
||||
if chanServNick == "" {
|
||||
channel.client.Say(channel.name, "This function is not enabled.")
|
||||
break
|
||||
}
|
||||
|
||||
channel.client.Sayf(chanServNick, "REGISTER %s", target.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
queue = append(queue, post)
|
||||
@@ -116,6 +154,9 @@ func (channel *Channel) loop() {
|
||||
}
|
||||
}
|
||||
|
||||
// Posts after here aren't going to be bot commands, so log its reception.
|
||||
log.Printf("Received %s post from %s", post.Kind, post.Nick)
|
||||
|
||||
// Stop here if there's nothing to post.
|
||||
if len(queue) == 0 {
|
||||
break
|
||||
|
||||
+23
-8
@@ -2,12 +2,12 @@ package bot
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"git.aiterp.net/rpdata/logbot3/internal/util"
|
||||
|
||||
"git.aiterp.net/gisle/irc"
|
||||
"github.com/gissleh/irc"
|
||||
"git.aiterp.net/rpdata/logbot3/internal/config"
|
||||
"git.aiterp.net/rpdata/logbot3/internal/util"
|
||||
)
|
||||
|
||||
func handler(event *irc.Event, client *irc.Client) {
|
||||
@@ -22,6 +22,8 @@ func handler(event *irc.Event, client *irc.Client) {
|
||||
{
|
||||
log.Println("Client is ready!")
|
||||
go bot.loop()
|
||||
|
||||
bot.runCommands(config.Get().Commands.OnReady, bot.client.Status(), nil)
|
||||
}
|
||||
case "client.disconnect":
|
||||
{
|
||||
@@ -93,6 +95,12 @@ func handler(event *irc.Event, client *irc.Client) {
|
||||
text = util.RemoveNPCAttribution(event.Text)
|
||||
}
|
||||
|
||||
// Do not dispatch empty messages.
|
||||
if len(text) < 1 || len(nick) < 1 || len(kind) < 1 {
|
||||
log.Println("Ignoring empty message from:", event.Nick)
|
||||
break
|
||||
}
|
||||
|
||||
// Dispatch it.
|
||||
bot.handlePost(channel.Name(), ChannelPost{
|
||||
Account: account,
|
||||
@@ -114,13 +122,20 @@ func handler(event *irc.Event, client *irc.Client) {
|
||||
{
|
||||
log.Printf("(%s) %s\n", event.Verb(), event.Text)
|
||||
}
|
||||
case "packet.005", "packet.254", "packet.cap", "packet.431", "packet.432", "packet.433", "packet.436":
|
||||
case "packet.005", "packet.cap", "packet.254":
|
||||
{
|
||||
log.Printf("(%s) %s %s\n", event.Verb(), strings.Join(event.Args, " "), event.Text)
|
||||
log.Printf("(%s) %s %s\n", event.Verb(), strings.Join(event.Args[1:], " "), event.Text)
|
||||
}
|
||||
case "packet.error":
|
||||
{
|
||||
log.Printf("(%s) %s\n", event.Verb(), event.Text)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// Always log error numerics.
|
||||
if len(event.Verb()) == 3 && event.Verb()[0] == '4' || event.Verb()[0] == '9' {
|
||||
log.Printf("(%s) %s %s\n", event.Verb(), strings.Join(event.Args, " "), event.Text)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
irc.Handle(handler)
|
||||
}
|
||||
|
||||
@@ -14,10 +14,14 @@ type Config struct {
|
||||
User string `json:"user"`
|
||||
RealName string `json:"realName"`
|
||||
} `json:"bot"`
|
||||
Debug struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Listen string `json:"listen"`
|
||||
} `json:"debug"`
|
||||
Server struct {
|
||||
Address string `json:"server"`
|
||||
SSL bool `json:"ssl"`
|
||||
}
|
||||
} `json:"server"`
|
||||
API struct {
|
||||
Endpoint string `json:"endpoint"`
|
||||
Username string `json:"username"`
|
||||
@@ -26,6 +30,13 @@ type Config struct {
|
||||
Secret string `json:"secret"`
|
||||
} `json:"key"`
|
||||
} `json:"api"`
|
||||
Commands struct {
|
||||
OnJoinOp []string `json:"onJoinOp"`
|
||||
OnReady []string `json:"onReady"`
|
||||
} `json:"commands"`
|
||||
Names struct {
|
||||
ChanServ string `json:"chanserv"`
|
||||
} `json:"names"`
|
||||
}
|
||||
|
||||
var mutex sync.Mutex
|
||||
|
||||
@@ -28,6 +28,10 @@ func TestRemoveNPCAttribution(t *testing.T) {
|
||||
Input: "((*Correction))",
|
||||
Output: "((*Correction))",
|
||||
},
|
||||
{
|
||||
Input: "((Remove :01 goofs!*))",
|
||||
Output: "((Remove :01 goofs!*))",
|
||||
},
|
||||
}
|
||||
|
||||
for i, row := range table {
|
||||
|
||||
@@ -2,7 +2,9 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
@@ -10,7 +12,6 @@ import (
|
||||
|
||||
"git.aiterp.net/rpdata/logbot3/internal/bot"
|
||||
"git.aiterp.net/rpdata/logbot3/internal/config"
|
||||
|
||||
"git.aiterp.net/rpdata/logbot3/internal/models/users"
|
||||
)
|
||||
|
||||
@@ -32,6 +33,23 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if conf.Debug.Enabled {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
mux.HandleFunc("/state", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(200)
|
||||
_ = json.NewEncoder(w).Encode(bot.ClientState())
|
||||
})
|
||||
|
||||
go func() {
|
||||
err := http.ListenAndServe(conf.Debug.Listen, mux)
|
||||
if err != nil {
|
||||
log.Println("Failed to setup debug listener", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Listen for a quit signal.
|
||||
interrupt := make(chan os.Signal, 1)
|
||||
signal.Notify(interrupt, os.Interrupt)
|
||||
|
||||
Reference in New Issue
Block a user