Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proxy connection to IRC server #402

Merged
merged 22 commits into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@

// 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)

Check warning on line 140 in publish/publish.go

View check run for this annotation

Codecov / codecov/patch

publish/publish.go#L140

Added line #L140 was not covered by tests
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 @@

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

"github.com/wabarc/logger"
"github.com/wabarc/wayback"
Expand All @@ -16,82 +16,97 @@
"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
}

Check warning on line 50 in publish/relaychat/relaychat.go

View check run for this annotation

Codecov / codecov/patch

publish/relaychat/relaychat.go#L43-L50

Added lines #L43 - L50 were not covered by tests
}

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...) {

Check warning on line 61 in publish/relaychat/relaychat.go

View check run for this annotation

Codecov / codecov/patch

publish/relaychat/relaychat.go#L60-L61

Added lines #L60 - L61 were not covered by tests
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 {

Check warning on line 69 in publish/relaychat/relaychat.go

View check run for this annotation

Codecov / codecov/patch

publish/relaychat/relaychat.go#L69

Added line #L69 was not covered by tests
if !i.opts.PublishToIRCChannel() || i.conn == nil {
logger.Warn("Do not publish to IRC channel.")
return false
}
if text == "" {
if len(text) == 0 {

Check warning on line 74 in publish/relaychat/relaychat.go

View check run for this annotation

Codecov / codecov/patch

publish/relaychat/relaychat.go#L74

Added line #L74 was not covered by tests
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
}

Check warning on line 83 in publish/relaychat/relaychat.go

View check run for this annotation

Codecov / codecov/patch

publish/relaychat/relaychat.go#L79-L83

Added lines #L79 - L83 were not covered by tests

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")
}

Check warning on line 96 in publish/relaychat/relaychat.go

View check run for this annotation

Codecov / codecov/patch

publish/relaychat/relaychat.go#L93-L96

Added lines #L93 - L96 were not covered by tests

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())
}

Check warning on line 109 in publish/relaychat/relaychat.go

View check run for this annotation

Codecov / codecov/patch

publish/relaychat/relaychat.go#L98-L109

Added lines #L98 - L109 were not covered by tests
}
return err

Check warning on line 111 in publish/relaychat/relaychat.go

View check run for this annotation

Codecov / codecov/patch

publish/relaychat/relaychat.go#L111

Added line #L111 was not covered by tests
}
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 @@
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)

Check warning on line 274 in reduxer/reduxer.go

View check run for this annotation

Codecov / codecov/patch

reduxer/reduxer.go#L274

Added line #L274 was not covered by tests
return fallback()
}
shot, err = browser.Screenshot(ctx, uri, opts...)
Expand Down
Loading
Loading