Begin: replace irc library with girc
This commit is contained in:
parent
922e41f095
commit
9b7f5296e7
|
@ -1,9 +0,0 @@
|
|||
ARG GOLANG_VERSION=1.16
|
||||
FROM golang:$GOLANG_VERSION-alpine
|
||||
|
||||
WORKDIR /bot
|
||||
COPY . .
|
||||
RUN go build
|
||||
|
||||
CMD ["./go-discord-irc", "--config", "config.yml"]
|
||||
|
26
LICENSE.md
26
LICENSE.md
|
@ -2,21 +2,15 @@ MIT License
|
|||
|
||||
Copyright (c) 2017 Qais Patankar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
67
README.md
67
README.md
|
@ -5,34 +5,31 @@
|
|||
|
||||
[![Preview](https://i.imgur.com/YpCqzdn.gif)](https://i.imgur.com/YpCqzdn.webm)
|
||||
|
||||
**Is this being maintained?** Yes. But I want to merge all this functionality
|
||||
into the much superior
|
||||
**Is this being maintained?** Yes. But I want to merge all this functionality into the much superior
|
||||
[matterbridge by 42wim](https://github.com/42wim/matterbridge).
|
||||
|
||||
This is IRC to Discord bridge was originally built for
|
||||
[@compsoc-edinburgh](http://github.com/compsoc-edinburgh) and
|
||||
[ImaginaryNet](http://imaginarynet.uk/), but now it looks like more people are
|
||||
using it!
|
||||
[ImaginaryNet](http://imaginarynet.uk/), but now it looks like more people are using it!
|
||||
|
||||
- The `IRC -> Discord` side of things work as you would expect it to: messages
|
||||
on IRC send to Discord as the bot user, as per usual.
|
||||
- The `Discord -> IRC` side of things is a little different. On connect, this
|
||||
bot will join the server with the `~d`, and spawn additional connections for
|
||||
each online person in the Discord.
|
||||
- The `IRC -> Discord` side of things work as you would expect it to: messages on IRC send to Discord as the bot user,
|
||||
as per usual.
|
||||
- The `Discord -> IRC` side of things is a little different. On connect, this bot will join the server with the `~d`,
|
||||
and spawn additional connections for each online person in the Discord.
|
||||
- Supports bidirectional PMs. (Not user friendly, but it works.)
|
||||
|
||||
**Features**
|
||||
|
||||
(not a full list)
|
||||
|
||||
- Every Discord user in your server will join your channel. Messages come from those "puppets", not from a single chat bridge user.
|
||||
- Every Discord user in your server will join your channel. Messages come from those "puppets", not from a single chat
|
||||
bridge user.
|
||||
- Saying the puppet username will @ that person on Discord.
|
||||
- When a Discord user's presence is "offline" or "idle", their irc puppet will
|
||||
have their AWAY status set.
|
||||
- A Discord user offline for will disconnect from IRC after 24 hours (or
|
||||
whatever `cooldown_duration` you set).
|
||||
- When a Discord user's presence is "offline" or "idle", their irc puppet will have their AWAY status set.
|
||||
- A Discord user offline for will disconnect from IRC after 24 hours (or whatever `cooldown_duration` you set).
|
||||
- Join/Quit/Part/Kick messages are sent to Discord (configurable!)
|
||||
- Replying to someone on Discord will prefix that someone's name, e.g. replying to Alex with "yes that's fine" will show up as `<you> Alex: yes, that's fine` on IRC.
|
||||
- Replying to someone on Discord will prefix that someone's name, e.g. replying to Alex with "yes that's fine" will show
|
||||
up as `<you> Alex: yes, that's fine` on IRC.
|
||||
- IRC users can send (custom!) emoji to Discord, just do `:somename:`. Discord emoji shows up like that on IRC.
|
||||
- Reacting to a Discord message will send a CTCP ACTION (`/me`) on IRC.
|
||||
|
||||
|
@ -40,18 +37,16 @@ using it!
|
|||
|
||||
Things to keep in mind in terms of functionality:
|
||||
|
||||
- This does not work with private Discord channels properly (all discord users
|
||||
are added to the channel)
|
||||
- This does not work with private Discord channels properly (all discord users are added to the channel)
|
||||
- **DO NOT USE THE SAME DISCORD BOT (API KEY) ACROSS MULTIPLE GUILDS
|
||||
(SERVERS).**
|
||||
|
||||
It's built with configuration in mind, but may need a little bit of tweaking for
|
||||
it to work for you:
|
||||
It's built with configuration in mind, but may need a little bit of tweaking for it to work for you:
|
||||
|
||||
- **Hardcoded**: Hostnames are hardcoded to follow the IPv6 IPs listed
|
||||
[here](https://github.com/qaisjp/go-discord-irc/issues/2).
|
||||
- **Defaults aren't usable**: You should set the `suffix` and `separator` config
|
||||
options. The default options require custom modifications to the IRC server.
|
||||
- **Defaults aren't usable**: You should set the `suffix` and `separator` config options. The default options require
|
||||
custom modifications to the IRC server.
|
||||
- **Server config**: This uses `WEBIRC` to give Discord users on IRC a distinct
|
||||
hostname. [See here](https://kiwiirc.com/docs/webirc).
|
||||
|
||||
|
@ -59,13 +54,11 @@ it to work for you:
|
|||
|
||||
The binary takes three flags:
|
||||
|
||||
- `--config filename.yaml`: to pass along a configuration file containing things
|
||||
like passwords and channel options
|
||||
- `--simple`: to only spawn one connection (the listener will send across
|
||||
messages from Discord) instead of a connection per online Discord user
|
||||
- `--debug`: provide this flag to print extra debug info. Setting this flag to
|
||||
false (or not providing this flag) will take the value from the config file
|
||||
instead
|
||||
- `--config filename.yaml`: to pass along a configuration file containing things like passwords and channel options
|
||||
- `--simple`: to only spawn one connection (the listener will send across messages from Discord) instead of a connection
|
||||
per online Discord user
|
||||
- `--debug`: provide this flag to print extra debug info. Setting this flag to false (or not providing this flag) will
|
||||
take the value from the config file instead
|
||||
- `--insecure`: used to skip TLS verification (false = use value from settings)
|
||||
- `--no-tls`: turns off TLS
|
||||
|
||||
|
@ -83,7 +76,8 @@ The config file is a yaml formatted file with the following fields:
|
|||
| `guild_id` | No | | No | the Discord guild (server) id |
|
||||
| `irc_pass` | Yes | | Yes | password for connecting to the IRC server |
|
||||
| `suffix` | No | `~d` | Yes | appended to each Discord user's nickname when they are connected to IRC. If set to `_d2`, if the name will be `bob_d2` |
|
||||
| `separator` | No | `_` | Yes | used in fallback situations. If set to `-`, the **fallback name** will be like `bob-7247_d2` (where `7247` is the discord user's discriminator, and `_d2` is the suffix) |
|
||||
| `separator` | No | `_` | Yes | used in fallback situations. If set to `-`, the **
|
||||
fallback name** will be like `bob-7247_d2` (where `7247` is the discord user's discriminator, and `_d2` is the suffix) |
|
||||
| `irc_listener_name` | Yes | `~d` | The name of the irc listener | |
|
||||
| `ignored_discord_ids` | Sometimes | | Yes | A list of Discord IDs to not relay to IRC |
|
||||
| `allowed_discord_ids` | Sometimes | `null` | Yes | A list of Discord IDs to relay to IRC. `null` allows all Discord users to be relayed to IRC. Hot reload: IDs added to the list require a presence change to take effect. |
|
||||
|
@ -100,13 +94,11 @@ The config file is a yaml formatted file with the following fields:
|
|||
| `ignored_irc_hostmasks` | No | | Yes | A list of IRC users identified by hostmask to not relay to Discord, uses matching syntax as in [glob](https://github.com/gobwas/glob) |
|
||||
| `connection_limit` | Yes | 0 | Yes | How many connections to IRC (including our listener) to spawn (limit of 0 or less means unlimited) |
|
||||
|
||||
**The filename.yaml file is continuously read from and many changes will
|
||||
automatically update on the bridge. This means you can add or remove channels
|
||||
without restarting the bot.**
|
||||
**The filename.yaml file is continuously read from and many changes will automatically update on the bridge. This means
|
||||
you can add or remove channels without restarting the bot.**
|
||||
|
||||
An example configuration file can be seen in [`config.yml`](./config.yml). Those
|
||||
marked as `requires restart` definitely require restart, but others may not
|
||||
currently be configured to automatically update.
|
||||
An example configuration file can be seen in [`config.yml`](./config.yml). Those marked as `requires restart` definitely
|
||||
require restart, but others may not currently be configured to automatically update.
|
||||
|
||||
This bot needs permissions to manage webhooks as it creates webhooks on the go.
|
||||
|
||||
|
@ -122,9 +114,8 @@ Make sure you also give the bot application these intents too:
|
|||
|
||||
## Docker
|
||||
|
||||
First edit `config.yml` file to your needs.
|
||||
Then launch `docker build -t go-discord-irc .` in the repository root folder.
|
||||
And then `docker run -d go-discord-irc` to run the bot in background.
|
||||
First edit `config.yml` file to your needs. Then launch `docker build -t go-discord-irc .` in the repository root
|
||||
folder. And then `docker run -d go-discord-irc` to run the bot in background.
|
||||
|
||||
## Development
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
irc "git.tcp.direct/kayos/girc-tcpd"
|
||||
"github.com/gobwas/glob"
|
||||
"github.com/matterbridge/discordgo"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/qaisjp/go-discord-irc/irc/varys"
|
||||
irc "github.com/qaisjp/go-ircevent"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/qaisjp/go-discord-irc/irc/varys"
|
||||
)
|
||||
|
||||
// Config to be passed to New
|
||||
|
@ -34,7 +34,6 @@ type Config struct {
|
|||
DiscordAllowed map[string]struct{} // Discord user IDs to only bridge
|
||||
ConnectionLimit int // number of IRC connections we can spawn
|
||||
|
||||
IRCPuppetPrejoinCommands []string
|
||||
IRCListenerPrejoinCommands []string
|
||||
|
||||
// filters
|
||||
|
@ -212,13 +211,13 @@ func (b *Bridge) SetChannelMappings(inMappings map[string]string) error {
|
|||
}
|
||||
}
|
||||
|
||||
b.ircListener.SendRaw("PART " + strings.Join(rmChannels, ","))
|
||||
b.ircListener.Client.Cmd.SendRaw("PART " + strings.Join(rmChannels, ","))
|
||||
if err := b.ircManager.varys.SendRaw("", varys.InterpolationParams{}, "PART "+strings.Join(rmChannels, ",")); err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
// The bots needs to join the new mappings
|
||||
b.ircListener.JoinChannels()
|
||||
b.ircListener.JoinChannels(b.ircListener.Client, irc.Event{})
|
||||
for _, conn := range b.ircManager.ircConnections {
|
||||
conn.JoinChannels()
|
||||
}
|
||||
|
@ -265,7 +264,7 @@ func New(conf *Config) (*Bridge, error) {
|
|||
// SetIRCListenerName changes the username of the listener bot.
|
||||
func (b *Bridge) SetIRCListenerName(name string) {
|
||||
b.Config.IRCListenerName = name
|
||||
b.ircListener.Nick(name)
|
||||
b.ircListener.Client.Cmd.Nick(name)
|
||||
}
|
||||
|
||||
// SetDebugMode allows you to control debug logging.
|
||||
|
@ -283,41 +282,14 @@ func (b *Bridge) Open() (err error) {
|
|||
return errors.Wrap(err, "can't open discord")
|
||||
}
|
||||
|
||||
err = b.ircListener.Connect(b.Config.IRCServer)
|
||||
err = b.ircListener.Connect()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "can't open irc connection")
|
||||
}
|
||||
|
||||
// run listener loop
|
||||
go b.ircListener.Loop()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SetupIRCConnection sets up an IRC connection with config settings like
|
||||
// UseTLS, InsecureSkipVerify, and WebIRCPass.
|
||||
func (b *Bridge) SetupIRCConnection(con *irc.Connection, hostname, ip string) {
|
||||
if !b.Config.NoTLS {
|
||||
con.UseTLS = true
|
||||
con.TLSConfig = &tls.Config{
|
||||
InsecureSkipVerify: b.Config.InsecureSkipVerify,
|
||||
}
|
||||
}
|
||||
|
||||
// On kick, rejoin the channel
|
||||
con.AddCallback("KICK", func(e *irc.Event) {
|
||||
if e.Arguments[1] == con.GetNick() {
|
||||
con.Join(e.Arguments[0])
|
||||
}
|
||||
})
|
||||
|
||||
con.Password = b.Config.IRCServerPass
|
||||
|
||||
if b.Config.WebIRCPass != "" {
|
||||
con.WebIRC = fmt.Sprintf("%s discord %s %s", b.Config.WebIRCPass, hostname, ip)
|
||||
}
|
||||
}
|
||||
|
||||
// GetJoinCommand produces a JOIN command based on the provided mappings
|
||||
func (b *Bridge) GetJoinCommand(mappings []Mapping) string {
|
||||
var channels, keyedChannels, keys []string
|
||||
|
@ -481,7 +453,7 @@ func (b *Bridge) loop() {
|
|||
// Done!
|
||||
case <-b.done:
|
||||
b.discord.Close()
|
||||
b.ircListener.Quit()
|
||||
b.ircListener.Client.Quit("yeet")
|
||||
b.ircManager.Close()
|
||||
close(b.done)
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/42wim/matterbridge/bridge/discord/transmitter"
|
||||
|
||||
"github.com/qaisjp/go-discord-irc/dstate"
|
||||
ircnick "github.com/qaisjp/go-discord-irc/irc/nick"
|
||||
|
||||
|
|
|
@ -5,9 +5,10 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/qaisjp/go-discord-irc/irc/varys"
|
||||
irc "github.com/qaisjp/go-ircevent"
|
||||
irc "git.tcp.direct/kayos/girc-tcpd"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/qaisjp/go-discord-irc/irc/varys"
|
||||
)
|
||||
|
||||
// An ircConnection should only ever communicate with its manager
|
||||
|
@ -47,9 +48,9 @@ func (i *ircConnection) Connected() bool {
|
|||
return connected
|
||||
}
|
||||
|
||||
func (i *ircConnection) OnWelcome(e *irc.Event) {
|
||||
func (i *ircConnection) OnWelcome(c *irc.Client, e irc.Event) {
|
||||
// execute puppet prejoin commands
|
||||
err := i.manager.varys.SendRaw(i.discord.ID, varys.InterpolationParams{Nick: true}, i.manager.bridge.Config.IRCPuppetPrejoinCommands...)
|
||||
err := i.manager.varys.SendRaw(i.discord.ID, varys.InterpolationParams{Nick: true})
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
@ -132,27 +133,27 @@ func (i *ircConnection) introducePM(nick string) {
|
|||
}
|
||||
}
|
||||
|
||||
func (i *ircConnection) OnPrivateMessage(e *irc.Event) {
|
||||
func (i *ircConnection) OnPrivateMessage(c *irc.Client, e irc.Event) {
|
||||
// Ignored hostmasks
|
||||
if i.manager.isIgnoredHostmask(e.Source) {
|
||||
if i.manager.isIgnoredHostmask(e.Source.String()) {
|
||||
return
|
||||
}
|
||||
|
||||
// Alert private messages
|
||||
if string(e.Arguments[0][0]) != "#" {
|
||||
if e.Message() == "help" {
|
||||
i.Privmsg(e.Nick, "Commands: help, who")
|
||||
} else if e.Message() == "who" {
|
||||
i.Privmsg(e.Nick, fmt.Sprintf("I am: %s#%s with ID %s", i.discord.Nick, i.discord.Discriminator, i.discord.ID))
|
||||
if string(e.Params[0][0]) != "#" {
|
||||
if e.Last() == "help" {
|
||||
i.Privmsg(e.Source.Name, "Commands: help, who")
|
||||
} else if e.Last() == "who" {
|
||||
i.Privmsg(e.Source.Name, fmt.Sprintf("I am: %s#%s with ID %s", i.discord.Nick, i.discord.Discriminator, i.discord.ID))
|
||||
}
|
||||
|
||||
d := i.manager.bridge.discord
|
||||
|
||||
i.introducePM(e.Nick)
|
||||
i.introducePM(e.Source.Name)
|
||||
|
||||
msg := fmt.Sprintf(
|
||||
"%s,%s - %s@%s: %s", e.Connection.Server, e.Source,
|
||||
e.Nick, i.manager.bridge.Config.Discriminator, e.Message())
|
||||
"%s - %s@%s: %s", e.Source,
|
||||
e.Source.Name, i.manager.bridge.Config.Discriminator, e.Last())
|
||||
_, err := d.Session.ChannelMessageSend(i.pmDiscordChannel, msg)
|
||||
if err != nil {
|
||||
log.Warnln("Could not send PM", i.discord, err)
|
||||
|
|
|
@ -1,74 +1,81 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
irc "git.tcp.direct/kayos/girc-tcpd"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
ircf "github.com/qaisjp/go-discord-irc/irc/format"
|
||||
irc "github.com/qaisjp/go-ircevent"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type ircListener struct {
|
||||
*irc.Connection
|
||||
*irc.Client
|
||||
bridge *Bridge
|
||||
|
||||
listenerCallbackIDs map[string]int
|
||||
}
|
||||
|
||||
func newIRCListener(dib *Bridge, webIRCPass string) *ircListener {
|
||||
irccon := irc.IRC(dib.Config.IRCListenerName, "discord")
|
||||
listener := &ircListener{irccon, dib, make(map[string]int)}
|
||||
var ircConfig = irc.Config{
|
||||
Server: dib.Config.IRCListenerName,
|
||||
User: dib.Config.IRCListenerName,
|
||||
Nick: dib.Config.IRCListenerName,
|
||||
ServerPass: dib.Config.IRCServerPass,
|
||||
Version: "tcp.direct",
|
||||
}
|
||||
|
||||
dib.SetupIRCConnection(irccon, "discord.", "fd75:f5f5:226f::")
|
||||
listener.SetDebugMode(dib.Config.Debug)
|
||||
if dib.Config.Debug {
|
||||
ircConfig.Debug = os.Stdout
|
||||
}
|
||||
|
||||
// Nick tracker for nick tracking
|
||||
irccon.SetupNickTrack()
|
||||
if !dib.Config.NoTLS {
|
||||
ircConfig.SSL = true
|
||||
ircConfig.TLSConfig = &tls.Config{
|
||||
InsecureSkipVerify: dib.Config.InsecureSkipVerify,
|
||||
}
|
||||
}
|
||||
|
||||
// Welcome event
|
||||
irccon.AddCallback("001", listener.OnWelcome)
|
||||
ircClient := irc.New(ircConfig)
|
||||
|
||||
// Called when received channel names... essentially OnJoinChannel
|
||||
irccon.AddCallback("366", listener.OnJoinChannel)
|
||||
irccon.AddCallback("PRIVMSG", listener.OnPrivateMessage)
|
||||
irccon.AddCallback("NOTICE", listener.OnPrivateMessage)
|
||||
irccon.AddCallback("CTCP_ACTION", listener.OnPrivateMessage)
|
||||
|
||||
irccon.AddCallback("900", func(e *irc.Event) {
|
||||
// Try to rejoni channels after authenticated with NickServ
|
||||
listener.JoinChannels()
|
||||
// On kick, rejoin the channel
|
||||
ircClient.Handlers.Add("KICK", func(c *irc.Client, e irc.Event) {
|
||||
if e.Params[1] == c.GetNick() {
|
||||
c.Cmd.Join(e.Params[0])
|
||||
}
|
||||
})
|
||||
|
||||
// we are assuming this will be posible to run independent of any
|
||||
// future NICK callbacks added, otherwise do it like the STQUIT callback
|
||||
listener.AddCallback("NICK", listener.nickTrackNick)
|
||||
listener := &ircListener{ircClient, dib, make(map[string]int)}
|
||||
|
||||
// Note that this might override SetupNickTrack!
|
||||
listener.OnJoinQuitSettingChange()
|
||||
// Welcome event
|
||||
ircClient.Handlers.Add(irc.CONNECTED, listener.JoinChannels)
|
||||
|
||||
// Called when received channel names... essentially OnJoinChannel
|
||||
ircClient.Handlers.Add("366", listener.OnJoinChannel)
|
||||
ircClient.Handlers.Add("PRIVMSG", listener.OnPrivateMessage)
|
||||
ircClient.Handlers.Add("NOTICE", listener.OnPrivateMessage)
|
||||
ircClient.Handlers.Add("CTCP_ACTION", listener.OnPrivateMessage)
|
||||
|
||||
// Try to rejoin channels after authenticated with NickServ
|
||||
ircClient.Handlers.Add("900", listener.JoinChannels)
|
||||
|
||||
return listener
|
||||
}
|
||||
|
||||
func (i *ircListener) nickTrackNick(event *irc.Event) {
|
||||
oldNick := event.Nick
|
||||
newNick := event.Message()
|
||||
if con, ok := i.bridge.ircManager.puppetNicks[oldNick]; ok {
|
||||
i.bridge.ircManager.puppetNicks[newNick] = con
|
||||
delete(i.bridge.ircManager.puppetNicks, oldNick)
|
||||
}
|
||||
}
|
||||
|
||||
func (i *ircListener) OnNickRelayToDiscord(event *irc.Event) {
|
||||
func (i *ircListener) OnNickRelayToDiscord(e irc.Event) {
|
||||
// ignored hostmasks, or we're a puppet? no relay
|
||||
if i.bridge.ircManager.isIgnoredHostmask(event.Source) ||
|
||||
i.isPuppetNick(event.Nick) ||
|
||||
i.isPuppetNick(event.Message()) {
|
||||
if i.bridge.ircManager.isIgnoredHostmask(e.Source.String()) ||
|
||||
i.isPuppetNick(e.Source.Name) ||
|
||||
i.isPuppetNick(e.Last()) {
|
||||
return
|
||||
}
|
||||
|
||||
oldNick := event.Nick
|
||||
newNick := event.Message()
|
||||
oldNick := e.Source.Name
|
||||
newNick := e.Last()
|
||||
|
||||
msg := IRCMessage{
|
||||
Username: "",
|
||||
|
@ -77,8 +84,9 @@ func (i *ircListener) OnNickRelayToDiscord(event *irc.Event) {
|
|||
|
||||
for _, m := range i.bridge.mappings {
|
||||
channel := m.IRCChannel
|
||||
if channelObj, ok := i.Connection.GetChannel(channel); ok {
|
||||
if _, ok := channelObj.GetUser(newNick); ok {
|
||||
|
||||
if channelObj := i.Client.LookupChannel(channel); channelObj != nil {
|
||||
if channelObj.UserIn(newNick) {
|
||||
msg.IRCChannel = channel
|
||||
i.bridge.discordMessagesChan <- msg
|
||||
}
|
||||
|
@ -86,79 +94,55 @@ func (i *ircListener) OnNickRelayToDiscord(event *irc.Event) {
|
|||
}
|
||||
}
|
||||
|
||||
func (i *ircListener) nickTrackPuppetQuit(e *irc.Event) {
|
||||
func (i *ircListener) nickTrackPuppetQuit(e irc.Event) {
|
||||
// Protect against HostServ changing nicks or ircd's with CHGHOST/CHGIDENT or similar
|
||||
// sending us a QUIT for a puppet nick only for it to rejoin right after.
|
||||
// The puppet nick won't see a true disconnection itself and thus will still see itself
|
||||
// as connected.
|
||||
if con, ok := i.bridge.ircManager.puppetNicks[e.Nick]; ok && !con.Connected() {
|
||||
delete(i.bridge.ircManager.puppetNicks, e.Nick)
|
||||
if con, ok := i.bridge.ircManager.puppetNicks[e.Source.Name]; ok && !con.Connected() {
|
||||
delete(i.bridge.ircManager.puppetNicks, e.Source.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func (i *ircListener) OnJoinQuitSettingChange() {
|
||||
// always remove our listener callbacks
|
||||
for ev, id := range i.listenerCallbackIDs {
|
||||
i.RemoveCallback(ev, id)
|
||||
delete(i.listenerCallbackIDs, ev)
|
||||
}
|
||||
|
||||
// we're either going to track quits, or track and relay said, so swap out the callback
|
||||
// based on which is in effect.
|
||||
if i.bridge.Config.ShowJoinQuit {
|
||||
i.listenerCallbackIDs["STNICK"] = i.AddCallback("STNICK", i.OnNickRelayToDiscord)
|
||||
|
||||
// KICK is not state tracked!
|
||||
callbacks := []string{"STJOIN", "STPART", "STQUIT", "KICK"}
|
||||
for _, cb := range callbacks {
|
||||
id := i.AddCallback(cb, i.OnJoinQuitCallback)
|
||||
i.listenerCallbackIDs[cb] = id
|
||||
}
|
||||
} else {
|
||||
id := i.AddCallback("STQUIT", i.nickTrackPuppetQuit)
|
||||
i.listenerCallbackIDs["STQUIT"] = id
|
||||
}
|
||||
}
|
||||
|
||||
func (i *ircListener) OnJoinQuitCallback(event *irc.Event) {
|
||||
func (i *ircListener) OnJoinQuitCallback(e irc.Event) {
|
||||
// This checks if the source of the event was from a puppet.
|
||||
if (event.Code == "KICK" && i.isPuppetNick(event.Arguments[1])) || i.isPuppetNick(event.Nick) {
|
||||
if (e.Command == "KICK" && i.isPuppetNick(e.Params[1])) || i.isPuppetNick(e.Source.Name) {
|
||||
// since we replace the STQUIT callback we have to manage our puppet nicks when
|
||||
// this call back is active!
|
||||
if event.Code == "STQUIT" {
|
||||
i.nickTrackPuppetQuit(event)
|
||||
if e.Command == "STQUIT" {
|
||||
i.nickTrackPuppetQuit(e)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Ignored hostmasks
|
||||
if i.bridge.ircManager.isIgnoredHostmask(event.Source) {
|
||||
if i.bridge.ircManager.isIgnoredHostmask(e.Source.String()) {
|
||||
return
|
||||
}
|
||||
|
||||
who := event.Nick
|
||||
message := event.Nick
|
||||
id := " (" + event.User + "@" + event.Host + ") "
|
||||
who := e.Source.Name
|
||||
message := e.Source.Name
|
||||
id := " (" + e.Source.Ident + "@" + e.Source.Host + ") "
|
||||
|
||||
switch event.Code {
|
||||
switch e.Command {
|
||||
case "STJOIN":
|
||||
message += " joined" + id
|
||||
case "STPART":
|
||||
message += " left" + id
|
||||
if len(event.Arguments) > 1 {
|
||||
message += ": " + event.Arguments[1]
|
||||
if len(e.Params) > 1 {
|
||||
message += ": " + e.Params[1]
|
||||
}
|
||||
case "STQUIT":
|
||||
message += " quit" + id
|
||||
|
||||
reason := event.Nick
|
||||
if len(event.Arguments) == 1 {
|
||||
reason = event.Arguments[0]
|
||||
reason := e.Source.Name
|
||||
if len(e.Params) == 1 {
|
||||
reason = e.Params[0]
|
||||
}
|
||||
message += "Quit: " + reason
|
||||
case "KICK":
|
||||
who = event.Arguments[1]
|
||||
message = event.Arguments[1] + " was kicked by " + event.Nick + ": " + event.Arguments[2]
|
||||
who = e.Params[1]
|
||||
message = e.Params[1] + " was kicked by " + e.Source.Name + ": " + e.Params[2]
|
||||
}
|
||||
|
||||
msg := IRCMessage{
|
||||
|
@ -167,38 +151,38 @@ func (i *ircListener) OnJoinQuitCallback(event *irc.Event) {
|
|||
Message: message,
|
||||
}
|
||||
|
||||
if event.Code == "STQUIT" {
|
||||
if e.Command == "STQUIT" {
|
||||
// Notify channels that the user is in
|
||||
for _, m := range i.bridge.mappings {
|
||||
channel := m.IRCChannel
|
||||
channelObj, ok := i.Connection.GetChannel(channel)
|
||||
if !ok {
|
||||
channelObj := i.Client.LookupChannel(channel)
|
||||
if channelObj == nil {
|
||||
log.WithField("channel", channel).WithField("who", who).Warnln("Trying to process QUIT. Channel not found in irc listener cache.")
|
||||
continue
|
||||
}
|
||||
if _, ok := channelObj.GetUser(who); !ok {
|
||||
|
||||
if channelObj.UserIn(who) {
|
||||
continue
|
||||
}
|
||||
msg.IRCChannel = channel
|
||||
i.bridge.discordMessagesChan <- msg
|
||||
}
|
||||
} else {
|
||||
msg.IRCChannel = event.Arguments[0]
|
||||
msg.IRCChannel = e.Params[0]
|
||||
i.bridge.discordMessagesChan <- msg
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: the user might not be on any channel that we're in and that would
|
||||
// lead to incorrect assumptions the user doesn't exist!
|
||||
// Good way to check is to utilize ISON
|
||||
func (i *ircListener) DoesUserExist(user string) bool {
|
||||
ret := false
|
||||
i.IterChannels(func(name string, ch *irc.Channel) {
|
||||
if !ret {
|
||||
_, ret = ch.GetUser(user)
|
||||
func (i *ircListener) DoesUserExist(user string) (exists bool) {
|
||||
exists = false
|
||||
i.Client.Cmd.SendRawf("ISON %s", user)
|
||||
i.Client.Handlers.AddTmp("303", 5*time.Second, func(c *irc.Client, e irc.Event) bool {
|
||||
if e.Params[len(e.Params)] == user {
|
||||
exists = true
|
||||
}
|
||||
return false
|
||||
})
|
||||
return ret
|
||||
return
|
||||
}
|
||||
|
||||
func (i *ircListener) SetDebugMode(debug bool) {
|
||||
|
@ -206,22 +190,14 @@ func (i *ircListener) SetDebugMode(debug bool) {
|
|||
// i.Debug = debug
|
||||
}
|
||||
|
||||
func (i *ircListener) OnWelcome(e *irc.Event) {
|
||||
// Execute prejoin commands
|
||||
for _, com := range i.bridge.Config.IRCListenerPrejoinCommands {
|
||||
i.SendRaw(strings.ReplaceAll(com, "${NICK}", i.GetNick()))
|
||||
func (i *ircListener) JoinChannels(c *irc.Client, e irc.Event) {
|
||||
for _, mapping := range i.bridge.mappings {
|
||||
c.Cmd.Join(mapping.IRCChannel)
|
||||
}
|
||||
|
||||
// Join all channels
|
||||
i.JoinChannels()
|
||||
}
|
||||
|
||||
func (i *ircListener) JoinChannels() {
|
||||
i.SendRaw(i.bridge.GetJoinCommand(i.bridge.mappings))
|
||||
}
|
||||
|
||||
func (i *ircListener) OnJoinChannel(e *irc.Event) {
|
||||
log.Infof("Listener has joined IRC channel %s.", e.Arguments[1])
|
||||
func (i *ircListener) OnJoinChannel(c *irc.Client, e irc.Event) {
|
||||
log.Infof("Listener has joined IRC channel %s.", e.Params[1])
|
||||
}
|
||||
|
||||
func (i *ircListener) isPuppetNick(nick string) bool {
|
||||
|
@ -234,18 +210,18 @@ func (i *ircListener) isPuppetNick(nick string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (i *ircListener) OnPrivateMessage(e *irc.Event) {
|
||||
func (i *ircListener) OnPrivateMessage(c *irc.Client, e irc.Event) {
|
||||
// Ignore private messages
|
||||
if string(e.Arguments[0][0]) != "#" {
|
||||
if string(e.Params[0][0]) != "#" {
|
||||
// If you decide to extend this to respond to PMs, make sure
|
||||
// you do not respond to NOTICEs, see issue #50.
|
||||
return
|
||||
}
|
||||
|
||||
if strings.TrimSpace(e.Message()) == "" || // Discord doesn't accept an empty message
|
||||
i.isPuppetNick(e.Nick) || // ignore msg's from our puppets
|
||||
i.bridge.ircManager.isIgnoredHostmask(e.Source) || //ignored hostmasks
|
||||
i.bridge.ircManager.isFilteredIRCMessage(e.Message()) { // filtered
|
||||
if strings.TrimSpace(e.Last()) == "" || // Discord doesn't accept an empty message
|
||||
i.isPuppetNick(e.Source.Name) || // ignore msg's from our puppets
|
||||
i.bridge.ircManager.isIgnoredHostmask(e.Source.String()) || // ignored hostmasks
|
||||
i.bridge.ircManager.isFilteredIRCMessage(e.Last()) { // filtered
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -256,18 +232,18 @@ func (i *ircListener) OnPrivateMessage(e *irc.Event) {
|
|||
|
||||
msg := strings.NewReplacer(
|
||||
replacements...,
|
||||
).Replace(e.Message())
|
||||
).Replace(e.Last())
|
||||
|
||||
if e.Code == "CTCP_ACTION" {
|
||||
if e.Command == "CTCP_ACTION" {
|
||||
msg = "_" + msg + "_"
|
||||
}
|
||||
|
||||
msg = ircf.BlocksToMarkdown(ircf.Parse(msg))
|
||||
|
||||
go func(e *irc.Event) {
|
||||
go func(e irc.Event) {
|
||||
i.bridge.discordMessagesChan <- IRCMessage{
|
||||
IRCChannel: e.Arguments[0],
|
||||
Username: e.Nick,
|
||||
IRCChannel: e.Params[0],
|
||||
Username: e.Source.Name,
|
||||
Message: msg,
|
||||
}
|
||||
}(e)
|
||||
|
|
|
@ -9,10 +9,11 @@ import (
|
|||
"github.com/mozillazg/go-unidecode"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
irc "git.tcp.direct/kayos/girc-tcpd"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
ircnick "github.com/qaisjp/go-discord-irc/irc/nick"
|
||||
"github.com/qaisjp/go-discord-irc/irc/varys"
|
||||
irc "github.com/qaisjp/go-ircevent"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// DevMode is a hack
|
||||
|
@ -258,7 +259,7 @@ func (m *IRCManager) HandleUser(user DiscordUser) {
|
|||
|
||||
WebIRCSuffix: fmt.Sprintf("discord %s %s", hostname, ip),
|
||||
|
||||
Callbacks: map[string]func(*irc.Event){
|
||||
Callbacks: map[string]func(c *irc.Client, e irc.Event){
|
||||
"001": con.OnWelcome,
|
||||
"PRIVMSG": con.OnPrivateMessage,
|
||||
},
|
||||
|
@ -394,7 +395,7 @@ func (m *IRCManager) SendMessage(channel string, msg *DiscordMessage) {
|
|||
if !ok {
|
||||
length := len(msg.Author.Username)
|
||||
for _, line := range strings.Split(content, "\n") {
|
||||
m.bridge.ircListener.Privmsg(channel, fmt.Sprintf(
|
||||
m.bridge.ircListener.Client.Cmd.Message(channel, fmt.Sprintf(
|
||||
"<%s#%s> %s",
|
||||
msg.Author.Username[:1]+"\u200B"+msg.Author.Username[1:length],
|
||||
msg.Author.Discriminator,
|
||||
|
|
2
go.mod
2
go.mod
|
@ -3,13 +3,13 @@ module github.com/qaisjp/go-discord-irc
|
|||
go 1.15
|
||||
|
||||
require (
|
||||
git.tcp.direct/kayos/girc-tcpd v0.0.0-20210905150122-4e0aac9cba2f
|
||||
github.com/42wim/matterbridge v1.22.0
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/matterbridge/discordgo v0.23.2-0.20210201201054-fb39a175b4f7
|
||||
github.com/mozillazg/go-unidecode v0.1.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/qaisjp/go-ircevent v0.0.0-20210224154625-07452bfb05b5
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
github.com/spf13/viper v1.7.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
|
|
27
go.sum
27
go.sum
|
@ -44,6 +44,8 @@ dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1
|
|||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
git.tcp.direct/kayos/girc-tcpd v0.0.0-20210905150122-4e0aac9cba2f h1:TfFJ1hBo5Ma29mn5QXJISE33UEJmfU0gjIpasYbb1Zw=
|
||||
git.tcp.direct/kayos/girc-tcpd v0.0.0-20210905150122-4e0aac9cba2f/go.mod h1:w6yijBG8Jw2AOrhYn2IlutzSB3gqv5ZKDcsJFeJZOVw=
|
||||
github.com/42wim/go-gitter v0.0.0-20170828205020-017310c2d557/go.mod h1:jL0YSXMs/txjtGJ4PWrmETOk6KUHMDPMshgQZlTeB3Y=
|
||||
github.com/42wim/matterbridge v1.22.0 h1:2RGvCa5s+hlGVhESgWnvvtQEhAYi1VrVEJ4zAXQQbwg=
|
||||
github.com/42wim/matterbridge v1.22.0/go.mod h1:FEkNlc5IhzSbAus9yzHprVoEvfvtEHODrGfCtKvP92k=
|
||||
|
@ -51,7 +53,6 @@ github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOv
|
|||
github.com/Azure/azure-sdk-for-go v26.5.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/go-autorest v11.5.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f/go.mod h1:4a58ifQTEe2uwwsaqbh3i2un5/CBPg+At/qHpt18Tmk=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw=
|
||||
|
@ -231,7 +232,6 @@ github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVB
|
|||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||
github.com/frankban/quicktest v1.4.0/go.mod h1:36zfPVQyHxymz4cH7wlDmVwDrJuljRB60qkgn7rorfQ=
|
||||
github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
|
@ -356,7 +356,6 @@ github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
|
|||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
|
@ -474,18 +473,15 @@ github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgo
|
|||
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
|
||||
github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/kljensen/snowball v0.6.0/go.mod h1:27N7E8fVU5H68RlUmnWwZCfxgt4POBJfENGMvNRhldw=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
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/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.3/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=
|
||||
|
@ -504,7 +500,6 @@ github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0U
|
|||
github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7/go.mod h1:liX5MxHPrwgHaKowoLkYGwbXfYABh1jbZ6FpElbGF1I=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
|
@ -576,7 +571,6 @@ github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUb
|
|||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
|
||||
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
|
@ -654,7 +648,6 @@ github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144T
|
|||
github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c/go.mod h1:YnNlZP7l4MhyGQ4CBRwv6ohZTPrUJJZtEv4ZgADkbs4=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
|
@ -667,7 +660,6 @@ github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi
|
|||
github.com/pierrec/lz4/v3 v3.3.2/go.mod h1:280XNCGS8jAcG++AHdd6SeWnzyJ1w9oow2vbORyey8Q=
|
||||
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/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=
|
||||
|
@ -709,8 +701,6 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
|
|||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/qaisjp/go-ircevent v0.0.0-20210224154625-07452bfb05b5 h1:elH75Fsz3q1CQT3/dt55EuehXGTBK/rslX7qnLvxADg=
|
||||
github.com/qaisjp/go-ircevent v0.0.0-20210224154625-07452bfb05b5/go.mod h1:QVUXUOAPFwMwEh+GKC+Zh56c5p7tZpRqGbXZzqaWbZE=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/reflog/dateconstraints v0.2.1/go.mod h1:Ax8AxTBcJc3E/oVS2hd2j7RDM/5MDtuPwuR7lIHtPLo=
|
||||
|
@ -765,7 +755,6 @@ github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYED
|
|||
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
|
||||
github.com/simplereach/timeutils v1.2.0/go.mod h1:VVbQDfN/FHRZa1LSqcwo4kNZ62OOyqLLGQKYB3pB0Q8=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
|
@ -783,28 +772,23 @@ github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJ
|
|||
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
|
||||
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.3.4 h1:8q6vk3hthlpb2SouZcnBVKboxWQWMDNF38bwholZrJc=
|
||||
github.com/spf13/afero v1.3.4/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
|
||||
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
|
@ -819,7 +803,6 @@ github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5J
|
|||
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/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
|
@ -927,7 +910,6 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf
|
|||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
|
@ -1064,7 +1046,6 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -1111,12 +1092,10 @@ golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d h1:MiWWjyhUzZ+jvhZvloX6ZrUsd
|
|||
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
@ -1289,7 +1268,6 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
|
|||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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=
|
||||
|
@ -1315,7 +1293,6 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
|
|||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
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 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
|
@ -28,7 +28,7 @@ const (
|
|||
FCHAN_C
|
||||
FNICK_C
|
||||
|
||||
// add )
|
||||
// add )
|
||||
)
|
||||
|
||||
// MAXLENGTH is the maximum length of a nickname
|
||||
|
|
|
@ -6,22 +6,21 @@ package varys
|
|||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
irc "github.com/qaisjp/go-ircevent"
|
||||
irc "git.tcp.direct/kayos/girc-tcpd"
|
||||
)
|
||||
|
||||
type Varys struct {
|
||||
connConfig SetupParams
|
||||
uidToConns map[string]*irc.Connection
|
||||
uidToConns map[string]*irc.Client
|
||||
}
|
||||
|
||||
func NewVarys() *Varys {
|
||||
return &Varys{uidToConns: make(map[string]*irc.Connection)}
|
||||
return &Varys{uidToConns: make(map[string]*irc.Client)}
|
||||
}
|
||||
|
||||
func (v *Varys) connCall(uid string, fn func(*irc.Connection)) {
|
||||
func (v *Varys) connCall(uid string, fn func(*irc.Client)) {
|
||||
if uid == "" {
|
||||
for _, conn := range v.uidToConns {
|
||||
fn(conn)
|
||||
|
@ -83,46 +82,52 @@ type ConnectParams struct {
|
|||
WebIRCSuffix string
|
||||
|
||||
// TODO(qaisjp): does not support net/rpc!!!!
|
||||
Callbacks map[string]func(*irc.Event)
|
||||
Callbacks map[string]func(c *irc.Client, e irc.Event)
|
||||
}
|
||||
|
||||
func (v *Varys) Connect(params ConnectParams, _ *struct{}) error {
|
||||
conn := irc.IRC(params.Nick, params.Username)
|
||||
// conn.Debug = true
|
||||
conn.RealName = params.RealName
|
||||
conn := irc.Config{
|
||||
Nick: params.Nick,
|
||||
User: params.Username,
|
||||
Name: params.RealName,
|
||||
Version: "tcp.direct",
|
||||
|
||||
SSL: false,
|
||||
}
|
||||
|
||||
// TLS things, and the server password
|
||||
conn.Password = v.connConfig.ServerPassword
|
||||
conn.UseTLS = v.connConfig.UseTLS
|
||||
conn.ServerPass = v.connConfig.ServerPassword
|
||||
if v.connConfig.UseTLS {
|
||||
conn.SSL = true
|
||||
}
|
||||
|
||||
if v.connConfig.InsecureSkipVerify {
|
||||
conn.TLSConfig = &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
}
|
||||
|
||||
// Set up WebIRC, if a suffix is provided
|
||||
if params.WebIRCSuffix != "" {
|
||||
conn.WebIRC = v.connConfig.WebIRCPassword + " " + params.WebIRCSuffix
|
||||
}
|
||||
client := irc.New(conn)
|
||||
|
||||
// On kick, rejoin the channel
|
||||
conn.AddCallback("KICK", func(e *irc.Event) {
|
||||
if e.Arguments[1] == conn.GetNick() {
|
||||
conn.Join(e.Arguments[0])
|
||||
client.Handlers.Add("KICK", func(c *irc.Client, e irc.Event) {
|
||||
if e.Params[1] == client.GetNick() {
|
||||
c.Cmd.Join(e.Params[0])
|
||||
}
|
||||
})
|
||||
|
||||
for eventcode, callback := range params.Callbacks {
|
||||
conn.AddCallback(eventcode, callback)
|
||||
client.Handlers.Add(eventcode, callback)
|
||||
}
|
||||
|
||||
err := conn.Connect(v.connConfig.Server)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error opening irc connection: %w", err)
|
||||
}
|
||||
go func() {
|
||||
err := client.Connect()
|
||||
if err != nil {
|
||||
println("error opening irc connection: %w", err)
|
||||
}
|
||||
}()
|
||||
|
||||
v.uidToConns[params.UID] = conn
|
||||
go conn.Loop()
|
||||
v.uidToConns[params.UID] = client
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -133,9 +138,8 @@ type QuitParams struct {
|
|||
|
||||
func (v *Varys) QuitIfConnected(params QuitParams, _ *struct{}) error {
|
||||
if conn, ok := v.uidToConns[params.UID]; ok {
|
||||
if conn.Connected() {
|
||||
conn.QuitMessage = params.QuitMessage
|
||||
conn.Quit()
|
||||
if conn.IsConnected() {
|
||||
conn.Quit(params.QuitMessage)
|
||||
}
|
||||
}
|
||||
delete(v.uidToConns, params.UID)
|
||||
|
@ -153,12 +157,12 @@ type SendRawParams struct {
|
|||
}
|
||||
|
||||
func (v *Varys) SendRaw(params SendRawParams, _ *struct{}) error {
|
||||
v.connCall(params.UID, func(c *irc.Connection) {
|
||||
v.connCall(params.UID, func(c *irc.Client) {
|
||||
for _, msg := range params.Messages {
|
||||
if params.Interpolation.Nick {
|
||||
msg = strings.ReplaceAll(msg, "${NICK}", c.GetNick())
|
||||
}
|
||||
c.SendRaw(msg)
|
||||
c.Cmd.SendRaw(msg)
|
||||
}
|
||||
})
|
||||
return nil
|
||||
|
@ -173,7 +177,7 @@ func (v *Varys) GetNick(uid string, result *string) error {
|
|||
|
||||
func (v *Varys) Connected(uid string, result *bool) error {
|
||||
if conn, ok := v.uidToConns[uid]; ok {
|
||||
*result = conn.Connected()
|
||||
*result = conn.IsConnected()
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -186,7 +190,7 @@ type NickParams struct {
|
|||
|
||||
func (v *Varys) Nick(params NickParams, _ *struct{}) error {
|
||||
if conn, ok := v.uidToConns[params.UID]; ok {
|
||||
conn.Nick(params.Nick)
|
||||
conn.Cmd.Nick(params.Nick)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
9
main.go
9
main.go
|
@ -13,10 +13,11 @@ import (
|
|||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/gobwas/glob"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/qaisjp/go-discord-irc/bridge"
|
||||
ircnick "github.com/qaisjp/go-discord-irc/irc/nick"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/qaisjp/go-discord-irc/bridge"
|
||||
ircnick "github.com/qaisjp/go-discord-irc/irc/nick"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -97,9 +98,6 @@ func main() {
|
|||
*insecure = viper.GetBool("insecure")
|
||||
}
|
||||
//
|
||||
viper.SetDefault("irc_puppet_prejoin_commands", []string{"MODE ${NICK} +D"})
|
||||
ircPuppetPrejoinCommands := viper.GetStringSlice("irc_puppet_prejoin_commands") // Commands for each connection to send before joining channels
|
||||
//
|
||||
viper.SetDefault("avatar_url", "https://robohash.org/${USERNAME}.png?set=set4")
|
||||
avatarURL := viper.GetString("avatar_url")
|
||||
//
|
||||
|
@ -153,7 +151,6 @@ func main() {
|
|||
IRCListenerName: ircUsername,
|
||||
IRCServer: ircServer,
|
||||
IRCServerPass: ircPassword,
|
||||
IRCPuppetPrejoinCommands: ircPuppetPrejoinCommands,
|
||||
IRCListenerPrejoinCommands: ircListenerPrejoinCommands,
|
||||
ConnectionLimit: connectionLimit,
|
||||
IRCIgnores: matchers,
|
||||
|
|
Loading…
Reference in New Issue