Skip to content

Commit

Permalink
Proxy connection to IRC server (#402)
Browse files Browse the repository at this point in the history
* Change `github.com/thoj/go-ircevent` to `gopkg.in/irc.v4`
* Fix `daemon` flag not working when value is `irc`
* Add support for playback from IRC
* Add support for place IRC name
* Styling IRC message
* Fallback to non-TLS server
  • Loading branch information
waybackarchiver authored Feb 23, 2024
1 parent d4e4dcd commit 30dc536
Show file tree
Hide file tree
Showing 21 changed files with 578 additions and 289 deletions.
26 changes: 26 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1443,6 +1443,32 @@ func TestIRC(t *testing.T) {
},
want: "foo",
},
{
name: "default irc name",
envs: map[string]string{
"WAYBACK_IRC_NAME": "",
},
call: func(t *testing.T, opts *Options, want string) {
called := opts.IRCName()
if called != want {
t.Errorf(`Unexpected get the irc name, got %v instead of %s`, called, want)
}
},
want: defIRCName,
},
{
name: "specified irc name",
envs: map[string]string{
"WAYBACK_IRC_NAME": "foo",
},
call: func(t *testing.T, opts *Options, want string) {
called := opts.IRCName()
if called != want {
t.Errorf(`Unexpected get the irc name, got %v instead of %s`, called, want)
}
},
want: "foo",
},
{
name: "default irc password",
envs: map[string]string{
Expand Down
13 changes: 12 additions & 1 deletion config/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const (
defSlackHelptext = "Hi there."

defIRCNick = ""
defIRCName = ""
defIRCPassword = ""
defIRCChannel = ""
defIRCServer = "irc.libera.chat:6697"
Expand Down Expand Up @@ -224,6 +225,7 @@ type nostr struct {

type irc struct {
nick string
name string
password string
channel string
server string
Expand Down Expand Up @@ -331,6 +333,7 @@ func NewOptions() *Options {
},
irc: &irc{
nick: defIRCNick,
name: defIRCName,
password: defIRCPassword,
channel: defIRCChannel,
server: defIRCServer,
Expand Down Expand Up @@ -361,7 +364,7 @@ func (o *Options) EnableServices(s ...string) {
o.services.Store(ServiceMastodon, true)
case ServiceMatrix.String():
o.services.Store(ServiceMatrix, true)
case ServiceIRC.String():
case ServiceIRC.String(), "irc":
o.services.Store(ServiceIRC, true)
case ServiceSlack.String():
o.services.Store(ServiceSlack, true)
Expand Down Expand Up @@ -597,6 +600,14 @@ func (o *Options) IRCNick() string {
return o.irc.nick
}

// IRCName returns name of IRC
func (o *Options) IRCName() string {
if o.irc.name != "" {
return o.irc.name
}
return o.irc.nick
}

// IRCPassword returns password of IRC
func (o *Options) IRCPassword() string {
return o.irc.password
Expand Down
2 changes: 2 additions & 0 deletions config/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ func (p *Parser) parseLines(lines []string) (err error) {
p.opts.notion.databaseID = parseString(val, defNotionDatabaseID)
case "WAYBACK_IRC_NICK":
p.opts.irc.nick = parseString(val, defIRCNick)
case "WAYBACK_IRC_NAME":
p.opts.irc.name = parseString(val, defIRCName)
case "WAYBACK_IRC_PASSWORD":
p.opts.irc.password = parseString(val, defIRCPassword)
case "WAYBACK_IRC_CHANNEL":
Expand Down
7 changes: 7 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Refactoring HTTP client for better consistency and maintainability ([#401](https://github.com/wabarc/wayback/pull/401))
- ci: bump action version for page workflow
- Replace meilisearch actions with `wabarc/.github/meilisearch` instead ([#491](https://github.com/wabarc/wayback/pull/491))
- Proxy connection to IRC server ([#402](https://github.com/wabarc/wayback/pull/402))
- Change `github.com/thoj/go-ircevent` to `gopkg.in/irc.v4`
- Fix `daemon` flag not working when value is `irc`
- Add support for playback from IRC
- Add support for place IRC name
- Fallback to non-TLS server
- Styling IRC message

## [0.19.1] - 2023-03-21

Expand Down
1 change: 1 addition & 0 deletions docs/environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Use the `-c` / `--config` option to specify the build definition file to use.
| - | `WAYBACK_TWITTER_ACCESS_TOKEN` | - | The access token of your Twitter application |
| - | `WAYBACK_TWITTER_ACCESS_SECRET` | - | The access secret of your Twitter application |
| - | `WAYBACK_IRC_NICK` | - | IRC nick |
| - | `WAYBACK_IRC_NAME` | - | IRC name |
| - | `WAYBACK_IRC_PASSWORD` | - | IRC password |
| - | `WAYBACK_IRC_CHANNEL` | - | IRC channel |
| - | `WAYBACK_IRC_SERVER` | `irc.libera.chat:6697` | IRC server, required TLS |
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ require (
github.com/rs/xid v1.4.0
github.com/slack-go/slack v0.11.2
github.com/spf13/cobra v1.6.1
github.com/thoj/go-ircevent v0.0.0-20190807115034-8e7ce4b5a1eb
github.com/wabarc/archive.is v1.4.0
github.com/wabarc/archive.org v1.2.1-0.20210708220121-cb9b83ff9896
github.com/wabarc/go-anonfile v0.1.0
Expand All @@ -51,6 +50,7 @@ require (
go.etcd.io/bbolt v1.3.6
golang.org/x/net v0.21.0
golang.org/x/sync v0.6.0
gopkg.in/irc.v4 v4.0.0
gopkg.in/telebot.v3 v3.0.0-20220130115853-f0291132d3c3
maunium.net/go/mautrix v0.12.0
mellium.im/sasl v0.3.1
Expand Down Expand Up @@ -156,6 +156,7 @@ require (
golang.org/x/mod v0.15.0 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect
golang.org/x/tools v0.17.0 // indirect
google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/sourcemap.v1 v1.0.5 // indirect
Expand Down
7 changes: 5 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/tdewolff/parse/v2 v2.5.27/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
Expand All @@ -445,8 +446,6 @@ github.com/tdewolff/parse/v2 v2.6.5/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOd
github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/tdewolff/test v1.0.7 h1:8Vs0142DmPFW/bQeHRP3MV19m1gvndjUb1sn8yy74LM=
github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
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/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo=
github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
Expand Down Expand Up @@ -630,6 +629,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ=
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/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=
Expand Down Expand Up @@ -663,6 +664,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
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/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/irc.v4 v4.0.0 h1:5jsLkU2Tg+R2nGNqmkGCrciasyi4kNkDXhyZD+C31yY=
gopkg.in/irc.v4 v4.0.0/go.mod h1:BfjDz9MmuWW6OZY7iq4naOhudO8+QQCdO4Ko18jcsRE=
gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
Expand Down
5 changes: 4 additions & 1 deletion publish/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,14 @@ func (p *Publish) Stop() {

// Spread accepts calls from services that with collections and various parameters.
// It prepare all available publishers and put them into pooling.
func (p *Publish) Spread(_ context.Context, rdx reduxer.Reduxer, cols []wayback.Collect, from Flag, args ...string) {
func (p *Publish) Spread(ctx context.Context, rdx reduxer.Reduxer, cols []wayback.Collect, from Flag, args ...string) {
v := ctx.Value(from)

exec(func(mod *Module) {
bucket := pooling.Bucket{
Request: func(ctx context.Context) error {
logger.Info("requesting publishing from [%s] to [%s]...", from, mod.Flag)
ctx = context.WithValue(ctx, from, v)
err := mod.Publish(ctx, rdx, cols, args...)
if err != nil {
logger.Error("requesting publishing from [%s] to [%s] failed: %v", from, mod.Flag, err)
Expand Down
75 changes: 45 additions & 30 deletions publish/relaychat/relaychat.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package relaychat // import "github.com/wabarc/wayback/publish/relaychat"

import (
"context"
"crypto/tls"
"strings"

"github.com/wabarc/logger"
"github.com/wabarc/wayback"
Expand All @@ -16,82 +16,97 @@ import (
"github.com/wabarc/wayback/publish"
"github.com/wabarc/wayback/reduxer"
"github.com/wabarc/wayback/template/render"

irc "github.com/thoj/go-ircevent"
"gopkg.in/irc.v4"
)

// Interface guard
var _ publish.Publisher = (*IRC)(nil)

type IRC struct {
conn *irc.Connection
conn *irc.Client
opts *config.Options
}

// New returns a IRC struct
func New(conn *irc.Connection, opts *config.Options) *IRC {
func New(c *irc.Client, opts *config.Options) *IRC {
if !opts.PublishToIRCChannel() {
logger.Debug("Missing required environment variable, abort.")
return nil
}

if conn == nil {
conn = irc.IRC(opts.IRCNick(), opts.IRCNick())
conn.Password = opts.IRCPassword()
conn.VerboseCallbackHandler = opts.HasDebugMode()
conn.Debug = opts.HasDebugMode()
conn.UseTLS = true
conn.TLSConfig = &tls.Config{InsecureSkipVerify: false, MinVersion: tls.VersionTLS12}
}
server := opts.IRCServer()
if err := conn.Connect(server); err != nil {
logger.Error("connect to %s failed: %v", server, err)
return nil
}

return &IRC{conn: conn, opts: opts}
return &IRC{opts: opts}
}

// Publish publish text to IRC channel of given cols and args.
// A context should contain a `reduxer.Reduxer` via `publish.PubBundle` struct.
func (i *IRC) Publish(ctx context.Context, _ reduxer.Reduxer, cols []wayback.Collect, args ...string) error {
// Most IRC server supports establish one connection,
// this value accessed from service module.
if i.conn == nil {
v := ctx.Value(publish.FlagIRC)
conn, ok := v.(*irc.Client)
if ok {
i.conn = conn
}
}

metrics.IncrementPublish(metrics.PublishIRC, metrics.StatusRequest)

if len(cols) == 0 {
metrics.IncrementPublish(metrics.PublishIRC, metrics.StatusFailure)
return errors.New("publish to irc: collects empty")
}

var txt = render.ForPublish(&render.Relaychat{Cols: cols}).String()
if i.toChannel(ctx, txt) {
txt := strings.Split(render.ForPublish(&render.Relaychat{Cols: cols}).String(), "\n")
if i.toChannel(ctx, txt...) {
metrics.IncrementPublish(metrics.PublishIRC, metrics.StatusSuccess)
return nil
}
metrics.IncrementPublish(metrics.PublishIRC, metrics.StatusFailure)
return errors.New("publish to irc failed")
}

func (i *IRC) toChannel(_ context.Context, text string) bool {
func (i *IRC) toChannel(_ context.Context, text ...string) bool {
if !i.opts.PublishToIRCChannel() || i.conn == nil {
logger.Warn("Do not publish to IRC channel.")
return false
}
if text == "" {
if len(text) == 0 {
logger.Warn("IRC validation failed: Text can't be blank")
return false
}

go func() {
// i.conn.Join(o.opts.IRCChannel())
i.conn.Privmsg(i.opts.IRCChannel(), text)
}()
err := i.reply(i.opts.IRCChannel(), text...)
if err != nil {
logger.Error("publish to IRC channel failed: %v", err)
return false
}

return true
}

// Shutdown shuts down the IRC publish service.
func (i *IRC) Shutdown() error {
i.conn.Quit()

return nil
}

func (i *IRC) reply(name string, messages ...string) (err error) {
if i.conn == nil {
return errors.New("irc connection is missing")
}

for _, text := range messages {
text = strings.ReplaceAll(text, "\n", " ")
msg := &irc.Message{
Command: "PRIVMSG",
Params: []string{
name,
text,
},
}
if e := i.conn.WriteMessage(msg); e != nil {
err = errors.Wrap(err, e.Error())
}
}
return err
}
2 changes: 1 addition & 1 deletion reduxer/reduxer.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ func capture(ctx context.Context, cfg *config.Options, uri *url.URL, dir string)
logger.Debug("reduxer using remote browser")
browser, er := screenshot.NewChromeRemoteScreenshoter[screenshot.Path](remote)
if er != nil {
logger.Error("screenshot dial failed: %v", er)
logger.Warn("screenshot dial failed: %v", er)
return fallback()
}
shot, err = browser.Screenshot(ctx, uri, opts...)
Expand Down
Loading

0 comments on commit 30dc536

Please sign in to comment.