forked from lug/matterbridge
		
	Compare commits
	
		
			3 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | bb38a61f3b | ||
|   | c447647af9 | ||
|   | 1de64f3f61 | 
| @@ -54,7 +54,7 @@ See https://github.com/42wim/matterbridge/wiki | ||||
|  | ||||
| # Installing | ||||
| ## Binaries | ||||
| * Latest stable release [v1.6.3](https://github.com/42wim/matterbridge/releases/latest) | ||||
| * Latest stable release [v1.5.0](https://github.com/42wim/matterbridge/releases/latest) | ||||
| * Development releases (follows master) can be downloaded [here](https://dl.bintray.com/42wim/nightly/)   | ||||
|  | ||||
| ## Building | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| package api | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	log "github.com/Sirupsen/logrus" | ||||
| 	"github.com/labstack/echo" | ||||
| @@ -9,13 +8,14 @@ import ( | ||||
| 	"github.com/zfjagann/golang-ring" | ||||
| 	"net/http" | ||||
| 	"sync" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| type Api struct { | ||||
| 	Config   *config.Protocol | ||||
| 	Remote   chan config.Message | ||||
| 	Account  string | ||||
| 	Messages ring.Ring | ||||
| 	sync.RWMutex | ||||
| 	*config.BridgeConfig | ||||
| } | ||||
|  | ||||
| type ApiMessage struct { | ||||
| @@ -33,21 +33,23 @@ func init() { | ||||
| 	flog = log.WithFields(log.Fields{"module": protocol}) | ||||
| } | ||||
|  | ||||
| func New(cfg *config.BridgeConfig) *Api { | ||||
| 	b := &Api{BridgeConfig: cfg} | ||||
| func New(cfg config.Protocol, account string, c chan config.Message) *Api { | ||||
| 	b := &Api{} | ||||
| 	e := echo.New() | ||||
| 	b.Messages = ring.Ring{} | ||||
| 	b.Messages.SetCapacity(b.Config.Buffer) | ||||
| 	b.Messages.SetCapacity(cfg.Buffer) | ||||
| 	b.Config = &cfg | ||||
| 	b.Account = account | ||||
| 	b.Remote = c | ||||
| 	if b.Config.Token != "" { | ||||
| 		e.Use(middleware.KeyAuth(func(key string, c echo.Context) (bool, error) { | ||||
| 			return key == b.Config.Token, nil | ||||
| 		})) | ||||
| 	} | ||||
| 	e.GET("/api/messages", b.handleMessages) | ||||
| 	e.GET("/api/stream", b.handleStream) | ||||
| 	e.POST("/api/message", b.handlePostMessage) | ||||
| 	go func() { | ||||
| 		flog.Fatal(e.Start(b.Config.BindAddress)) | ||||
| 		flog.Fatal(e.Start(cfg.BindAddress)) | ||||
| 	}() | ||||
| 	return b | ||||
| } | ||||
| @@ -101,24 +103,3 @@ func (b *Api) handleMessages(c echo.Context) error { | ||||
| 	b.Messages = ring.Ring{} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Api) handleStream(c echo.Context) error { | ||||
| 	c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSON) | ||||
| 	c.Response().WriteHeader(http.StatusOK) | ||||
| 	closeNotifier := c.Response().CloseNotify() | ||||
| 	for { | ||||
| 		select { | ||||
| 		case <-closeNotifier: | ||||
| 			return nil | ||||
| 		default: | ||||
| 			msg := b.Messages.Dequeue() | ||||
| 			if msg != nil { | ||||
| 				if err := json.NewEncoder(c.Response()).Encode(msg); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				c.Response().Flush() | ||||
| 			} | ||||
| 			time.Sleep(200 * time.Millisecond) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -10,7 +10,6 @@ import ( | ||||
| 	"github.com/42wim/matterbridge/bridge/mattermost" | ||||
| 	"github.com/42wim/matterbridge/bridge/rocketchat" | ||||
| 	"github.com/42wim/matterbridge/bridge/slack" | ||||
| 	"github.com/42wim/matterbridge/bridge/sshchat" | ||||
| 	"github.com/42wim/matterbridge/bridge/steam" | ||||
| 	"github.com/42wim/matterbridge/bridge/telegram" | ||||
| 	"github.com/42wim/matterbridge/bridge/xmpp" | ||||
| @@ -46,49 +45,44 @@ func New(cfg *config.Config, bridge *config.Bridge, c chan config.Message) *Brid | ||||
| 	b.Protocol = protocol | ||||
| 	b.Account = bridge.Account | ||||
| 	b.Joined = make(map[string]bool) | ||||
| 	bridgeConfig := &config.BridgeConfig{General: &cfg.General, Account: bridge.Account, Remote: c} | ||||
|  | ||||
| 	// override config from environment | ||||
| 	config.OverrideCfgFromEnv(cfg, protocol, name) | ||||
| 	switch protocol { | ||||
| 	case "mattermost": | ||||
| 		bridgeConfig.Config = cfg.Mattermost[name] | ||||
| 		b.Bridger = bmattermost.New(bridgeConfig) | ||||
| 		b.Config = cfg.Mattermost[name] | ||||
| 		b.Bridger = bmattermost.New(cfg.Mattermost[name], bridge.Account, c) | ||||
| 	case "irc": | ||||
| 		bridgeConfig.Config = cfg.IRC[name] | ||||
| 		b.Bridger = birc.New(bridgeConfig) | ||||
| 		b.Config = cfg.IRC[name] | ||||
| 		b.Bridger = birc.New(cfg.IRC[name], bridge.Account, c) | ||||
| 	case "gitter": | ||||
| 		bridgeConfig.Config = cfg.Gitter[name] | ||||
| 		b.Bridger = bgitter.New(bridgeConfig) | ||||
| 		b.Config = cfg.Gitter[name] | ||||
| 		b.Bridger = bgitter.New(cfg.Gitter[name], bridge.Account, c) | ||||
| 	case "slack": | ||||
| 		bridgeConfig.Config = cfg.Slack[name] | ||||
| 		b.Bridger = bslack.New(bridgeConfig) | ||||
| 		b.Config = cfg.Slack[name] | ||||
| 		b.Bridger = bslack.New(cfg.Slack[name], bridge.Account, c) | ||||
| 	case "xmpp": | ||||
| 		bridgeConfig.Config = cfg.Xmpp[name] | ||||
| 		b.Bridger = bxmpp.New(bridgeConfig) | ||||
| 		b.Config = cfg.Xmpp[name] | ||||
| 		b.Bridger = bxmpp.New(cfg.Xmpp[name], bridge.Account, c) | ||||
| 	case "discord": | ||||
| 		bridgeConfig.Config = cfg.Discord[name] | ||||
| 		b.Bridger = bdiscord.New(bridgeConfig) | ||||
| 		b.Config = cfg.Discord[name] | ||||
| 		b.Bridger = bdiscord.New(cfg.Discord[name], bridge.Account, c) | ||||
| 	case "telegram": | ||||
| 		bridgeConfig.Config = cfg.Telegram[name] | ||||
| 		b.Bridger = btelegram.New(bridgeConfig) | ||||
| 		b.Config = cfg.Telegram[name] | ||||
| 		b.Bridger = btelegram.New(cfg.Telegram[name], bridge.Account, c) | ||||
| 	case "rocketchat": | ||||
| 		bridgeConfig.Config = cfg.Rocketchat[name] | ||||
| 		b.Bridger = brocketchat.New(bridgeConfig) | ||||
| 		b.Config = cfg.Rocketchat[name] | ||||
| 		b.Bridger = brocketchat.New(cfg.Rocketchat[name], bridge.Account, c) | ||||
| 	case "matrix": | ||||
| 		bridgeConfig.Config = cfg.Matrix[name] | ||||
| 		b.Bridger = bmatrix.New(bridgeConfig) | ||||
| 		b.Config = cfg.Matrix[name] | ||||
| 		b.Bridger = bmatrix.New(cfg.Matrix[name], bridge.Account, c) | ||||
| 	case "steam": | ||||
| 		bridgeConfig.Config = cfg.Steam[name] | ||||
| 		b.Bridger = bsteam.New(bridgeConfig) | ||||
| 	case "sshchat": | ||||
| 		bridgeConfig.Config = cfg.Sshchat[name] | ||||
| 		b.Bridger = bsshchat.New(bridgeConfig) | ||||
| 		b.Config = cfg.Steam[name] | ||||
| 		b.Bridger = bsteam.New(cfg.Steam[name], bridge.Account, c) | ||||
| 	case "api": | ||||
| 		bridgeConfig.Config = cfg.Api[name] | ||||
| 		b.Bridger = api.New(bridgeConfig) | ||||
| 		b.Config = cfg.Api[name] | ||||
| 		b.Bridger = api.New(cfg.Api[name], bridge.Account, c) | ||||
| 	} | ||||
| 	b.Config = bridgeConfig.Config | ||||
| 	return b | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -60,7 +60,6 @@ type Protocol struct { | ||||
| 	IgnoreMessages         string // all protocols | ||||
| 	Jid                    string // xmpp | ||||
| 	Login                  string // mattermost, matrix | ||||
| 	MediaDownloadSize      int    // all protocols | ||||
| 	MediaServerDownload    string | ||||
| 	MediaServerUpload      string | ||||
| 	MessageDelay           int        // IRC, time in millisecond to wait between messages | ||||
| @@ -81,7 +80,6 @@ type Protocol struct { | ||||
| 	Password               string     // IRC,mattermost,XMPP,matrix | ||||
| 	PrefixMessagesWithNick bool       // mattemost, slack | ||||
| 	Protocol               string     // all protocols | ||||
| 	RejoinDelay            int        // IRC | ||||
| 	ReplaceMessages        [][]string // all protocols | ||||
| 	ReplaceNicks           [][]string // all protocols | ||||
| 	RemoteNickFormat       string     // all protocols | ||||
| @@ -143,19 +141,11 @@ type Config struct { | ||||
| 	Discord            map[string]Protocol | ||||
| 	Telegram           map[string]Protocol | ||||
| 	Rocketchat         map[string]Protocol | ||||
| 	Sshchat            map[string]Protocol | ||||
| 	General            Protocol | ||||
| 	Gateway            []Gateway | ||||
| 	SameChannelGateway []SameChannelGateway | ||||
| } | ||||
|  | ||||
| type BridgeConfig struct { | ||||
| 	Config  Protocol | ||||
| 	General *Protocol | ||||
| 	Account string | ||||
| 	Remote  chan Message | ||||
| } | ||||
|  | ||||
| func NewConfig(cfgfile string) *Config { | ||||
| 	var cfg Config | ||||
| 	if _, err := toml.DecodeFile(cfgfile, &cfg); err != nil { | ||||
| @@ -183,9 +173,6 @@ func NewConfig(cfgfile string) *Config { | ||||
| 	if fail { | ||||
| 		log.Fatalf("Fix your config. Please see changelog for more information") | ||||
| 	} | ||||
| 	if cfg.General.MediaDownloadSize == 0 { | ||||
| 		cfg.General.MediaDownloadSize = 1000000 | ||||
| 	} | ||||
| 	return &cfg | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -12,6 +12,9 @@ import ( | ||||
|  | ||||
| type bdiscord struct { | ||||
| 	c              *discordgo.Session | ||||
| 	Config         *config.Protocol | ||||
| 	Remote         chan config.Message | ||||
| 	Account        string | ||||
| 	Channels       []*discordgo.Channel | ||||
| 	Nick           string | ||||
| 	UseChannelID   bool | ||||
| @@ -21,7 +24,6 @@ type bdiscord struct { | ||||
| 	webhookToken   string | ||||
| 	channelInfoMap map[string]*config.ChannelInfo | ||||
| 	sync.RWMutex | ||||
| 	*config.BridgeConfig | ||||
| } | ||||
|  | ||||
| var flog *log.Entry | ||||
| @@ -31,8 +33,11 @@ func init() { | ||||
| 	flog = log.WithFields(log.Fields{"module": protocol}) | ||||
| } | ||||
|  | ||||
| func New(cfg *config.BridgeConfig) *bdiscord { | ||||
| 	b := &bdiscord{BridgeConfig: cfg} | ||||
| func New(cfg config.Protocol, account string, c chan config.Message) *bdiscord { | ||||
| 	b := &bdiscord{} | ||||
| 	b.Config = &cfg | ||||
| 	b.Remote = c | ||||
| 	b.Account = account | ||||
| 	b.userMemberMap = make(map[string]*discordgo.Member) | ||||
| 	b.channelInfoMap = make(map[string]*config.ChannelInfo) | ||||
| 	if b.Config.WebhookURL != "" { | ||||
|   | ||||
| @@ -10,10 +10,12 @@ import ( | ||||
|  | ||||
| type Bgitter struct { | ||||
| 	c       *gitter.Gitter | ||||
| 	Config  *config.Protocol | ||||
| 	Remote  chan config.Message | ||||
| 	Account string | ||||
| 	User    *gitter.User | ||||
| 	Users   []gitter.User | ||||
| 	Rooms   []gitter.Room | ||||
| 	*config.BridgeConfig | ||||
| } | ||||
|  | ||||
| var flog *log.Entry | ||||
| @@ -23,8 +25,12 @@ func init() { | ||||
| 	flog = log.WithFields(log.Fields{"module": protocol}) | ||||
| } | ||||
|  | ||||
| func New(cfg *config.BridgeConfig) *Bgitter { | ||||
| 	return &Bgitter{BridgeConfig: cfg} | ||||
| func New(cfg config.Protocol, account string, c chan config.Message) *Bgitter { | ||||
| 	b := &Bgitter{} | ||||
| 	b.Config = &cfg | ||||
| 	b.Remote = c | ||||
| 	b.Account = account | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| func (b *Bgitter) Connect() error { | ||||
|   | ||||
| @@ -25,11 +25,12 @@ type Birc struct { | ||||
| 	i               *girc.Client | ||||
| 	Nick            string | ||||
| 	names           map[string][]string | ||||
| 	Config          *config.Protocol | ||||
| 	Remote          chan config.Message | ||||
| 	connected       chan struct{} | ||||
| 	Local           chan config.Message // local queue for flood control | ||||
| 	Account         string | ||||
| 	FirstConnection bool | ||||
|  | ||||
| 	*config.BridgeConfig | ||||
| } | ||||
|  | ||||
| var flog *log.Entry | ||||
| @@ -39,11 +40,13 @@ func init() { | ||||
| 	flog = log.WithFields(log.Fields{"module": protocol}) | ||||
| } | ||||
|  | ||||
| func New(cfg *config.BridgeConfig) *Birc { | ||||
| func New(cfg config.Protocol, account string, c chan config.Message) *Birc { | ||||
| 	b := &Birc{} | ||||
| 	b.BridgeConfig = cfg | ||||
| 	b.Config = &cfg | ||||
| 	b.Nick = b.Config.Nick | ||||
| 	b.Remote = c | ||||
| 	b.names = make(map[string][]string) | ||||
| 	b.Account = account | ||||
| 	b.connected = make(chan struct{}) | ||||
| 	if b.Config.MessageDelay == 0 { | ||||
| 		b.Config.MessageDelay = 1300 | ||||
| @@ -267,7 +270,6 @@ func (b *Birc) handleJoinPart(client *girc.Client, event girc.Event) { | ||||
| 	channel := event.Params[0] | ||||
| 	if event.Command == "KICK" { | ||||
| 		flog.Infof("Got kicked from %s by %s", channel, event.Source.Name) | ||||
| 		time.Sleep(time.Duration(b.Config.RejoinDelay) * time.Second) | ||||
| 		b.Remote <- config.Message{Username: "system", Text: "rejoin", Channel: channel, Account: b.Account, Event: config.EVENT_REJOIN_CHANNELS} | ||||
| 		return | ||||
| 	} | ||||
| @@ -323,7 +325,7 @@ func (b *Birc) handlePrivMsg(client *girc.Client, event girc.Event) { | ||||
| 	if event.Source.Name == b.Nick { | ||||
| 		return | ||||
| 	} | ||||
| 	rmsg := config.Message{Username: event.Source.Name, Channel: strings.ToLower(event.Params[0]), Account: b.Account, UserID: event.Source.Ident + "@" + event.Source.Host} | ||||
| 	rmsg := config.Message{Username: event.Source.Name, Channel: event.Params[0], Account: b.Account, UserID: event.Source.Ident + "@" + event.Source.Host} | ||||
| 	flog.Debugf("handlePrivMsg() %s %s %#v", event.Source.Name, event.Trailing, event) | ||||
| 	msg := "" | ||||
| 	if event.IsAction() { | ||||
|   | ||||
| @@ -15,10 +15,12 @@ import ( | ||||
|  | ||||
| type Bmatrix struct { | ||||
| 	mc      *matrix.Client | ||||
| 	Config  *config.Protocol | ||||
| 	Remote  chan config.Message | ||||
| 	Account string | ||||
| 	UserID  string | ||||
| 	RoomMap map[string]string | ||||
| 	sync.RWMutex | ||||
| 	*config.BridgeConfig | ||||
| } | ||||
|  | ||||
| var flog *log.Entry | ||||
| @@ -28,9 +30,12 @@ func init() { | ||||
| 	flog = log.WithFields(log.Fields{"module": protocol}) | ||||
| } | ||||
|  | ||||
| func New(cfg *config.BridgeConfig) *Bmatrix { | ||||
| 	b := &Bmatrix{BridgeConfig: cfg} | ||||
| func New(cfg config.Protocol, account string, c chan config.Message) *Bmatrix { | ||||
| 	b := &Bmatrix{} | ||||
| 	b.RoomMap = make(map[string]string) | ||||
| 	b.Config = &cfg | ||||
| 	b.Account = account | ||||
| 	b.Remote = c | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| @@ -101,7 +106,6 @@ func (b *Bmatrix) Send(msg config.Message) (string, error) { | ||||
| 					res, err := b.mc.UploadToContentRepo(content, mtype, int64(len(*fi.Data))) | ||||
| 					if err != nil { | ||||
| 						flog.Errorf("file upload failed: %#v", err) | ||||
| 						continue | ||||
| 					} | ||||
| 					if strings.Contains(mtype, "video") { | ||||
| 						flog.Debugf("sendVideo %s", res.ContentURI) | ||||
| @@ -175,7 +179,7 @@ func (b *Bmatrix) handlematrix() error { | ||||
| 				size := info["size"].(float64) | ||||
| 				name := ev.Content["body"].(string) | ||||
| 				flog.Debugf("trying to download %#v with size %#v", name, size) | ||||
| 				if size <= float64(b.General.MediaDownloadSize) { | ||||
| 				if size <= 1000000 { | ||||
| 					data, err := helper.DownloadFile(url) | ||||
| 					if err != nil { | ||||
| 						flog.Errorf("download %s failed %#v", url, err) | ||||
|   | ||||
| @@ -32,8 +32,10 @@ type MMMessage struct { | ||||
| type Bmattermost struct { | ||||
| 	MMhook | ||||
| 	MMapi | ||||
| 	Config  *config.Protocol | ||||
| 	Remote  chan config.Message | ||||
| 	TeamId  string | ||||
| 	*config.BridgeConfig | ||||
| 	Account string | ||||
| } | ||||
|  | ||||
| var flog *log.Entry | ||||
| @@ -43,8 +45,11 @@ func init() { | ||||
| 	flog = log.WithFields(log.Fields{"module": protocol}) | ||||
| } | ||||
|  | ||||
| func New(cfg *config.BridgeConfig) *Bmattermost { | ||||
| 	b := &Bmattermost{BridgeConfig: cfg} | ||||
| func New(cfg config.Protocol, account string, c chan config.Message) *Bmattermost { | ||||
| 	b := &Bmattermost{} | ||||
| 	b.Config = &cfg | ||||
| 	b.Remote = c | ||||
| 	b.Account = account | ||||
| 	b.mmMap = make(map[string]string) | ||||
| 	return b | ||||
| } | ||||
|   | ||||
| @@ -14,7 +14,9 @@ type MMhook struct { | ||||
|  | ||||
| type Brocketchat struct { | ||||
| 	MMhook | ||||
| 	*config.BridgeConfig | ||||
| 	Config  *config.Protocol | ||||
| 	Remote  chan config.Message | ||||
| 	Account string | ||||
| } | ||||
|  | ||||
| var flog *log.Entry | ||||
| @@ -24,8 +26,12 @@ func init() { | ||||
| 	flog = log.WithFields(log.Fields{"module": protocol}) | ||||
| } | ||||
|  | ||||
| func New(cfg *config.BridgeConfig) *Brocketchat { | ||||
| 	return &Brocketchat{BridgeConfig: cfg} | ||||
| func New(cfg config.Protocol, account string, c chan config.Message) *Brocketchat { | ||||
| 	b := &Brocketchat{} | ||||
| 	b.Config = &cfg | ||||
| 	b.Remote = c | ||||
| 	b.Account = account | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| func (b *Brocketchat) Command(cmd string) string { | ||||
|   | ||||
| @@ -7,7 +7,7 @@ import ( | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	"github.com/42wim/matterbridge/matterhook" | ||||
| 	log "github.com/Sirupsen/logrus" | ||||
| 	"github.com/nlopes/slack" | ||||
| 	"github.com/matterbridge/slack" | ||||
| 	"html" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| @@ -27,12 +27,14 @@ type MMMessage struct { | ||||
| type Bslack struct { | ||||
| 	mh       *matterhook.Client | ||||
| 	sc       *slack.Client | ||||
| 	Config   *config.Protocol | ||||
| 	rtm      *slack.RTM | ||||
| 	Plus     bool | ||||
| 	Remote   chan config.Message | ||||
| 	Users    []slack.User | ||||
| 	Account  string | ||||
| 	si       *slack.Info | ||||
| 	channels []slack.Channel | ||||
| 	*config.BridgeConfig | ||||
| } | ||||
|  | ||||
| var flog *log.Entry | ||||
| @@ -42,8 +44,12 @@ func init() { | ||||
| 	flog = log.WithFields(log.Fields{"module": protocol}) | ||||
| } | ||||
|  | ||||
| func New(cfg *config.BridgeConfig) *Bslack { | ||||
| 	return &Bslack{BridgeConfig: cfg} | ||||
| func New(cfg config.Protocol, account string, c chan config.Message) *Bslack { | ||||
| 	b := &Bslack{} | ||||
| 	b.Config = &cfg | ||||
| 	b.Remote = c | ||||
| 	b.Account = account | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| func (b *Bslack) Command(cmd string) string { | ||||
| @@ -107,7 +113,7 @@ func (b *Bslack) Disconnect() error { | ||||
|  | ||||
| func (b *Bslack) JoinChannel(channel config.ChannelInfo) error { | ||||
| 	// we can only join channels using the API | ||||
| 	if b.sc != nil { | ||||
| 	if b.Config.WebhookURL == "" && b.Config.WebhookBindAddress == "" { | ||||
| 		if strings.HasPrefix(b.Config.Token, "xoxb") { | ||||
| 			// TODO check if bot has already joined channel | ||||
| 			return nil | ||||
| @@ -155,7 +161,7 @@ func (b *Bslack) Send(msg config.Message) (string, error) { | ||||
| 		np.AsUser = true | ||||
| 	} | ||||
| 	np.Username = nick | ||||
| 	np.IconURL = config.GetIconURL(&msg, &b.Config) | ||||
| 	np.IconURL = config.GetIconURL(&msg, b.Config) | ||||
| 	if msg.Avatar != "" { | ||||
| 		np.IconURL = msg.Avatar | ||||
| 	} | ||||
| @@ -288,7 +294,7 @@ func (b *Bslack) handleSlack() { | ||||
| 		// if we have a file attached, download it (in memory) and put a pointer to it in msg.Extra | ||||
| 		if message.Raw.File != nil { | ||||
| 			// limit to 1MB for now | ||||
| 			if message.Raw.File.Size <= b.General.MediaDownloadSize { | ||||
| 			if message.Raw.File.Size <= 1000000 { | ||||
| 				comment := "" | ||||
| 				data, err := b.downloadFile(message.Raw.File.URLPrivateDownload) | ||||
| 				if err != nil { | ||||
| @@ -309,11 +315,9 @@ func (b *Bslack) handleSlack() { | ||||
|  | ||||
| func (b *Bslack) handleSlackClient(mchan chan *MMMessage) { | ||||
| 	for msg := range b.rtm.IncomingEvents { | ||||
| 		if msg.Type != "user_typing" && msg.Type != "latency_report" { | ||||
| 			flog.Debugf("Receiving from slackclient %#v", msg.Data) | ||||
| 		} | ||||
| 		switch ev := msg.Data.(type) { | ||||
| 		case *slack.MessageEvent: | ||||
| 			flog.Debugf("Receiving from slackclient %#v", ev) | ||||
| 			if len(ev.Attachments) > 0 { | ||||
| 				// skip messages we made ourselves | ||||
| 				if ev.Attachments[0].CallbackID == "matterbridge" { | ||||
| @@ -396,8 +400,6 @@ func (b *Bslack) handleSlackClient(mchan chan *MMMessage) { | ||||
| 			} | ||||
| 		case *slack.InvalidAuthEvent: | ||||
| 			flog.Fatalf("Invalid Token %#v", ev) | ||||
| 		case *slack.ConnectionErrorEvent: | ||||
| 			flog.Errorf("Connection failed %#v %#v", ev.Error(), ev.ErrorObj) | ||||
| 		default: | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -1,132 +0,0 @@ | ||||
| package bsshchat | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"github.com/42wim/matterbridge/bridge/config" | ||||
| 	log "github.com/Sirupsen/logrus" | ||||
| 	"github.com/shazow/ssh-chat/sshd" | ||||
| 	"io" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type Bsshchat struct { | ||||
| 	r *bufio.Scanner | ||||
| 	w io.WriteCloser | ||||
| 	*config.BridgeConfig | ||||
| } | ||||
|  | ||||
| var flog *log.Entry | ||||
| var protocol = "sshchat" | ||||
|  | ||||
| func init() { | ||||
| 	flog = log.WithFields(log.Fields{"module": protocol}) | ||||
| } | ||||
|  | ||||
| func New(cfg *config.BridgeConfig) *Bsshchat { | ||||
| 	return &Bsshchat{BridgeConfig: cfg} | ||||
| } | ||||
|  | ||||
| func (b *Bsshchat) Connect() error { | ||||
| 	var err error | ||||
| 	flog.Infof("Connecting %s", b.Config.Server) | ||||
| 	go func() { | ||||
| 		err = sshd.ConnectShell(b.Config.Server, b.Config.Nick, func(r io.Reader, w io.WriteCloser) error { | ||||
| 			b.r = bufio.NewScanner(r) | ||||
| 			b.w = w | ||||
| 			b.r.Scan() | ||||
| 			w.Write([]byte("/theme mono\r\n")) | ||||
| 			b.handleSshChat() | ||||
| 			return nil | ||||
| 		}) | ||||
| 	}() | ||||
| 	if err != nil { | ||||
| 		flog.Debugf("%#v", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	flog.Info("Connection succeeded") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bsshchat) Disconnect() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bsshchat) JoinChannel(channel config.ChannelInfo) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (b *Bsshchat) Send(msg config.Message) (string, error) { | ||||
| 	// ignore delete messages | ||||
| 	if msg.Event == config.EVENT_MSG_DELETE { | ||||
| 		return "", nil | ||||
| 	} | ||||
| 	flog.Debugf("Receiving %#v", msg) | ||||
| 	if msg.Extra != nil { | ||||
| 		if len(msg.Extra["file"]) > 0 { | ||||
| 			for _, f := range msg.Extra["file"] { | ||||
| 				fi := f.(config.FileInfo) | ||||
| 				if fi.URL != "" { | ||||
| 					msg.Text = fi.URL | ||||
| 				} | ||||
| 				b.w.Write([]byte(msg.Username + msg.Text)) | ||||
| 			} | ||||
| 			return "", nil | ||||
| 		} | ||||
| 	} | ||||
| 	b.w.Write([]byte(msg.Username + msg.Text + "\r\n")) | ||||
| 	return "", nil | ||||
| } | ||||
|  | ||||
| /* | ||||
| func (b *Bsshchat) sshchatKeepAlive() chan bool { | ||||
| 	done := make(chan bool) | ||||
| 	go func() { | ||||
| 		ticker := time.NewTicker(90 * time.Second) | ||||
| 		defer ticker.Stop() | ||||
| 		for { | ||||
| 			select { | ||||
| 			case <-ticker.C: | ||||
| 				flog.Debugf("PING") | ||||
| 				err := b.xc.PingC2S("", "") | ||||
| 				if err != nil { | ||||
| 					flog.Debugf("PING failed %#v", err) | ||||
| 				} | ||||
| 			case <-done: | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
| 	return done | ||||
| } | ||||
| */ | ||||
|  | ||||
| func stripPrompt(s string) string { | ||||
| 	pos := strings.LastIndex(s, "\033[K") | ||||
| 	if pos < 0 { | ||||
| 		return s | ||||
| 	} | ||||
| 	return s[pos+3:] | ||||
| } | ||||
|  | ||||
| func (b *Bsshchat) handleSshChat() error { | ||||
| 	/* | ||||
| 		done := b.sshchatKeepAlive() | ||||
| 		defer close(done) | ||||
| 	*/ | ||||
| 	wait := true | ||||
| 	for { | ||||
| 		if b.r.Scan() { | ||||
| 			res := strings.Split(stripPrompt(b.r.Text()), ":") | ||||
| 			if res[0] == "-> Set theme" { | ||||
| 				wait = false | ||||
| 				log.Debugf("mono found, allowing") | ||||
| 				continue | ||||
| 			} | ||||
| 			if !wait { | ||||
| 				flog.Debugf("message %#v", res) | ||||
| 				rmsg := config.Message{Username: res[0], Text: strings.Join(res[1:], ":"), Channel: "sshchat", Account: b.Account, UserID: "nick"} | ||||
| 				b.Remote <- rmsg | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -16,9 +16,11 @@ import ( | ||||
| type Bsteam struct { | ||||
| 	c         *steam.Client | ||||
| 	connected chan struct{} | ||||
| 	Config    *config.Protocol | ||||
| 	Remote    chan config.Message | ||||
| 	Account   string | ||||
| 	userMap   map[steamid.SteamId]string | ||||
| 	sync.RWMutex | ||||
| 	*config.BridgeConfig | ||||
| } | ||||
|  | ||||
| var flog *log.Entry | ||||
| @@ -28,8 +30,11 @@ func init() { | ||||
| 	flog = log.WithFields(log.Fields{"module": protocol}) | ||||
| } | ||||
|  | ||||
| func New(cfg *config.BridgeConfig) *Bsteam { | ||||
| 	b := &Bsteam{BridgeConfig: cfg} | ||||
| func New(cfg config.Protocol, account string, c chan config.Message) *Bsteam { | ||||
| 	b := &Bsteam{} | ||||
| 	b.Config = &cfg | ||||
| 	b.Remote = c | ||||
| 	b.Account = account | ||||
| 	b.userMap = make(map[steamid.SteamId]string) | ||||
| 	b.connected = make(chan struct{}) | ||||
| 	return b | ||||
|   | ||||
| @@ -13,7 +13,9 @@ import ( | ||||
|  | ||||
| type Btelegram struct { | ||||
| 	c       *tgbotapi.BotAPI | ||||
| 	*config.BridgeConfig | ||||
| 	Config  *config.Protocol | ||||
| 	Remote  chan config.Message | ||||
| 	Account string | ||||
| } | ||||
|  | ||||
| var flog *log.Entry | ||||
| @@ -23,8 +25,12 @@ func init() { | ||||
| 	flog = log.WithFields(log.Fields{"module": protocol}) | ||||
| } | ||||
|  | ||||
| func New(cfg *config.BridgeConfig) *Btelegram { | ||||
| 	return &Btelegram{BridgeConfig: cfg} | ||||
| func New(cfg config.Protocol, account string, c chan config.Message) *Btelegram { | ||||
| 	b := &Btelegram{} | ||||
| 	b.Config = &cfg | ||||
| 	b.Remote = c | ||||
| 	b.Account = account | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| func (b *Btelegram) Connect() error { | ||||
| @@ -84,9 +90,6 @@ func (b *Btelegram) Send(msg config.Message) (string, error) { | ||||
| 			return "", err | ||||
| 		} | ||||
| 		m := tgbotapi.NewEditMessageText(chatid, msgid, msg.Username+msg.Text) | ||||
| 		if b.Config.MessageFormat == "HTML" { | ||||
| 			m.ParseMode = tgbotapi.ModeHTML | ||||
| 		} | ||||
| 		_, err = b.c.Send(m) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| @@ -176,29 +179,6 @@ func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) { | ||||
| 		if message.Document != nil { | ||||
| 			b.handleDownload(message.Document, &fmsg) | ||||
| 		} | ||||
| 		if message.Voice != nil { | ||||
| 			b.handleDownload(message.Voice, &fmsg) | ||||
| 		} | ||||
| 		if message.Audio != nil { | ||||
| 			b.handleDownload(message.Audio, &fmsg) | ||||
| 		} | ||||
|  | ||||
| 		if message.ForwardFrom != nil { | ||||
| 			usernameForward := "" | ||||
| 			if b.Config.UseFirstName { | ||||
| 				usernameForward = message.ForwardFrom.FirstName | ||||
| 			} | ||||
| 			if usernameForward == "" { | ||||
| 				usernameForward = message.ForwardFrom.UserName | ||||
| 				if usernameForward == "" { | ||||
| 					usernameForward = message.ForwardFrom.FirstName | ||||
| 				} | ||||
| 			} | ||||
| 			if usernameForward == "" { | ||||
| 				usernameForward = "unknown" | ||||
| 			} | ||||
| 			text = "Forwarded from " + usernameForward + ": " + text | ||||
| 		} | ||||
|  | ||||
| 		// quote the previous message | ||||
| 		if message.ReplyToMessage != nil { | ||||
| @@ -244,23 +224,6 @@ func (b *Btelegram) handleDownload(file interface{}, msg *config.Message) { | ||||
| 	text := "" | ||||
| 	fileid := "" | ||||
| 	switch v := file.(type) { | ||||
| 	case *tgbotapi.Audio: | ||||
| 		size = v.FileSize | ||||
| 		url = b.getFileDirectURL(v.FileID) | ||||
| 		urlPart := strings.Split(url, "/") | ||||
| 		name = urlPart[len(urlPart)-1] | ||||
| 		text = " " + url | ||||
| 		fileid = v.FileID | ||||
| 	case *tgbotapi.Voice: | ||||
| 		size = v.FileSize | ||||
| 		url = b.getFileDirectURL(v.FileID) | ||||
| 		urlPart := strings.Split(url, "/") | ||||
| 		name = urlPart[len(urlPart)-1] | ||||
| 		text = " " + url | ||||
| 		if !strings.HasSuffix(name, ".ogg") { | ||||
| 			name = name + ".ogg" | ||||
| 		} | ||||
| 		fileid = v.FileID | ||||
| 	case *tgbotapi.Sticker: | ||||
| 		size = v.FileSize | ||||
| 		url = b.getFileDirectURL(v.FileID) | ||||
| @@ -299,7 +262,7 @@ func (b *Btelegram) handleDownload(file interface{}, msg *config.Message) { | ||||
| 	// if we have a file attached, download it (in memory) and put a pointer to it in msg.Extra | ||||
| 	// limit to 1MB for now | ||||
| 	flog.Debugf("trying to download %#v fileid %#v with size %#v", name, fileid, size) | ||||
| 	if size <= b.General.MediaDownloadSize { | ||||
| 	if size <= 1000000 { | ||||
| 		data, err := helper.DownloadFile(url) | ||||
| 		if err != nil { | ||||
| 			flog.Errorf("download %s failed %#v", url, err) | ||||
|   | ||||
| @@ -14,7 +14,9 @@ import ( | ||||
| type Bxmpp struct { | ||||
| 	xc      *xmpp.Client | ||||
| 	xmppMap map[string]string | ||||
| 	*config.BridgeConfig | ||||
| 	Config  *config.Protocol | ||||
| 	Remote  chan config.Message | ||||
| 	Account string | ||||
| } | ||||
|  | ||||
| var flog *log.Entry | ||||
| @@ -24,9 +26,12 @@ func init() { | ||||
| 	flog = log.WithFields(log.Fields{"module": protocol}) | ||||
| } | ||||
|  | ||||
| func New(cfg *config.BridgeConfig) *Bxmpp { | ||||
| 	b := &Bxmpp{BridgeConfig: cfg} | ||||
| func New(cfg config.Protocol, account string, c chan config.Message) *Bxmpp { | ||||
| 	b := &Bxmpp{} | ||||
| 	b.xmppMap = make(map[string]string) | ||||
| 	b.Config = &cfg | ||||
| 	b.Account = account | ||||
| 	b.Remote = c | ||||
| 	return b | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										33
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								changelog.md
									
									
									
									
									
								
							| @@ -1,36 +1,3 @@ | ||||
| # v1.6.3 | ||||
| ## Bugfix | ||||
| * slack: Fix connection issues | ||||
| * slack: Add more debug messages | ||||
| * irc: Convert received IRC channel names to lowercase. Fixes #329 (#330) | ||||
|  | ||||
| # v1.6.2 | ||||
| ## Bugfix | ||||
| * mattermost: Crashes while connecting to Mattermost (regression). Closes #327 | ||||
|  | ||||
| # v1.6.1 | ||||
| ## Bugfix | ||||
| * general: Display of nicks not longer working (regression). Closes #323 | ||||
|  | ||||
| # v1.6.0 | ||||
| ## New features | ||||
| * sshchat: New protocol support added (https://github.com/shazow/ssh-chat) | ||||
| * general: Allow specifying maximum download size of media using MediaDownloadSize (slack,telegram,matrix) | ||||
| * api: Add (simple, one listener) long-polling support (api). Closes #307 | ||||
| * telegram: Add support for forwarded messages. Closes #313 | ||||
| * telegram: Add support for Audio/Voice files (telegram). Closes #314 | ||||
| * irc: Add RejoinDelay option. Delay to rejoin after channel kick (irc). Closes #322 | ||||
|  | ||||
| ## Bugfix | ||||
| * telegram: Also use HTML in edited messages (telegram). Closes #315 | ||||
| * matrix: Fix panic (matrix). Closes #316 | ||||
|  | ||||
| # v1.5.1 | ||||
|  | ||||
| ## Bugfix | ||||
| * irc: Fix irc ACTION regression (irc). Closes #306 | ||||
| * irc: Split on UTF-8 for MessageSplit (irc). Closes #308 | ||||
|  | ||||
| # v1.5.0 | ||||
| ## New features | ||||
| * general: remote mediaserver support. See MediaServerDownload and MediaServerUpload in matterbridge.toml.sample | ||||
|   | ||||
| @@ -12,7 +12,7 @@ import ( | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	version = "1.6.3" | ||||
| 	version = "1.5.1" | ||||
| 	githash string | ||||
| ) | ||||
|  | ||||
|   | ||||
| @@ -85,10 +85,6 @@ MessageLength=400 | ||||
| #OPTIONAL (default false) | ||||
| MessageSplit=false | ||||
|  | ||||
| #Delay in seconds to rejoin a channel when kicked | ||||
| #OPTIONAL (default 0) | ||||
| RejoinDelay=0 | ||||
|  | ||||
| #Nicks you want to ignore.  | ||||
| #Messages from those users will not be sent to other bridges. | ||||
| #OPTIONAL | ||||
| @@ -1048,15 +1044,6 @@ MediaServerUpload="https://user:pass@yourserver.com/upload" | ||||
| #OPTIONAL (default empty) | ||||
| MediaServerDownload="https://youserver.com/download" | ||||
|  | ||||
| #MediaDownloadSize is the maximum size of attachments, videos, images | ||||
| #matterbridge will download and upload this file to bridges that also support uploading files. | ||||
| #eg downloading from slack to upload it to mattermost | ||||
| # | ||||
| #It will only download from bridges that don't have public links available, which are for the moment | ||||
| #slack, telegram and matrix | ||||
| # | ||||
| #Optional (default 1000000 (1 megabyte)) | ||||
| MediaDownloadSize=1000000 | ||||
|  | ||||
| ################################################################### | ||||
| #Gateway configuration | ||||
|   | ||||
							
								
								
									
										11
									
								
								vendor/github.com/labstack/echo/context.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/labstack/echo/context.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -494,9 +494,14 @@ func (c *context) Stream(code int, contentType string, r io.Reader) (err error) | ||||
| } | ||||
|  | ||||
| func (c *context) File(file string) (err error) { | ||||
| 	file, err = url.QueryUnescape(file) // Issue #839 | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	f, err := os.Open(file) | ||||
| 	if err != nil { | ||||
| 		return NotFoundHandler(c) | ||||
| 		return ErrNotFound | ||||
| 	} | ||||
| 	defer f.Close() | ||||
|  | ||||
| @@ -505,7 +510,7 @@ func (c *context) File(file string) (err error) { | ||||
| 		file = filepath.Join(file, indexPage) | ||||
| 		f, err = os.Open(file) | ||||
| 		if err != nil { | ||||
| 			return NotFoundHandler(c) | ||||
| 			return ErrNotFound | ||||
| 		} | ||||
| 		defer f.Close() | ||||
| 		if fi, err = f.Stat(); err != nil { | ||||
| @@ -525,7 +530,7 @@ func (c *context) Inline(file, name string) (err error) { | ||||
| } | ||||
|  | ||||
| func (c *context) contentDisposition(file, name, dispositionType string) (err error) { | ||||
| 	c.response.Header().Set(HeaderContentDisposition, fmt.Sprintf("%s; filename=%q", dispositionType, name)) | ||||
| 	c.response.Header().Set(HeaderContentDisposition, fmt.Sprintf("%s; filename=%s", dispositionType, name)) | ||||
| 	c.File(file) | ||||
| 	return | ||||
| } | ||||
|   | ||||
							
								
								
									
										128
									
								
								vendor/github.com/labstack/echo/echo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										128
									
								
								vendor/github.com/labstack/echo/echo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -72,7 +72,6 @@ type ( | ||||
| 		TLSServer        *http.Server | ||||
| 		Listener         net.Listener | ||||
| 		TLSListener      net.Listener | ||||
| 		AutoTLSManager   autocert.Manager | ||||
| 		DisableHTTP2     bool | ||||
| 		Debug            bool | ||||
| 		HideBanner       bool | ||||
| @@ -80,6 +79,7 @@ type ( | ||||
| 		Binder           Binder | ||||
| 		Validator        Validator | ||||
| 		Renderer         Renderer | ||||
| 		AutoTLSManager   autocert.Manager | ||||
| 		// Mutex            sync.RWMutex | ||||
| 		Logger Logger | ||||
| 	} | ||||
| @@ -88,14 +88,13 @@ type ( | ||||
| 	Route struct { | ||||
| 		Method  string `json:"method"` | ||||
| 		Path    string `json:"path"` | ||||
| 		Name   string `json:"name"` | ||||
| 		Handler string `json:"handler"` | ||||
| 	} | ||||
|  | ||||
| 	// HTTPError represents an error that occurred while handling a request. | ||||
| 	HTTPError struct { | ||||
| 		Code    int | ||||
| 		Message interface{} | ||||
| 		Inner   error // Stores the error returned by an external dependency | ||||
| 	} | ||||
|  | ||||
| 	// MiddlewareFunc defines a function to process middleware. | ||||
| @@ -122,7 +121,7 @@ type ( | ||||
|  | ||||
| 	// i is the interface for Echo and Group. | ||||
| 	i interface { | ||||
| 		GET(string, HandlerFunc, ...MiddlewareFunc) *Route | ||||
| 		GET(string, HandlerFunc, ...MiddlewareFunc) | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| @@ -213,7 +212,7 @@ const ( | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	version = "3.2.5" | ||||
| 	version = "3.1.0" | ||||
| 	website = "https://echo.labstack.com" | ||||
| 	// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo | ||||
| 	banner = ` | ||||
| @@ -283,7 +282,7 @@ func New() (e *Echo) { | ||||
| 	e.TLSServer.Handler = e | ||||
| 	e.HTTPErrorHandler = e.DefaultHTTPErrorHandler | ||||
| 	e.Binder = &DefaultBinder{} | ||||
| 	e.Logger.SetLevel(log.ERROR) | ||||
| 	e.Logger.SetLevel(log.OFF) | ||||
| 	e.stdLogger = stdLog.New(e.Logger.Output(), e.Logger.Prefix()+": ", 0) | ||||
| 	e.pool.New = func() interface{} { | ||||
| 		return e.NewContext(nil, nil) | ||||
| @@ -320,9 +319,6 @@ func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) { | ||||
| 	if he, ok := err.(*HTTPError); ok { | ||||
| 		code = he.Code | ||||
| 		msg = he.Message | ||||
| 		if he.Inner != nil { | ||||
| 			msg = fmt.Sprintf("%v, %v", err, he.Inner) | ||||
| 		} | ||||
| 	} else if e.Debug { | ||||
| 		msg = err.Error() | ||||
| 	} else { | ||||
| @@ -332,20 +328,20 @@ func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) { | ||||
| 		msg = Map{"message": msg} | ||||
| 	} | ||||
|  | ||||
| 	e.Logger.Error(err) | ||||
|  | ||||
| 	// Send response | ||||
| 	if !c.Response().Committed { | ||||
| 		if c.Request().Method == HEAD { // Issue #608 | ||||
| 			err = c.NoContent(code) | ||||
| 			if err := c.NoContent(code); err != nil { | ||||
| 				goto ERROR | ||||
| 			} | ||||
| 		} else { | ||||
| 			err = c.JSON(code, msg) | ||||
| 			if err := c.JSON(code, msg); err != nil { | ||||
| 				goto ERROR | ||||
| 			} | ||||
| 		if err != nil { | ||||
| 		} | ||||
| 	} | ||||
| ERROR: | ||||
| 	e.Logger.Error(err) | ||||
| } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Pre adds middleware to the chain which is run before router. | ||||
| func (e *Echo) Pre(middleware ...MiddlewareFunc) { | ||||
| @@ -359,114 +355,104 @@ func (e *Echo) Use(middleware ...MiddlewareFunc) { | ||||
|  | ||||
| // CONNECT registers a new CONNECT route for a path with matching handler in the | ||||
| // router with optional route-level middleware. | ||||
| func (e *Echo) CONNECT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return e.Add(CONNECT, path, h, m...) | ||||
| func (e *Echo) CONNECT(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	e.add(CONNECT, path, h, m...) | ||||
| } | ||||
|  | ||||
| // DELETE registers a new DELETE route for a path with matching handler in the router | ||||
| // with optional route-level middleware. | ||||
| func (e *Echo) DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return e.Add(DELETE, path, h, m...) | ||||
| func (e *Echo) DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	e.add(DELETE, path, h, m...) | ||||
| } | ||||
|  | ||||
| // GET registers a new GET route for a path with matching handler in the router | ||||
| // with optional route-level middleware. | ||||
| func (e *Echo) GET(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return e.Add(GET, path, h, m...) | ||||
| func (e *Echo) GET(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	e.add(GET, path, h, m...) | ||||
| } | ||||
|  | ||||
| // HEAD registers a new HEAD route for a path with matching handler in the | ||||
| // router with optional route-level middleware. | ||||
| func (e *Echo) HEAD(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return e.Add(HEAD, path, h, m...) | ||||
| func (e *Echo) HEAD(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	e.add(HEAD, path, h, m...) | ||||
| } | ||||
|  | ||||
| // OPTIONS registers a new OPTIONS route for a path with matching handler in the | ||||
| // router with optional route-level middleware. | ||||
| func (e *Echo) OPTIONS(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return e.Add(OPTIONS, path, h, m...) | ||||
| func (e *Echo) OPTIONS(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	e.add(OPTIONS, path, h, m...) | ||||
| } | ||||
|  | ||||
| // PATCH registers a new PATCH route for a path with matching handler in the | ||||
| // router with optional route-level middleware. | ||||
| func (e *Echo) PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return e.Add(PATCH, path, h, m...) | ||||
| func (e *Echo) PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	e.add(PATCH, path, h, m...) | ||||
| } | ||||
|  | ||||
| // POST registers a new POST route for a path with matching handler in the | ||||
| // router with optional route-level middleware. | ||||
| func (e *Echo) POST(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return e.Add(POST, path, h, m...) | ||||
| func (e *Echo) POST(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	e.add(POST, path, h, m...) | ||||
| } | ||||
|  | ||||
| // PUT registers a new PUT route for a path with matching handler in the | ||||
| // router with optional route-level middleware. | ||||
| func (e *Echo) PUT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return e.Add(PUT, path, h, m...) | ||||
| func (e *Echo) PUT(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	e.add(PUT, path, h, m...) | ||||
| } | ||||
|  | ||||
| // TRACE registers a new TRACE route for a path with matching handler in the | ||||
| // router with optional route-level middleware. | ||||
| func (e *Echo) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return e.Add(TRACE, path, h, m...) | ||||
| func (e *Echo) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	e.add(TRACE, path, h, m...) | ||||
| } | ||||
|  | ||||
| // Any registers a new route for all HTTP methods and path with matching handler | ||||
| // in the router with optional route-level middleware. | ||||
| func (e *Echo) Any(path string, handler HandlerFunc, middleware ...MiddlewareFunc) []*Route { | ||||
| 	routes := make([]*Route, 0) | ||||
| func (e *Echo) Any(path string, handler HandlerFunc, middleware ...MiddlewareFunc) { | ||||
| 	for _, m := range methods { | ||||
| 		routes = append(routes, e.Add(m, path, handler, middleware...)) | ||||
| 		e.add(m, path, handler, middleware...) | ||||
| 	} | ||||
| 	return routes | ||||
| } | ||||
|  | ||||
| // Match registers a new route for multiple HTTP methods and path with matching | ||||
| // handler in the router with optional route-level middleware. | ||||
| func (e *Echo) Match(methods []string, path string, handler HandlerFunc, middleware ...MiddlewareFunc) []*Route { | ||||
| 	routes := make([]*Route, 0) | ||||
| func (e *Echo) Match(methods []string, path string, handler HandlerFunc, middleware ...MiddlewareFunc) { | ||||
| 	for _, m := range methods { | ||||
| 		routes = append(routes, e.Add(m, path, handler, middleware...)) | ||||
| 		e.add(m, path, handler, middleware...) | ||||
| 	} | ||||
| 	return routes | ||||
| } | ||||
|  | ||||
| // Static registers a new route with path prefix to serve static files from the | ||||
| // provided root directory. | ||||
| func (e *Echo) Static(prefix, root string) *Route { | ||||
| func (e *Echo) Static(prefix, root string) { | ||||
| 	if root == "" { | ||||
| 		root = "." // For security we want to restrict to CWD. | ||||
| 	} | ||||
| 	return static(e, prefix, root) | ||||
| 	static(e, prefix, root) | ||||
| } | ||||
|  | ||||
| func static(i i, prefix, root string) *Route { | ||||
| func static(i i, prefix, root string) { | ||||
| 	h := func(c Context) error { | ||||
| 		p, err := PathUnescape(c.Param("*")) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		name := filepath.Join(root, path.Clean("/"+p)) // "/"+ for security | ||||
| 		name := filepath.Join(root, path.Clean("/"+c.Param("*"))) // "/"+ for security | ||||
| 		return c.File(name) | ||||
| 	} | ||||
| 	i.GET(prefix, h) | ||||
| 	if prefix == "/" { | ||||
| 		return i.GET(prefix+"*", h) | ||||
| 		i.GET(prefix+"*", h) | ||||
| 	} else { | ||||
| 		i.GET(prefix+"/*", h) | ||||
| 	} | ||||
|  | ||||
| 	return i.GET(prefix+"/*", h) | ||||
| } | ||||
|  | ||||
| // File registers a new route with path to serve a static file. | ||||
| func (e *Echo) File(path, file string) *Route { | ||||
| 	return e.GET(path, func(c Context) error { | ||||
| func (e *Echo) File(path, file string) { | ||||
| 	e.GET(path, func(c Context) error { | ||||
| 		return c.File(file) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // Add registers a new route for an HTTP method and path with matching handler | ||||
| // in the router with optional route-level middleware. | ||||
| func (e *Echo) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route { | ||||
| func (e *Echo) add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) { | ||||
| 	name := handlerName(handler) | ||||
| 	e.router.Add(method, path, func(c Context) error { | ||||
| 		h := handler | ||||
| @@ -479,10 +465,9 @@ func (e *Echo) Add(method, path string, handler HandlerFunc, middleware ...Middl | ||||
| 	r := &Route{ | ||||
| 		Method:  method, | ||||
| 		Path:    path, | ||||
| 		Name:   name, | ||||
| 		Handler: name, | ||||
| 	} | ||||
| 	e.router.routes[method+path] = r | ||||
| 	return r | ||||
| } | ||||
|  | ||||
| // Group creates a new router group with prefix and optional group-level middleware. | ||||
| @@ -494,22 +479,12 @@ func (e *Echo) Group(prefix string, m ...MiddlewareFunc) (g *Group) { | ||||
|  | ||||
| // URI generates a URI from handler. | ||||
| func (e *Echo) URI(handler HandlerFunc, params ...interface{}) string { | ||||
| 	name := handlerName(handler) | ||||
| 	return e.Reverse(name, params...) | ||||
| } | ||||
|  | ||||
| // URL is an alias for `URI` function. | ||||
| func (e *Echo) URL(h HandlerFunc, params ...interface{}) string { | ||||
| 	return e.URI(h, params...) | ||||
| } | ||||
|  | ||||
| // Reverse generates an URL from route name and provided parameters. | ||||
| func (e *Echo) Reverse(name string, params ...interface{}) string { | ||||
| 	uri := new(bytes.Buffer) | ||||
| 	ln := len(params) | ||||
| 	n := 0 | ||||
| 	name := handlerName(handler) | ||||
| 	for _, r := range e.router.routes { | ||||
| 		if r.Name == name { | ||||
| 		if r.Handler == name { | ||||
| 			for i, l := 0, len(r.Path); i < l; i++ { | ||||
| 				if r.Path[i] == ':' && n < ln { | ||||
| 					for ; i < l && r.Path[i] != '/'; i++ { | ||||
| @@ -527,6 +502,11 @@ func (e *Echo) Reverse(name string, params ...interface{}) string { | ||||
| 	return uri.String() | ||||
| } | ||||
|  | ||||
| // URL is an alias for `URI` function. | ||||
| func (e *Echo) URL(h HandlerFunc, params ...interface{}) string { | ||||
| 	return e.URI(h, params...) | ||||
| } | ||||
|  | ||||
| // Routes returns the registered routes. | ||||
| func (e *Echo) Routes() []*Route { | ||||
| 	routes := []*Route{} | ||||
| @@ -673,7 +653,7 @@ func NewHTTPError(code int, message ...interface{}) *HTTPError { | ||||
|  | ||||
| // Error makes it compatible with `error` interface. | ||||
| func (he *HTTPError) Error() string { | ||||
| 	return fmt.Sprintf("code=%d, message=%v", he.Code, he.Message) | ||||
| 	return fmt.Sprintf("code=%d, message=%s", he.Code, he.Message) | ||||
| } | ||||
|  | ||||
| // WrapHandler wraps `http.Handler` into `echo.HandlerFunc`. | ||||
|   | ||||
							
								
								
									
										47
									
								
								vendor/github.com/labstack/echo/group.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										47
									
								
								vendor/github.com/labstack/echo/group.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -21,66 +21,66 @@ func (g *Group) Use(middleware ...MiddlewareFunc) { | ||||
| 	// Allow all requests to reach the group as they might get dropped if router | ||||
| 	// doesn't find a match, making none of the group middleware process. | ||||
| 	g.echo.Any(path.Clean(g.prefix+"/*"), func(c Context) error { | ||||
| 		return NotFoundHandler(c) | ||||
| 		return ErrNotFound | ||||
| 	}, g.middleware...) | ||||
| } | ||||
|  | ||||
| // CONNECT implements `Echo#CONNECT()` for sub-routes within the Group. | ||||
| func (g *Group) CONNECT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return g.Add(CONNECT, path, h, m...) | ||||
| func (g *Group) CONNECT(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	g.add(CONNECT, path, h, m...) | ||||
| } | ||||
|  | ||||
| // DELETE implements `Echo#DELETE()` for sub-routes within the Group. | ||||
| func (g *Group) DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return g.Add(DELETE, path, h, m...) | ||||
| func (g *Group) DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	g.add(DELETE, path, h, m...) | ||||
| } | ||||
|  | ||||
| // GET implements `Echo#GET()` for sub-routes within the Group. | ||||
| func (g *Group) GET(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return g.Add(GET, path, h, m...) | ||||
| func (g *Group) GET(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	g.add(GET, path, h, m...) | ||||
| } | ||||
|  | ||||
| // HEAD implements `Echo#HEAD()` for sub-routes within the Group. | ||||
| func (g *Group) HEAD(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return g.Add(HEAD, path, h, m...) | ||||
| func (g *Group) HEAD(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	g.add(HEAD, path, h, m...) | ||||
| } | ||||
|  | ||||
| // OPTIONS implements `Echo#OPTIONS()` for sub-routes within the Group. | ||||
| func (g *Group) OPTIONS(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return g.Add(OPTIONS, path, h, m...) | ||||
| func (g *Group) OPTIONS(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	g.add(OPTIONS, path, h, m...) | ||||
| } | ||||
|  | ||||
| // PATCH implements `Echo#PATCH()` for sub-routes within the Group. | ||||
| func (g *Group) PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return g.Add(PATCH, path, h, m...) | ||||
| func (g *Group) PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	g.add(PATCH, path, h, m...) | ||||
| } | ||||
|  | ||||
| // POST implements `Echo#POST()` for sub-routes within the Group. | ||||
| func (g *Group) POST(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return g.Add(POST, path, h, m...) | ||||
| func (g *Group) POST(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	g.add(POST, path, h, m...) | ||||
| } | ||||
|  | ||||
| // PUT implements `Echo#PUT()` for sub-routes within the Group. | ||||
| func (g *Group) PUT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return g.Add(PUT, path, h, m...) | ||||
| func (g *Group) PUT(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	g.add(PUT, path, h, m...) | ||||
| } | ||||
|  | ||||
| // TRACE implements `Echo#TRACE()` for sub-routes within the Group. | ||||
| func (g *Group) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route { | ||||
| 	return g.Add(TRACE, path, h, m...) | ||||
| func (g *Group) TRACE(path string, h HandlerFunc, m ...MiddlewareFunc) { | ||||
| 	g.add(TRACE, path, h, m...) | ||||
| } | ||||
|  | ||||
| // Any implements `Echo#Any()` for sub-routes within the Group. | ||||
| func (g *Group) Any(path string, handler HandlerFunc, middleware ...MiddlewareFunc) { | ||||
| 	for _, m := range methods { | ||||
| 		g.Add(m, path, handler, middleware...) | ||||
| 		g.add(m, path, handler, middleware...) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Match implements `Echo#Match()` for sub-routes within the Group. | ||||
| func (g *Group) Match(methods []string, path string, handler HandlerFunc, middleware ...MiddlewareFunc) { | ||||
| 	for _, m := range methods { | ||||
| 		g.Add(m, path, handler, middleware...) | ||||
| 		g.add(m, path, handler, middleware...) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -102,13 +102,12 @@ func (g *Group) File(path, file string) { | ||||
| 	g.echo.File(g.prefix+path, file) | ||||
| } | ||||
|  | ||||
| // Add implements `Echo#Add()` for sub-routes within the Group. | ||||
| func (g *Group) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route { | ||||
| func (g *Group) add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) { | ||||
| 	// Combine into a new slice to avoid accidentally passing the same slice for | ||||
| 	// multiple routes, which would lead to later add() calls overwriting the | ||||
| 	// middleware from earlier calls. | ||||
| 	m := []MiddlewareFunc{} | ||||
| 	m = append(m, g.middleware...) | ||||
| 	m = append(m, middleware...) | ||||
| 	return g.echo.Add(method, g.prefix+path, handler, m...) | ||||
| 	g.echo.add(method, g.prefix+path, handler, m...) | ||||
| } | ||||
|   | ||||
							
								
								
									
										7
									
								
								vendor/github.com/labstack/echo/middleware/basic_auth.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/labstack/echo/middleware/basic_auth.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -3,7 +3,6 @@ package middleware | ||||
| import ( | ||||
| 	"encoding/base64" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/labstack/echo" | ||||
| ) | ||||
| @@ -28,7 +27,7 @@ type ( | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	basic        = "basic" | ||||
| 	basic        = "Basic" | ||||
| 	defaultRealm = "Restricted" | ||||
| ) | ||||
|  | ||||
| @@ -55,7 +54,7 @@ func BasicAuth(fn BasicAuthValidator) echo.MiddlewareFunc { | ||||
| func BasicAuthWithConfig(config BasicAuthConfig) echo.MiddlewareFunc { | ||||
| 	// Defaults | ||||
| 	if config.Validator == nil { | ||||
| 		panic("echo: basic-auth middleware requires a validator function") | ||||
| 		panic("basic-auth middleware requires a validator function") | ||||
| 	} | ||||
| 	if config.Skipper == nil { | ||||
| 		config.Skipper = DefaultBasicAuthConfig.Skipper | ||||
| @@ -73,7 +72,7 @@ func BasicAuthWithConfig(config BasicAuthConfig) echo.MiddlewareFunc { | ||||
| 			auth := c.Request().Header.Get(echo.HeaderAuthorization) | ||||
| 			l := len(basic) | ||||
|  | ||||
| 			if len(auth) > l+1 && strings.ToLower(auth[:l]) == basic { | ||||
| 			if len(auth) > l+1 && auth[:l] == basic { | ||||
| 				b, err := base64.StdEncoding.DecodeString(auth[l+1:]) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
|   | ||||
							
								
								
									
										112
									
								
								vendor/github.com/labstack/echo/middleware/body_dump.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										112
									
								
								vendor/github.com/labstack/echo/middleware/body_dump.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,112 +0,0 @@ | ||||
| package middleware | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"io/ioutil" | ||||
| 	"net" | ||||
| 	"net/http" | ||||
|  | ||||
| 	"io" | ||||
|  | ||||
| 	"github.com/labstack/echo" | ||||
| ) | ||||
|  | ||||
| type ( | ||||
| 	// BodyDumpConfig defines the config for BodyDump middleware. | ||||
| 	BodyDumpConfig struct { | ||||
| 		// Skipper defines a function to skip middleware. | ||||
| 		Skipper Skipper | ||||
|  | ||||
| 		// Handler receives request and response payload. | ||||
| 		// Required. | ||||
| 		Handler BodyDumpHandler | ||||
| 	} | ||||
|  | ||||
| 	// BodyDumpHandler receives the request and response payload. | ||||
| 	BodyDumpHandler func(echo.Context, []byte, []byte) | ||||
|  | ||||
| 	bodyDumpResponseWriter struct { | ||||
| 		io.Writer | ||||
| 		http.ResponseWriter | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// DefaultBodyDumpConfig is the default Gzip middleware config. | ||||
| 	DefaultBodyDumpConfig = BodyDumpConfig{ | ||||
| 		Skipper: DefaultSkipper, | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| // BodyDump returns a BodyDump middleware. | ||||
| // | ||||
| // BodyLimit middleware captures the request and response payload and calls the | ||||
| // registered handler. | ||||
| func BodyDump(handler BodyDumpHandler) echo.MiddlewareFunc { | ||||
| 	c := DefaultBodyDumpConfig | ||||
| 	c.Handler = handler | ||||
| 	return BodyDumpWithConfig(c) | ||||
| } | ||||
|  | ||||
| // BodyDumpWithConfig returns a BodyDump middleware with config. | ||||
| // See: `BodyDump()`. | ||||
| func BodyDumpWithConfig(config BodyDumpConfig) echo.MiddlewareFunc { | ||||
| 	// Defaults | ||||
| 	if config.Handler == nil { | ||||
| 		panic("echo: body-dump middleware requires a handler function") | ||||
| 	} | ||||
| 	if config.Skipper == nil { | ||||
| 		config.Skipper = DefaultBodyDumpConfig.Skipper | ||||
| 	} | ||||
|  | ||||
| 	return func(next echo.HandlerFunc) echo.HandlerFunc { | ||||
| 		return func(c echo.Context) (err error) { | ||||
| 			if config.Skipper(c) { | ||||
| 				return next(c) | ||||
| 			} | ||||
|  | ||||
| 			// Request | ||||
| 			reqBody := []byte{} | ||||
| 			if c.Request().Body != nil { // Read | ||||
| 				reqBody, _ = ioutil.ReadAll(c.Request().Body) | ||||
| 			} | ||||
| 			c.Request().Body = ioutil.NopCloser(bytes.NewBuffer(reqBody)) // Reset | ||||
|  | ||||
| 			// Response | ||||
| 			resBody := new(bytes.Buffer) | ||||
| 			mw := io.MultiWriter(c.Response().Writer, resBody) | ||||
| 			writer := &bodyDumpResponseWriter{Writer: mw, ResponseWriter: c.Response().Writer} | ||||
| 			c.Response().Writer = writer | ||||
|  | ||||
| 			if err = next(c); err != nil { | ||||
| 				c.Error(err) | ||||
| 			} | ||||
|  | ||||
| 			// Callback | ||||
| 			config.Handler(c, reqBody, resBody.Bytes()) | ||||
|  | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (w *bodyDumpResponseWriter) WriteHeader(code int) { | ||||
| 	w.ResponseWriter.WriteHeader(code) | ||||
| } | ||||
|  | ||||
| func (w *bodyDumpResponseWriter) Write(b []byte) (int, error) { | ||||
| 	return w.Writer.Write(b) | ||||
| } | ||||
|  | ||||
| func (w *bodyDumpResponseWriter) Flush() { | ||||
| 	w.ResponseWriter.(http.Flusher).Flush() | ||||
| } | ||||
|  | ||||
| func (w *bodyDumpResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { | ||||
| 	return w.ResponseWriter.(http.Hijacker).Hijack() | ||||
| } | ||||
|  | ||||
| func (w *bodyDumpResponseWriter) CloseNotify() <-chan bool { | ||||
| 	return w.ResponseWriter.(http.CloseNotifier).CloseNotify() | ||||
| } | ||||
							
								
								
									
										4
									
								
								vendor/github.com/labstack/echo/middleware/body_limit.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/labstack/echo/middleware/body_limit.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -30,7 +30,7 @@ type ( | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// DefaultBodyLimitConfig is the default BodyLimit middleware config. | ||||
| 	// DefaultBodyLimitConfig is the default Gzip middleware config. | ||||
| 	DefaultBodyLimitConfig = BodyLimitConfig{ | ||||
| 		Skipper: DefaultSkipper, | ||||
| 	} | ||||
| @@ -60,7 +60,7 @@ func BodyLimitWithConfig(config BodyLimitConfig) echo.MiddlewareFunc { | ||||
|  | ||||
| 	limit, err := bytes.Parse(config.Limit) | ||||
| 	if err != nil { | ||||
| 		panic(fmt.Errorf("echo: invalid body-limit=%s", config.Limit)) | ||||
| 		panic(fmt.Errorf("invalid body-limit=%s", config.Limit)) | ||||
| 	} | ||||
| 	config.limit = limit | ||||
| 	pool := limitedReaderPool(config) | ||||
|   | ||||
							
								
								
									
										3
									
								
								vendor/github.com/labstack/echo/middleware/compress.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/labstack/echo/middleware/compress.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -67,7 +67,7 @@ func GzipWithConfig(config GzipConfig) echo.MiddlewareFunc { | ||||
| 			res := c.Response() | ||||
| 			res.Header().Add(echo.HeaderVary, echo.HeaderAcceptEncoding) | ||||
| 			if strings.Contains(c.Request().Header.Get(echo.HeaderAcceptEncoding), gzipScheme) { | ||||
| 				res.Header().Set(echo.HeaderContentEncoding, gzipScheme) // Issue #806 | ||||
| 				res.Header().Add(echo.HeaderContentEncoding, gzipScheme) // Issue #806 | ||||
| 				rw := res.Writer | ||||
| 				w, err := gzip.NewWriterLevel(rw, config.Level) | ||||
| 				if err != nil { | ||||
| @@ -98,7 +98,6 @@ func (w *gzipResponseWriter) WriteHeader(code int) { | ||||
| 	if code == http.StatusNoContent { // Issue #489 | ||||
| 		w.ResponseWriter.Header().Del(echo.HeaderContentEncoding) | ||||
| 	} | ||||
| 	w.Header().Del(echo.HeaderContentLength) // Issue #444 | ||||
| 	w.ResponseWriter.WriteHeader(code) | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										26
									
								
								vendor/github.com/labstack/echo/middleware/jwt.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/labstack/echo/middleware/jwt.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,6 +1,7 @@ | ||||
| package middleware | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"reflect" | ||||
| @@ -56,12 +57,6 @@ const ( | ||||
| 	AlgorithmHS256 = "HS256" | ||||
| ) | ||||
|  | ||||
| // Errors | ||||
| var ( | ||||
| 	ErrJWTMissing = echo.NewHTTPError(http.StatusBadRequest, "Missing or malformed jwt") | ||||
| 	ErrJWTInvalid = echo.NewHTTPError(http.StatusUnauthorized, "Invalid or expired jwt") | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// DefaultJWTConfig is the default JWT auth middleware config. | ||||
| 	DefaultJWTConfig = JWTConfig{ | ||||
| @@ -82,7 +77,7 @@ var ( | ||||
| // | ||||
| // See: https://jwt.io/introduction | ||||
| // See `JWTConfig.TokenLookup` | ||||
| func JWT(key interface{}) echo.MiddlewareFunc { | ||||
| func JWT(key []byte) echo.MiddlewareFunc { | ||||
| 	c := DefaultJWTConfig | ||||
| 	c.SigningKey = key | ||||
| 	return JWTWithConfig(c) | ||||
| @@ -139,15 +134,14 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc { | ||||
|  | ||||
| 			auth, err := extractor(c) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 				return echo.NewHTTPError(http.StatusBadRequest, err.Error()) | ||||
| 			} | ||||
| 			token := new(jwt.Token) | ||||
| 			// Issue #647, #656 | ||||
| 			if _, ok := config.Claims.(jwt.MapClaims); ok { | ||||
| 				token, err = jwt.Parse(auth, config.keyFunc) | ||||
| 			} else { | ||||
| 				t := reflect.ValueOf(config.Claims).Type().Elem() | ||||
| 				claims := reflect.New(t).Interface().(jwt.Claims) | ||||
| 				claims := reflect.ValueOf(config.Claims).Interface().(jwt.Claims) | ||||
| 				token, err = jwt.ParseWithClaims(auth, claims, config.keyFunc) | ||||
| 			} | ||||
| 			if err == nil && token.Valid { | ||||
| @@ -155,11 +149,7 @@ func JWTWithConfig(config JWTConfig) echo.MiddlewareFunc { | ||||
| 				c.Set(config.ContextKey, token) | ||||
| 				return next(c) | ||||
| 			} | ||||
| 			return &echo.HTTPError{ | ||||
| 				Code:    ErrJWTInvalid.Code, | ||||
| 				Message: ErrJWTInvalid.Message, | ||||
| 				Inner:   err, | ||||
| 			} | ||||
| 			return echo.ErrUnauthorized | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -172,7 +162,7 @@ func jwtFromHeader(header string, authScheme string) jwtExtractor { | ||||
| 		if len(auth) > l+1 && auth[:l] == authScheme { | ||||
| 			return auth[l+1:], nil | ||||
| 		} | ||||
| 		return "", ErrJWTMissing | ||||
| 		return "", errors.New("Missing or invalid jwt in the request header") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -181,7 +171,7 @@ func jwtFromQuery(param string) jwtExtractor { | ||||
| 	return func(c echo.Context) (string, error) { | ||||
| 		token := c.QueryParam(param) | ||||
| 		if token == "" { | ||||
| 			return "", ErrJWTMissing | ||||
| 			return "", errors.New("Missing jwt in the query string") | ||||
| 		} | ||||
| 		return token, nil | ||||
| 	} | ||||
| @@ -192,7 +182,7 @@ func jwtFromCookie(name string) jwtExtractor { | ||||
| 	return func(c echo.Context) (string, error) { | ||||
| 		cookie, err := c.Cookie(name) | ||||
| 		if err != nil { | ||||
| 			return "", ErrJWTMissing | ||||
| 			return "", errors.New("Missing jwt in the cookie") | ||||
| 		} | ||||
| 		return cookie.Value, nil | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/github.com/labstack/echo/middleware/key_auth.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/labstack/echo/middleware/key_auth.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -72,7 +72,7 @@ func KeyAuthWithConfig(config KeyAuthConfig) echo.MiddlewareFunc { | ||||
| 		config.KeyLookup = DefaultKeyAuthConfig.KeyLookup | ||||
| 	} | ||||
| 	if config.Validator == nil { | ||||
| 		panic("echo: key-auth middleware requires a validator function") | ||||
| 		panic("key-auth middleware requires a validator function") | ||||
| 	} | ||||
|  | ||||
| 	// Initialize | ||||
|   | ||||
							
								
								
									
										42
									
								
								vendor/github.com/labstack/echo/middleware/proxy.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										42
									
								
								vendor/github.com/labstack/echo/middleware/proxy.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,6 +1,7 @@ | ||||
| package middleware | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"math/rand" | ||||
| @@ -53,38 +54,35 @@ type ( | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// DefaultProxyConfig is the default Proxy middleware config. | ||||
| 	DefaultProxyConfig = ProxyConfig{ | ||||
| 		Skipper: DefaultSkipper, | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| func proxyHTTP(t *ProxyTarget) http.Handler { | ||||
| 	return httputil.NewSingleHostReverseProxy(t.URL) | ||||
| } | ||||
|  | ||||
| func proxyRaw(t *ProxyTarget, c echo.Context) http.Handler { | ||||
| 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
| 		in, _, err := c.Response().Hijack() | ||||
| 		h, ok := w.(http.Hijacker) | ||||
| 		if !ok { | ||||
| 			c.Error(errors.New("proxy raw, not a hijacker")) | ||||
| 			return | ||||
| 		} | ||||
| 		in, _, err := h.Hijack() | ||||
| 		if err != nil { | ||||
| 			c.Error(fmt.Errorf("proxy raw, hijack error=%v, url=%s", t.URL, err)) | ||||
| 			c.Error(fmt.Errorf("proxy raw, hijack error=%v, url=%s", r.URL, err)) | ||||
| 			return | ||||
| 		} | ||||
| 		defer in.Close() | ||||
|  | ||||
| 		out, err := net.Dial("tcp", t.URL.Host) | ||||
| 		if err != nil { | ||||
| 			he := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, dial error=%v, url=%s", t.URL, err)) | ||||
| 			he := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, dial error=%v, url=%s", r.URL, err)) | ||||
| 			c.Error(he) | ||||
| 			return | ||||
| 		} | ||||
| 		defer out.Close() | ||||
|  | ||||
| 		// Write header | ||||
| 		err = r.Write(out) | ||||
| 		if err != nil { | ||||
| 			he := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, request header copy error=%v, url=%s", t.URL, err)) | ||||
| 			he := echo.NewHTTPError(http.StatusBadGateway, fmt.Sprintf("proxy raw, request copy error=%v, url=%s", r.URL, err)) | ||||
| 			c.Error(he) | ||||
| 			return | ||||
| 		} | ||||
| @@ -99,7 +97,7 @@ func proxyRaw(t *ProxyTarget, c echo.Context) http.Handler { | ||||
| 		go cp(in, out) | ||||
| 		err = <-errc | ||||
| 		if err != nil && err != io.EOF { | ||||
| 			c.Logger().Errorf("proxy raw, copy body error=%v, url=%s", t.URL, err) | ||||
| 			c.Logger().Errorf("proxy raw, error=%v, url=%s", r.URL, err) | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
| @@ -120,18 +118,8 @@ func (r *RoundRobinBalancer) Next() *ProxyTarget { | ||||
| 	return t | ||||
| } | ||||
|  | ||||
| // Proxy returns a Proxy middleware. | ||||
| // | ||||
| // Proxy middleware forwards the request to upstream server using a configured load balancing technique. | ||||
| func Proxy(balancer ProxyBalancer) echo.MiddlewareFunc { | ||||
| 	c := DefaultProxyConfig | ||||
| 	c.Balancer = balancer | ||||
| 	return ProxyWithConfig(c) | ||||
| } | ||||
|  | ||||
| // ProxyWithConfig returns a Proxy middleware with config. | ||||
| // See: `Proxy()` | ||||
| func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc { | ||||
| // Proxy returns an HTTP/WebSocket reverse proxy middleware. | ||||
| func Proxy(config ProxyConfig) echo.MiddlewareFunc { | ||||
| 	// Defaults | ||||
| 	if config.Skipper == nil { | ||||
| 		config.Skipper = DefaultLoggerConfig.Skipper | ||||
| @@ -142,10 +130,6 @@ func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc { | ||||
|  | ||||
| 	return func(next echo.HandlerFunc) echo.HandlerFunc { | ||||
| 		return func(c echo.Context) (err error) { | ||||
| 			if config.Skipper(c) { | ||||
| 				return next(c) | ||||
| 			} | ||||
|  | ||||
| 			req := c.Request() | ||||
| 			res := c.Response() | ||||
| 			tgt := config.Balancer.Next() | ||||
|   | ||||
							
								
								
									
										10
									
								
								vendor/github.com/labstack/echo/middleware/recover.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/labstack/echo/middleware/recover.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -5,6 +5,7 @@ import ( | ||||
| 	"runtime" | ||||
|  | ||||
| 	"github.com/labstack/echo" | ||||
| 	"github.com/labstack/gommon/color" | ||||
| ) | ||||
|  | ||||
| type ( | ||||
| @@ -63,14 +64,17 @@ func RecoverWithConfig(config RecoverConfig) echo.MiddlewareFunc { | ||||
|  | ||||
| 			defer func() { | ||||
| 				if r := recover(); r != nil { | ||||
| 					err, ok := r.(error) | ||||
| 					if !ok { | ||||
| 					var err error | ||||
| 					switch r := r.(type) { | ||||
| 					case error: | ||||
| 						err = r | ||||
| 					default: | ||||
| 						err = fmt.Errorf("%v", r) | ||||
| 					} | ||||
| 					stack := make([]byte, config.StackSize) | ||||
| 					length := runtime.Stack(stack, !config.DisableStackAll) | ||||
| 					if !config.DisablePrintStack { | ||||
| 						c.Logger().Printf("[PANIC RECOVER] %v %s\n", err, stack[:length]) | ||||
| 						c.Logger().Printf("[%s] %s %s\n", color.Red("PANIC RECOVER"), err, stack[:length]) | ||||
| 					} | ||||
| 					c.Error(err) | ||||
| 				} | ||||
|   | ||||
							
								
								
									
										31
									
								
								vendor/github.com/labstack/echo/middleware/static.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										31
									
								
								vendor/github.com/labstack/echo/middleware/static.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -2,7 +2,6 @@ package middleware | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 	"path/filepath" | ||||
| @@ -67,7 +66,7 @@ func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc { | ||||
| 	} | ||||
|  | ||||
| 	return func(next echo.HandlerFunc) echo.HandlerFunc { | ||||
| 		return func(c echo.Context) (err error) { | ||||
| 		return func(c echo.Context) error { | ||||
| 			if config.Skipper(c) { | ||||
| 				return next(c) | ||||
| 			} | ||||
| @@ -76,25 +75,17 @@ func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc { | ||||
| 			if strings.HasSuffix(c.Path(), "*") { // When serving from a group, e.g. `/static*`. | ||||
| 				p = c.Param("*") | ||||
| 			} | ||||
| 			p, err = echo.PathUnescape(p) | ||||
| 			if err != nil { | ||||
| 				return | ||||
| 			} | ||||
| 			name := filepath.Join(config.Root, path.Clean("/"+p)) // "/"+ for security | ||||
|  | ||||
| 			fi, err := os.Stat(name) | ||||
| 			if err != nil { | ||||
| 				if os.IsNotExist(err) { | ||||
| 					if err = next(c); err != nil { | ||||
| 						if he, ok := err.(*echo.HTTPError); ok { | ||||
| 							if config.HTML5 && he.Code == http.StatusNotFound { | ||||
| 					if config.HTML5 && path.Ext(p) == "" { | ||||
| 						return c.File(filepath.Join(config.Root, config.Index)) | ||||
| 					} | ||||
| 					return next(c) | ||||
| 				} | ||||
| 						return | ||||
| 					} | ||||
| 				} | ||||
| 				return | ||||
| 				return err | ||||
| 			} | ||||
|  | ||||
| 			if fi.IsDir() { | ||||
| @@ -108,7 +99,7 @@ func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc { | ||||
| 					if os.IsNotExist(err) { | ||||
| 						return next(c) | ||||
| 					} | ||||
| 					return | ||||
| 					return err | ||||
| 				} | ||||
|  | ||||
| 				return c.File(index) | ||||
| @@ -119,20 +110,20 @@ func StaticWithConfig(config StaticConfig) echo.MiddlewareFunc { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func listDir(name string, res *echo.Response) (err error) { | ||||
| func listDir(name string, res *echo.Response) error { | ||||
| 	dir, err := os.Open(name) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 		return err | ||||
| 	} | ||||
| 	dirs, err := dir.Readdir(-1) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Create a directory index | ||||
| 	res.Header().Set(echo.HeaderContentType, echo.MIMETextHTMLCharsetUTF8) | ||||
| 	if _, err = fmt.Fprintf(res, "<pre>\n"); err != nil { | ||||
| 		return | ||||
| 		return err | ||||
| 	} | ||||
| 	for _, d := range dirs { | ||||
| 		name := d.Name() | ||||
| @@ -142,9 +133,9 @@ func listDir(name string, res *echo.Response) (err error) { | ||||
| 			name += "/" | ||||
| 		} | ||||
| 		if _, err = fmt.Fprintf(res, "<a href=\"%s\" style=\"color: %s;\">%s</a>\n", name, color, name); err != nil { | ||||
| 			return | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	_, err = fmt.Fprintf(res, "</pre>\n") | ||||
| 	return | ||||
| 	return err | ||||
| } | ||||
|   | ||||
							
								
								
									
										11
									
								
								vendor/github.com/labstack/echo/response.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/labstack/echo/response.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -11,12 +11,11 @@ type ( | ||||
| 	// by an HTTP handler to construct an HTTP response. | ||||
| 	// See: https://golang.org/pkg/net/http/#ResponseWriter | ||||
| 	Response struct { | ||||
| 		echo        *Echo | ||||
| 		beforeFuncs []func() | ||||
| 		Writer    http.ResponseWriter | ||||
| 		Status    int | ||||
| 		Size      int64 | ||||
| 		Committed bool | ||||
| 		echo      *Echo | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| @@ -35,11 +34,6 @@ func (r *Response) Header() http.Header { | ||||
| 	return r.Writer.Header() | ||||
| } | ||||
|  | ||||
| // Before registers a function which is called just before the response is written. | ||||
| func (r *Response) Before(fn func()) { | ||||
| 	r.beforeFuncs = append(r.beforeFuncs, fn) | ||||
| } | ||||
|  | ||||
| // WriteHeader sends an HTTP response header with status code. If WriteHeader is | ||||
| // not called explicitly, the first call to Write will trigger an implicit | ||||
| // WriteHeader(http.StatusOK). Thus explicit calls to WriteHeader are mainly | ||||
| @@ -49,9 +43,6 @@ func (r *Response) WriteHeader(code int) { | ||||
| 		r.echo.Logger.Warn("response already committed") | ||||
| 		return | ||||
| 	} | ||||
| 	for _, fn := range r.beforeFuncs { | ||||
| 		fn() | ||||
| 	} | ||||
| 	r.Status = code | ||||
| 	r.Writer.WriteHeader(code) | ||||
| 	r.Committed = true | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/github.com/labstack/echo/router.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/labstack/echo/router.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -394,7 +394,7 @@ func (r *Router) Find(method, path string, c Context) { | ||||
| 		if cn = cn.findChildByKind(akind); cn == nil { | ||||
| 			if nn != nil { | ||||
| 				cn = nn | ||||
| 				nn = cn.parent // Next (Issue #954) | ||||
| 				nn = nil // Next | ||||
| 				search = ns | ||||
| 				if nk == pkind { | ||||
| 					goto Param | ||||
|   | ||||
							
								
								
									
										12
									
								
								vendor/github.com/labstack/echo/util_go17.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								vendor/github.com/labstack/echo/util_go17.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,12 +0,0 @@ | ||||
| // +build go1.7, !go1.8 | ||||
|  | ||||
| package echo | ||||
|  | ||||
| import ( | ||||
| 	"net/url" | ||||
| ) | ||||
|  | ||||
| // PathUnescape is wraps `url.QueryUnescape` | ||||
| func PathUnescape(s string) (string, error) { | ||||
| 	return url.QueryUnescape(s) | ||||
| } | ||||
							
								
								
									
										10
									
								
								vendor/github.com/labstack/echo/util_go18.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/labstack/echo/util_go18.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,10 +0,0 @@ | ||||
| // +build go1.8 | ||||
|  | ||||
| package echo | ||||
|  | ||||
| import "net/url" | ||||
|  | ||||
| // PathUnescape is wraps `url.PathUnescape` | ||||
| func PathUnescape(s string) (string, error) { | ||||
| 	return url.PathUnescape(s) | ||||
| } | ||||
| @@ -25,7 +25,6 @@ type AttachmentAction struct { | ||||
| 	SelectedOptions []AttachmentActionOption      `json:"selected_options,omitempty"` // Optional. The first element of this array will be set as the pre-selected option for this menu. | ||||
| 	OptionGroups    []AttachmentActionOptionGroup `json:"option_groups,omitempty"`    // Optional. | ||||
| 	Confirm         *ConfirmationField            `json:"confirm,omitempty"`          // Optional. | ||||
| 	URL             string                        `json:"url,omitempty"`              // Optional. | ||||
| } | ||||
| 
 | ||||
| // AttachmentActionOption the individual option to appear in action menu. | ||||
| @@ -49,9 +48,6 @@ type AttachmentActionCallback struct { | ||||
| 	Channel    Channel            `json:"channel"` | ||||
| 	User       User               `json:"user"` | ||||
| 
 | ||||
| 	Name  string `json:"name"` | ||||
| 	Value string `json:"value"` | ||||
| 
 | ||||
| 	OriginalMessage Message `json:"original_message"` | ||||
| 
 | ||||
| 	ActionTs     string `json:"action_ts"` | ||||
| @@ -38,51 +38,51 @@ func channelRequest(ctx context.Context, path string, values url.Values, debug b | ||||
| } | ||||
| 
 | ||||
| // ArchiveChannel archives the given channel | ||||
| // see https://api.slack.com/methods/channels.archive | ||||
| func (api *Client) ArchiveChannel(channelID string) error { | ||||
| 	return api.ArchiveChannelContext(context.Background(), channelID) | ||||
| func (api *Client) ArchiveChannel(channel string) error { | ||||
| 	return api.ArchiveChannelContext(context.Background(), channel) | ||||
| } | ||||
| 
 | ||||
| // ArchiveChannelContext archives the given channel with a custom context | ||||
| // see https://api.slack.com/methods/channels.archive | ||||
| func (api *Client) ArchiveChannelContext(ctx context.Context, channelID string) error { | ||||
| func (api *Client) ArchiveChannelContext(ctx context.Context, channel string) error { | ||||
| 	values := url.Values{ | ||||
| 		"token":   {api.config.token}, | ||||
| 		"channel": {channelID}, | ||||
| 		"channel": {channel}, | ||||
| 	} | ||||
| 	_, err := channelRequest(ctx, "channels.archive", values, api.debug) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // UnarchiveChannel unarchives the given channel | ||||
| // see https://api.slack.com/methods/channels.unarchive | ||||
| func (api *Client) UnarchiveChannel(channelID string) error { | ||||
| 	return api.UnarchiveChannelContext(context.Background(), channelID) | ||||
| func (api *Client) UnarchiveChannel(channel string) error { | ||||
| 	return api.UnarchiveChannelContext(context.Background(), channel) | ||||
| } | ||||
| 
 | ||||
| // UnarchiveChannelContext unarchives the given channel with a custom context | ||||
| // see https://api.slack.com/methods/channels.unarchive | ||||
| func (api *Client) UnarchiveChannelContext(ctx context.Context, channelID string) error { | ||||
| func (api *Client) UnarchiveChannelContext(ctx context.Context, channel string) error { | ||||
| 	values := url.Values{ | ||||
| 		"token":   {api.config.token}, | ||||
| 		"channel": {channelID}, | ||||
| 		"channel": {channel}, | ||||
| 	} | ||||
| 	_, err := channelRequest(ctx, "channels.unarchive", values, api.debug) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // CreateChannel creates a channel with the given name and returns a *Channel | ||||
| // see https://api.slack.com/methods/channels.create | ||||
| func (api *Client) CreateChannel(channelName string) (*Channel, error) { | ||||
| 	return api.CreateChannelContext(context.Background(), channelName) | ||||
| func (api *Client) CreateChannel(channel string) (*Channel, error) { | ||||
| 	return api.CreateChannelContext(context.Background(), channel) | ||||
| } | ||||
| 
 | ||||
| // CreateChannelContext creates a channel with the given name and returns a *Channel with a custom context | ||||
| // see https://api.slack.com/methods/channels.create | ||||
| func (api *Client) CreateChannelContext(ctx context.Context, channelName string) (*Channel, error) { | ||||
| func (api *Client) CreateChannelContext(ctx context.Context, channel string) (*Channel, error) { | ||||
| 	values := url.Values{ | ||||
| 		"token": {api.config.token}, | ||||
| 		"name":  {channelName}, | ||||
| 		"name":  {channel}, | ||||
| 	} | ||||
| 	response, err := channelRequest(ctx, "channels.create", values, api.debug) | ||||
| 	if err != nil { | ||||
| @@ -92,17 +92,15 @@ func (api *Client) CreateChannelContext(ctx context.Context, channelName string) | ||||
| } | ||||
| 
 | ||||
| // GetChannelHistory retrieves the channel history | ||||
| // see https://api.slack.com/methods/channels.history | ||||
| func (api *Client) GetChannelHistory(channelID string, params HistoryParameters) (*History, error) { | ||||
| 	return api.GetChannelHistoryContext(context.Background(), channelID, params) | ||||
| func (api *Client) GetChannelHistory(channel string, params HistoryParameters) (*History, error) { | ||||
| 	return api.GetChannelHistoryContext(context.Background(), channel, params) | ||||
| } | ||||
| 
 | ||||
| // GetChannelHistoryContext retrieves the channel history with a custom context | ||||
| // see https://api.slack.com/methods/channels.history | ||||
| func (api *Client) GetChannelHistoryContext(ctx context.Context, channelID string, params HistoryParameters) (*History, error) { | ||||
| func (api *Client) GetChannelHistoryContext(ctx context.Context, channel string, params HistoryParameters) (*History, error) { | ||||
| 	values := url.Values{ | ||||
| 		"token":   {api.config.token}, | ||||
| 		"channel": {channelID}, | ||||
| 		"channel": {channel}, | ||||
| 	} | ||||
| 	if params.Latest != DEFAULT_HISTORY_LATEST { | ||||
| 		values.Add("latest", params.Latest) | ||||
| @@ -135,17 +133,15 @@ func (api *Client) GetChannelHistoryContext(ctx context.Context, channelID strin | ||||
| } | ||||
| 
 | ||||
| // GetChannelInfo retrieves the given channel | ||||
| // see https://api.slack.com/methods/channels.info | ||||
| func (api *Client) GetChannelInfo(channelID string) (*Channel, error) { | ||||
| 	return api.GetChannelInfoContext(context.Background(), channelID) | ||||
| func (api *Client) GetChannelInfo(channel string) (*Channel, error) { | ||||
| 	return api.GetChannelInfoContext(context.Background(), channel) | ||||
| } | ||||
| 
 | ||||
| // GetChannelInfoContext retrieves the given channel with a custom context | ||||
| // see https://api.slack.com/methods/channels.info | ||||
| func (api *Client) GetChannelInfoContext(ctx context.Context, channelID string) (*Channel, error) { | ||||
| func (api *Client) GetChannelInfoContext(ctx context.Context, channel string) (*Channel, error) { | ||||
| 	values := url.Values{ | ||||
| 		"token":   {api.config.token}, | ||||
| 		"channel": {channelID}, | ||||
| 		"channel": {channel}, | ||||
| 	} | ||||
| 	response, err := channelRequest(ctx, "channels.info", values, api.debug) | ||||
| 	if err != nil { | ||||
| @@ -155,17 +151,15 @@ func (api *Client) GetChannelInfoContext(ctx context.Context, channelID string) | ||||
| } | ||||
| 
 | ||||
| // InviteUserToChannel invites a user to a given channel and returns a *Channel | ||||
| // see https://api.slack.com/methods/channels.invite | ||||
| func (api *Client) InviteUserToChannel(channelID, user string) (*Channel, error) { | ||||
| 	return api.InviteUserToChannelContext(context.Background(), channelID, user) | ||||
| func (api *Client) InviteUserToChannel(channel, user string) (*Channel, error) { | ||||
| 	return api.InviteUserToChannelContext(context.Background(), channel, user) | ||||
| } | ||||
| 
 | ||||
| // InviteUserToChannelCustom invites a user to a given channel and returns a *Channel with a custom context | ||||
| // see https://api.slack.com/methods/channels.invite | ||||
| func (api *Client) InviteUserToChannelContext(ctx context.Context, channelID, user string) (*Channel, error) { | ||||
| func (api *Client) InviteUserToChannelContext(ctx context.Context, channel, user string) (*Channel, error) { | ||||
| 	values := url.Values{ | ||||
| 		"token":   {api.config.token}, | ||||
| 		"channel": {channelID}, | ||||
| 		"channel": {channel}, | ||||
| 		"user":    {user}, | ||||
| 	} | ||||
| 	response, err := channelRequest(ctx, "channels.invite", values, api.debug) | ||||
| @@ -176,17 +170,15 @@ func (api *Client) InviteUserToChannelContext(ctx context.Context, channelID, us | ||||
| } | ||||
| 
 | ||||
| // JoinChannel joins the currently authenticated user to a channel | ||||
| // see https://api.slack.com/methods/channels.join | ||||
| func (api *Client) JoinChannel(channelName string) (*Channel, error) { | ||||
| 	return api.JoinChannelContext(context.Background(), channelName) | ||||
| func (api *Client) JoinChannel(channel string) (*Channel, error) { | ||||
| 	return api.JoinChannelContext(context.Background(), channel) | ||||
| } | ||||
| 
 | ||||
| // JoinChannelContext joins the currently authenticated user to a channel with a custom context | ||||
| // see https://api.slack.com/methods/channels.join | ||||
| func (api *Client) JoinChannelContext(ctx context.Context, channelName string) (*Channel, error) { | ||||
| func (api *Client) JoinChannelContext(ctx context.Context, channel string) (*Channel, error) { | ||||
| 	values := url.Values{ | ||||
| 		"token": {api.config.token}, | ||||
| 		"name":  {channelName}, | ||||
| 		"name":  {channel}, | ||||
| 	} | ||||
| 	response, err := channelRequest(ctx, "channels.join", values, api.debug) | ||||
| 	if err != nil { | ||||
| @@ -196,17 +188,15 @@ func (api *Client) JoinChannelContext(ctx context.Context, channelName string) ( | ||||
| } | ||||
| 
 | ||||
| // LeaveChannel makes the authenticated user leave the given channel | ||||
| // see https://api.slack.com/methods/channels.leave | ||||
| func (api *Client) LeaveChannel(channelID string) (bool, error) { | ||||
| 	return api.LeaveChannelContext(context.Background(), channelID) | ||||
| func (api *Client) LeaveChannel(channel string) (bool, error) { | ||||
| 	return api.LeaveChannelContext(context.Background(), channel) | ||||
| } | ||||
| 
 | ||||
| // LeaveChannelContext makes the authenticated user leave the given channel with a custom context | ||||
| // see https://api.slack.com/methods/channels.leave | ||||
| func (api *Client) LeaveChannelContext(ctx context.Context, channelID string) (bool, error) { | ||||
| func (api *Client) LeaveChannelContext(ctx context.Context, channel string) (bool, error) { | ||||
| 	values := url.Values{ | ||||
| 		"token":   {api.config.token}, | ||||
| 		"channel": {channelID}, | ||||
| 		"channel": {channel}, | ||||
| 	} | ||||
| 	response, err := channelRequest(ctx, "channels.leave", values, api.debug) | ||||
| 	if err != nil { | ||||
| @@ -219,31 +209,30 @@ func (api *Client) LeaveChannelContext(ctx context.Context, channelID string) (b | ||||
| } | ||||
| 
 | ||||
| // KickUserFromChannel kicks a user from a given channel | ||||
| // see https://api.slack.com/methods/channels.kick | ||||
| func (api *Client) KickUserFromChannel(channelID, user string) error { | ||||
| 	return api.KickUserFromChannelContext(context.Background(), channelID, user) | ||||
| func (api *Client) KickUserFromChannel(channel, user string) error { | ||||
| 	return api.KickUserFromChannelContext(context.Background(), channel, user) | ||||
| } | ||||
| 
 | ||||
| // KickUserFromChannelContext kicks a user from a given channel with a custom context | ||||
| // see https://api.slack.com/methods/channels.kick | ||||
| func (api *Client) KickUserFromChannelContext(ctx context.Context, channelID, user string) error { | ||||
| func (api *Client) KickUserFromChannelContext(ctx context.Context, channel, user string) error { | ||||
| 	values := url.Values{ | ||||
| 		"token":   {api.config.token}, | ||||
| 		"channel": {channelID}, | ||||
| 		"channel": {channel}, | ||||
| 		"user":    {user}, | ||||
| 	} | ||||
| 	_, err := channelRequest(ctx, "channels.kick", values, api.debug) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // GetChannels retrieves all the channels | ||||
| // see https://api.slack.com/methods/channels.list | ||||
| func (api *Client) GetChannels(excludeArchived bool) ([]Channel, error) { | ||||
| 	return api.GetChannelsContext(context.Background(), excludeArchived) | ||||
| } | ||||
| 
 | ||||
| // GetChannelsContext retrieves all the channels with a custom context | ||||
| // see https://api.slack.com/methods/channels.list | ||||
| func (api *Client) GetChannelsContext(ctx context.Context, excludeArchived bool) ([]Channel, error) { | ||||
| 	values := url.Values{ | ||||
| 		"token": {api.config.token}, | ||||
| @@ -263,36 +252,35 @@ func (api *Client) GetChannelsContext(ctx context.Context, excludeArchived bool) | ||||
| // timer before making the call. In this way, any further updates needed during the timeout will not generate extra calls | ||||
| // (just one per channel). This is useful for when reading scroll-back history, or following a busy live channel. A | ||||
| // timeout of 5 seconds is a good starting point. Be sure to flush these calls on shutdown/logout. | ||||
| // see https://api.slack.com/methods/channels.mark | ||||
| func (api *Client) SetChannelReadMark(channelID, ts string) error { | ||||
| 	return api.SetChannelReadMarkContext(context.Background(), channelID, ts) | ||||
| func (api *Client) SetChannelReadMark(channel, ts string) error { | ||||
| 	return api.SetChannelReadMarkContext(context.Background(), channel, ts) | ||||
| } | ||||
| 
 | ||||
| // SetChannelReadMarkContext sets the read mark of a given channel to a specific point with a custom context | ||||
| // For more details see SetChannelReadMark documentation | ||||
| // see https://api.slack.com/methods/channels.mark | ||||
| func (api *Client) SetChannelReadMarkContext(ctx context.Context, channelID, ts string) error { | ||||
| func (api *Client) SetChannelReadMarkContext(ctx context.Context, channel, ts string) error { | ||||
| 	values := url.Values{ | ||||
| 		"token":   {api.config.token}, | ||||
| 		"channel": {channelID}, | ||||
| 		"channel": {channel}, | ||||
| 		"ts":      {ts}, | ||||
| 	} | ||||
| 	_, err := channelRequest(ctx, "channels.mark", values, api.debug) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // RenameChannel renames a given channel | ||||
| // see https://api.slack.com/methods/channels.rename | ||||
| func (api *Client) RenameChannel(channelID, name string) (*Channel, error) { | ||||
| 	return api.RenameChannelContext(context.Background(), channelID, name) | ||||
| func (api *Client) RenameChannel(channel, name string) (*Channel, error) { | ||||
| 	return api.RenameChannelContext(context.Background(), channel, name) | ||||
| } | ||||
| 
 | ||||
| // RenameChannelContext renames a given channel with a custom context | ||||
| // see https://api.slack.com/methods/channels.rename | ||||
| func (api *Client) RenameChannelContext(ctx context.Context, channelID, name string) (*Channel, error) { | ||||
| func (api *Client) RenameChannelContext(ctx context.Context, channel, name string) (*Channel, error) { | ||||
| 	values := url.Values{ | ||||
| 		"token":   {api.config.token}, | ||||
| 		"channel": {channelID}, | ||||
| 		"channel": {channel}, | ||||
| 		"name":    {name}, | ||||
| 	} | ||||
| 	// XXX: the created entry in this call returns a string instead of a number | ||||
| @@ -305,17 +293,15 @@ func (api *Client) RenameChannelContext(ctx context.Context, channelID, name str | ||||
| } | ||||
| 
 | ||||
| // SetChannelPurpose sets the channel purpose and returns the purpose that was successfully set | ||||
| // see https://api.slack.com/methods/channels.setPurpose | ||||
| func (api *Client) SetChannelPurpose(channelID, purpose string) (string, error) { | ||||
| 	return api.SetChannelPurposeContext(context.Background(), channelID, purpose) | ||||
| func (api *Client) SetChannelPurpose(channel, purpose string) (string, error) { | ||||
| 	return api.SetChannelPurposeContext(context.Background(), channel, purpose) | ||||
| } | ||||
| 
 | ||||
| // SetChannelPurposeContext sets the channel purpose and returns the purpose that was successfully set with a custom context | ||||
| // see https://api.slack.com/methods/channels.setPurpose | ||||
| func (api *Client) SetChannelPurposeContext(ctx context.Context, channelID, purpose string) (string, error) { | ||||
| func (api *Client) SetChannelPurposeContext(ctx context.Context, channel, purpose string) (string, error) { | ||||
| 	values := url.Values{ | ||||
| 		"token":   {api.config.token}, | ||||
| 		"channel": {channelID}, | ||||
| 		"channel": {channel}, | ||||
| 		"purpose": {purpose}, | ||||
| 	} | ||||
| 	response, err := channelRequest(ctx, "channels.setPurpose", values, api.debug) | ||||
| @@ -326,17 +312,15 @@ func (api *Client) SetChannelPurposeContext(ctx context.Context, channelID, purp | ||||
| } | ||||
| 
 | ||||
| // SetChannelTopic sets the channel topic and returns the topic that was successfully set | ||||
| // see https://api.slack.com/methods/channels.setTopic | ||||
| func (api *Client) SetChannelTopic(channelID, topic string) (string, error) { | ||||
| 	return api.SetChannelTopicContext(context.Background(), channelID, topic) | ||||
| func (api *Client) SetChannelTopic(channel, topic string) (string, error) { | ||||
| 	return api.SetChannelTopicContext(context.Background(), channel, topic) | ||||
| } | ||||
| 
 | ||||
| // SetChannelTopicContext sets the channel topic and returns the topic that was successfully set with a custom context | ||||
| // see https://api.slack.com/methods/channels.setTopic | ||||
| func (api *Client) SetChannelTopicContext(ctx context.Context, channelID, topic string) (string, error) { | ||||
| func (api *Client) SetChannelTopicContext(ctx context.Context, channel, topic string) (string, error) { | ||||
| 	values := url.Values{ | ||||
| 		"token":   {api.config.token}, | ||||
| 		"channel": {channelID}, | ||||
| 		"channel": {channel}, | ||||
| 		"topic":   {topic}, | ||||
| 	} | ||||
| 	response, err := channelRequest(ctx, "channels.setTopic", values, api.debug) | ||||
| @@ -347,17 +331,15 @@ func (api *Client) SetChannelTopicContext(ctx context.Context, channelID, topic | ||||
| } | ||||
| 
 | ||||
| // GetChannelReplies gets an entire thread (a message plus all the messages in reply to it). | ||||
| // see https://api.slack.com/methods/channels.replies | ||||
| func (api *Client) GetChannelReplies(channelID, thread_ts string) ([]Message, error) { | ||||
| 	return api.GetChannelRepliesContext(context.Background(), channelID, thread_ts) | ||||
| func (api *Client) GetChannelReplies(channel, thread_ts string) ([]Message, error) { | ||||
| 	return api.GetChannelRepliesContext(context.Background(), channel, thread_ts) | ||||
| } | ||||
| 
 | ||||
| // GetChannelRepliesContext gets an entire thread (a message plus all the messages in reply to it) with a custom context | ||||
| // see https://api.slack.com/methods/channels.replies | ||||
| func (api *Client) GetChannelRepliesContext(ctx context.Context, channelID, thread_ts string) ([]Message, error) { | ||||
| func (api *Client) GetChannelRepliesContext(ctx context.Context, channel, thread_ts string) ([]Message, error) { | ||||
| 	values := url.Values{ | ||||
| 		"token":     {api.config.token}, | ||||
| 		"channel":   {channelID}, | ||||
| 		"channel":   {channel}, | ||||
| 		"thread_ts": {thread_ts}, | ||||
| 	} | ||||
| 	response, err := channelRequest(ctx, "channels.replies", values, api.debug) | ||||
							
								
								
									
										56
									
								
								vendor/github.com/nlopes/slack/chat.go → vendor/github.com/matterbridge/slack/chat.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										56
									
								
								vendor/github.com/nlopes/slack/chat.go → vendor/github.com/matterbridge/slack/chat.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -11,7 +11,6 @@ import ( | ||||
| const ( | ||||
| 	DEFAULT_MESSAGE_USERNAME         = "" | ||||
| 	DEFAULT_MESSAGE_THREAD_TIMESTAMP = "" | ||||
| 	DEFAULT_MESSAGE_REPLY_BROADCAST  = false | ||||
| 	DEFAULT_MESSAGE_ASUSER           = false | ||||
| 	DEFAULT_MESSAGE_PARSE            = "" | ||||
| 	DEFAULT_MESSAGE_LINK_NAMES       = 0 | ||||
| @@ -37,7 +36,6 @@ type PostMessageParameters struct { | ||||
| 	AsUser          bool         `json:"as_user"` | ||||
| 	Parse           string       `json:"parse"` | ||||
| 	ThreadTimestamp string       `json:"thread_ts"` | ||||
| 	ReplyBroadcast  bool         `json:"reply_broadcast"` | ||||
| 	LinkNames       int          `json:"link_names"` | ||||
| 	Attachments     []Attachment `json:"attachments"` | ||||
| 	UnfurlLinks     bool         `json:"unfurl_links"` | ||||
| @@ -46,17 +44,12 @@ type PostMessageParameters struct { | ||||
| 	IconEmoji       string       `json:"icon_emoji"` | ||||
| 	Markdown        bool         `json:"mrkdwn,omitempty"` | ||||
| 	EscapeText      bool         `json:"escape_text"` | ||||
| 
 | ||||
| 	// chat.postEphemeral support | ||||
| 	Channel string `json:"channel"` | ||||
| 	User    string `json:"user"` | ||||
| } | ||||
| 
 | ||||
| // NewPostMessageParameters provides an instance of PostMessageParameters with all the sane default values set | ||||
| func NewPostMessageParameters() PostMessageParameters { | ||||
| 	return PostMessageParameters{ | ||||
| 		Username:    DEFAULT_MESSAGE_USERNAME, | ||||
| 		User:        DEFAULT_MESSAGE_USERNAME, | ||||
| 		AsUser:      DEFAULT_MESSAGE_ASUSER, | ||||
| 		Parse:       DEFAULT_MESSAGE_PARSE, | ||||
| 		LinkNames:   DEFAULT_MESSAGE_LINK_NAMES, | ||||
| @@ -109,37 +102,6 @@ func (api *Client) PostMessageContext(ctx context.Context, channel, text string, | ||||
| 	return respChannel, respTimestamp, err | ||||
| } | ||||
| 
 | ||||
| // PostEphemeral sends an ephemeral message to a user in a channel. | ||||
| // Message is escaped by default according to https://api.slack.com/docs/formatting | ||||
| // Use http://davestevens.github.io/slack-message-builder/ to help crafting your message. | ||||
| func (api *Client) PostEphemeral(channel, userID string, options ...MsgOption) (string, error) { | ||||
| 	options = append(options, MsgOptionPostEphemeral()) | ||||
| 	return api.PostEphemeralContext( | ||||
| 		context.Background(), | ||||
| 		channel, | ||||
| 		userID, | ||||
| 		options..., | ||||
| 	) | ||||
| } | ||||
| 
 | ||||
| // PostEphemeralContext sends an ephemeal message to a user in a channel with a custom context | ||||
| // For more details, see PostEphemeral documentation | ||||
| func (api *Client) PostEphemeralContext(ctx context.Context, channel, userID string, options ...MsgOption) (string, error) { | ||||
| 	path, values, err := ApplyMsgOptions(api.config.token, channel, options...) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 
 | ||||
| 	values.Add("user", userID) | ||||
| 
 | ||||
| 	response, err := chatRequest(ctx, path, values, api.debug) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 
 | ||||
| 	return response.Timestamp, nil | ||||
| } | ||||
| 
 | ||||
| // UpdateMessage updates a message in a channel | ||||
| func (api *Client) UpdateMessage(channel, timestamp, text string) (string, string, string, error) { | ||||
| 	return api.UpdateMessageContext(context.Background(), channel, timestamp, text) | ||||
| @@ -212,7 +174,6 @@ const ( | ||||
| 	chatUpdate      sendMode = "chat.update" | ||||
| 	chatPostMessage sendMode = "chat.postMessage" | ||||
| 	chatDelete      sendMode = "chat.delete" | ||||
| 	chatPostEphemeral sendMode = "chat.postEphemeral" | ||||
| ) | ||||
| 
 | ||||
| type sendConfig struct { | ||||
| @@ -232,15 +193,6 @@ func MsgOptionPost() MsgOption { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // MsgOptionPostEphemeral posts an ephemeral message | ||||
| func MsgOptionPostEphemeral() MsgOption { | ||||
| 	return func(config *sendConfig) error { | ||||
| 		config.mode = chatPostEphemeral | ||||
| 		config.values.Del("ts") | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // MsgOptionUpdate updates a message based on the timestamp. | ||||
| func MsgOptionUpdate(timestamp string) MsgOption { | ||||
| 	return func(config *sendConfig) error { | ||||
| @@ -327,11 +279,6 @@ func MsgOptionPostMessageParameters(params PostMessageParameters) MsgOption { | ||||
| 			config.values.Set("username", string(params.Username)) | ||||
| 		} | ||||
| 
 | ||||
| 		// chat.postEphemeral support | ||||
| 		if params.User != DEFAULT_MESSAGE_USERNAME { | ||||
| 			config.values.Set("user", params.User) | ||||
| 		} | ||||
| 
 | ||||
| 		// never generates an error. | ||||
| 		MsgOptionAsUser(params.AsUser)(config) | ||||
| 
 | ||||
| @@ -367,9 +314,6 @@ func MsgOptionPostMessageParameters(params PostMessageParameters) MsgOption { | ||||
| 		if params.ThreadTimestamp != DEFAULT_MESSAGE_THREAD_TIMESTAMP { | ||||
| 			config.values.Set("thread_ts", params.ThreadTimestamp) | ||||
| 		} | ||||
| 		if params.ReplyBroadcast != DEFAULT_MESSAGE_REPLY_BROADCAST { | ||||
| 			config.values.Set("reply_broadcast", "true") | ||||
| 		} | ||||
| 
 | ||||
| 		return nil | ||||
| 	} | ||||
							
								
								
									
										0
									
								
								vendor/github.com/nlopes/slack/dnd.go → vendor/github.com/matterbridge/slack/dnd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								vendor/github.com/nlopes/slack/dnd.go → vendor/github.com/matterbridge/slack/dnd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -267,7 +267,10 @@ func (api *Client) DeleteFileContext(ctx context.Context, fileID string) error { | ||||
| 		"file":  {fileID}, | ||||
| 	} | ||||
| 	_, err := fileRequest(ctx, "files.delete", values, api.debug) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| @@ -208,8 +208,11 @@ func (api *Client) LeaveGroupContext(ctx context.Context, group string) error { | ||||
| 		"channel": {group}, | ||||
| 	} | ||||
| 	_, err := groupRequest(ctx, "groups.leave", values, api.debug) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // KickUserFromGroup kicks a user from a group | ||||
| func (api *Client) KickUserFromGroup(group, user string) error { | ||||
| @@ -224,8 +227,11 @@ func (api *Client) KickUserFromGroupContext(ctx context.Context, group, user str | ||||
| 		"user":    {user}, | ||||
| 	} | ||||
| 	_, err := groupRequest(ctx, "groups.kick", values, api.debug) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // GetGroups retrieves all groups | ||||
| func (api *Client) GetGroups(excludeArchived bool) ([]Group, error) { | ||||
| @@ -283,8 +289,11 @@ func (api *Client) SetGroupReadMarkContext(ctx context.Context, group, ts string | ||||
| 		"ts":      {ts}, | ||||
| 	} | ||||
| 	_, err := groupRequest(ctx, "groups.mark", values, api.debug) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // OpenGroup opens a private group | ||||
| func (api *Client) OpenGroup(group string) (bool, bool, error) { | ||||
							
								
								
									
										0
									
								
								vendor/github.com/nlopes/slack/im.go → vendor/github.com/matterbridge/slack/im.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								vendor/github.com/nlopes/slack/im.go → vendor/github.com/matterbridge/slack/im.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -3,7 +3,6 @@ package slack | ||||
| // OutgoingMessage is used for the realtime API, and seems incomplete. | ||||
| type OutgoingMessage struct { | ||||
| 	ID              int    `json:"id"` | ||||
| 	// channel ID | ||||
| 	Channel         string `json:"channel,omitempty"` | ||||
| 	Text            string `json:"text,omitempty"` | ||||
| 	Type            string `json:"type,omitempty"` | ||||
| @@ -122,12 +121,12 @@ type Pong struct { | ||||
| // NewOutgoingMessage prepares an OutgoingMessage that the user can | ||||
| // use to send a message. Use this function to properly set the | ||||
| // messageID. | ||||
| func (rtm *RTM) NewOutgoingMessage(text string, channelID string) *OutgoingMessage { | ||||
| func (rtm *RTM) NewOutgoingMessage(text string, channel string) *OutgoingMessage { | ||||
| 	id := rtm.idGen.Next() | ||||
| 	return &OutgoingMessage{ | ||||
| 		ID:      id, | ||||
| 		Type:    "message", | ||||
| 		Channel: channelID, | ||||
| 		Channel: channel, | ||||
| 		Text:    text, | ||||
| 	} | ||||
| } | ||||
| @@ -135,11 +134,11 @@ func (rtm *RTM) NewOutgoingMessage(text string, channelID string) *OutgoingMessa | ||||
| // NewTypingMessage prepares an OutgoingMessage that the user can | ||||
| // use to send as a typing indicator. Use this function to properly set the | ||||
| // messageID. | ||||
| func (rtm *RTM) NewTypingMessage(channelID string) *OutgoingMessage { | ||||
| func (rtm *RTM) NewTypingMessage(channel string) *OutgoingMessage { | ||||
| 	id := rtm.idGen.Next() | ||||
| 	return &OutgoingMessage{ | ||||
| 		ID:      id, | ||||
| 		Type:    "typing", | ||||
| 		Channel: channelID, | ||||
| 		Channel: channel, | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										36
									
								
								vendor/github.com/nlopes/slack/misc.go → vendor/github.com/matterbridge/slack/misc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										36
									
								
								vendor/github.com/nlopes/slack/misc.go → vendor/github.com/matterbridge/slack/misc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -13,7 +13,6 @@ import ( | ||||
| 	"net/url" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
| @@ -43,14 +42,6 @@ func (s WebError) Error() string { | ||||
| 	return string(s) | ||||
| } | ||||
| 
 | ||||
| type RateLimitedError struct { | ||||
| 	RetryAfter time.Duration | ||||
| } | ||||
| 
 | ||||
| func (e *RateLimitedError) Error() string { | ||||
| 	return fmt.Sprintf("Slack rate limit exceeded, retry after %s", e.RetryAfter) | ||||
| } | ||||
| 
 | ||||
| func fileUploadReq(ctx context.Context, path, fieldname, filename string, values url.Values, r io.Reader) (*http.Request, error) { | ||||
| 	body := &bytes.Buffer{} | ||||
| 	wr := multipart.NewWriter(body) | ||||
| @@ -88,7 +79,12 @@ func parseResponseBody(body io.ReadCloser, intf *interface{}, debug bool) error | ||||
| 		logger.Printf("parseResponseBody: %s\n", string(response)) | ||||
| 	} | ||||
| 
 | ||||
| 	return json.Unmarshal(response, &intf) | ||||
| 	err = json.Unmarshal(response, &intf) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func postLocalWithMultipartResponse(ctx context.Context, path, fpath, fieldname string, values url.Values, intf interface{}, debug bool) error { | ||||
| @@ -116,16 +112,8 @@ func postWithMultipartResponse(ctx context.Context, path, name, fieldname string | ||||
| 	} | ||||
| 	defer resp.Body.Close() | ||||
| 
 | ||||
| 	if resp.StatusCode == http.StatusTooManyRequests { | ||||
| 		retry, err := strconv.ParseInt(resp.Header.Get("Retry-After"), 10, 64) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		return &RateLimitedError{time.Duration(retry) * time.Second} | ||||
| 	} | ||||
| 
 | ||||
| 	// Slack seems to send an HTML body along with 5xx error codes. Don't parse it. | ||||
| 	if resp.StatusCode != http.StatusOK { | ||||
| 	if resp.StatusCode != 200 { | ||||
| 		logResponse(resp, debug) | ||||
| 		return fmt.Errorf("Slack server error: %s.", resp.Status) | ||||
| 	} | ||||
| @@ -148,16 +136,8 @@ func postForm(ctx context.Context, endpoint string, values url.Values, intf inte | ||||
| 	} | ||||
| 	defer resp.Body.Close() | ||||
| 
 | ||||
| 	if resp.StatusCode == http.StatusTooManyRequests { | ||||
| 		retry, err := strconv.ParseInt(resp.Header.Get("Retry-After"), 10, 64) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		return &RateLimitedError{time.Duration(retry) * time.Second} | ||||
| 	} | ||||
| 
 | ||||
| 	// Slack seems to send an HTML body along with 5xx error codes. Don't parse it. | ||||
| 	if resp.StatusCode != http.StatusOK { | ||||
| 	if resp.StatusCode != 200 { | ||||
| 		logResponse(resp, debug) | ||||
| 		return fmt.Errorf("Slack server error: %s.", resp.Status) | ||||
| 	} | ||||
							
								
								
									
										23
									
								
								vendor/github.com/nlopes/slack/rtm.go → vendor/github.com/matterbridge/slack/rtm.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/nlopes/slack/rtm.go → vendor/github.com/matterbridge/slack/rtm.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -27,8 +27,17 @@ func (api *Client) StartRTMContext(ctx context.Context) (info *Info, websocketUR | ||||
| 	if !response.Ok { | ||||
| 		return nil, "", response.Error | ||||
| 	} | ||||
| 
 | ||||
| 	// websocket.Dial does not accept url without the port (yet) | ||||
| 	// Fixed by: https://github.com/golang/net/commit/5058c78c3627b31e484a81463acd51c7cecc06f3 | ||||
| 	// but slack returns the address with no port, so we have to fix it | ||||
| 	api.Debugln("Using URL:", response.Info.URL) | ||||
| 	return &response.Info, response.Info.URL, nil | ||||
| 	websocketURL, err = websocketizeURLPort(response.Info.URL) | ||||
| 	if err != nil { | ||||
| 		return nil, "", fmt.Errorf("parsing response URL: %s", err) | ||||
| 	} | ||||
| 
 | ||||
| 	return &response.Info, websocketURL, nil | ||||
| } | ||||
| 
 | ||||
| // ConnectRTM calls the "rtm.connect" endpoint and returns the provided URL and the compact Info block. | ||||
| @@ -50,8 +59,17 @@ func (api *Client) ConnectRTMContext(ctx context.Context) (info *Info, websocket | ||||
| 	if !response.Ok { | ||||
| 		return nil, "", response.Error | ||||
| 	} | ||||
| 
 | ||||
| 	// websocket.Dial does not accept url without the port (yet) | ||||
| 	// Fixed by: https://github.com/golang/net/commit/5058c78c3627b31e484a81463acd51c7cecc06f3 | ||||
| 	// but slack returns the address with no port, so we have to fix it | ||||
| 	api.Debugln("Using URL:", response.Info.URL) | ||||
| 	return &response.Info, response.Info.URL, nil | ||||
| 	websocketURL, err = websocketizeURLPort(response.Info.URL) | ||||
| 	if err != nil { | ||||
| 		return nil, "", fmt.Errorf("parsing response URL: %s", err) | ||||
| 	} | ||||
| 
 | ||||
| 	return &response.Info, websocketURL, nil | ||||
| } | ||||
| 
 | ||||
| // NewRTM returns a RTM, which provides a fully managed connection to | ||||
| @@ -72,7 +90,6 @@ func (api *Client) NewRTMWithOptions(options *RTMOptions) *RTM { | ||||
| 		isConnected:      false, | ||||
| 		wasIntentional:   true, | ||||
| 		killChannel:      make(chan bool), | ||||
| 		disconnected:     make(chan struct{}), | ||||
| 		forcePing:        make(chan bool), | ||||
| 		rawEvents:        make(chan json.RawMessage), | ||||
| 		idGen:            NewSafeID(1), | ||||
							
								
								
									
										28
									
								
								vendor/github.com/nlopes/slack/slack.go → vendor/github.com/matterbridge/slack/slack.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								vendor/github.com/nlopes/slack/slack.go → vendor/github.com/matterbridge/slack/slack.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -3,13 +3,12 @@ package slack | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"net/url" | ||||
| 	"os" | ||||
| ) | ||||
| 
 | ||||
| var logger stdLogger // A logger that can be set by consumers | ||||
| var logger *log.Logger // A logger that can be set by consumers | ||||
| /* | ||||
|   Added as a var so that we can change this for testing purposes | ||||
| */ | ||||
| @@ -42,31 +41,12 @@ type Client struct { | ||||
| 	debug bool | ||||
| } | ||||
| 
 | ||||
| // stdLogger is a logger interface compatible with both stdlib and some | ||||
| // 3rd party loggers such as logrus. | ||||
| type stdLogger interface { | ||||
| 	Print(...interface{}) | ||||
| 	Printf(string, ...interface{}) | ||||
| 	Println(...interface{}) | ||||
| 
 | ||||
| 	Fatal(...interface{}) | ||||
| 	Fatalf(string, ...interface{}) | ||||
| 	Fatalln(...interface{}) | ||||
| 
 | ||||
| 	Panic(...interface{}) | ||||
| 	Panicf(string, ...interface{}) | ||||
| 	Panicln(...interface{}) | ||||
| 
 | ||||
| 	Output(int, string) error | ||||
| } | ||||
| 
 | ||||
| // SetLogger let's library users supply a logger, so that api debugging | ||||
| // can be logged along with the application's debugging info. | ||||
| func SetLogger(l stdLogger) { | ||||
| func SetLogger(l *log.Logger) { | ||||
| 	logger = l | ||||
| } | ||||
| 
 | ||||
| // New creates new Client. | ||||
| func New(token string) *Client { | ||||
| 	s := &Client{} | ||||
| 	s.config.token = token | ||||
| @@ -103,12 +83,12 @@ func (api *Client) SetDebug(debug bool) { | ||||
| 
 | ||||
| func (api *Client) Debugf(format string, v ...interface{}) { | ||||
| 	if api.debug { | ||||
| 		logger.Output(2, fmt.Sprintf(format, v...)) | ||||
| 		logger.Printf(format, v...) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (api *Client) Debugln(v ...interface{}) { | ||||
| 	if api.debug { | ||||
| 		logger.Output(2, fmt.Sprintln(v...)) | ||||
| 		logger.Println(v...) | ||||
| 	} | ||||
| } | ||||
| @@ -200,8 +200,11 @@ func (api *Client) SetUserAsActiveContext(ctx context.Context) error { | ||||
| 		"token": {api.config.token}, | ||||
| 	} | ||||
| 	_, err := userRequest(ctx, "users.setActive", values, api.debug) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // SetUserPresence changes the currently authenticated user presence | ||||
| func (api *Client) SetUserPresence(presence string) error { | ||||
| @@ -244,8 +247,8 @@ func (api *Client) GetUserIdentityContext(ctx context.Context) (*UserIdentityRes | ||||
| } | ||||
| 
 | ||||
| // SetUserPhoto changes the currently authenticated user's profile image | ||||
| func (api *Client) SetUserPhoto(image string, params UserSetPhotoParams) error { | ||||
| 	return api.SetUserPhotoContext(context.Background(), image, params) | ||||
| func (api *Client) SetUserPhoto(ctx context.Context, image string, params UserSetPhotoParams) error { | ||||
| 	return api.SetUserPhoto(context.Background(), image, params) | ||||
| } | ||||
| 
 | ||||
| // SetUserPhotoContext changes the currently authenticated user's profile image using a custom context | ||||
| @@ -27,7 +27,6 @@ type RTM struct { | ||||
| 	IncomingEvents   chan RTMEvent | ||||
| 	outgoingMessages chan OutgoingMessage | ||||
| 	killChannel      chan bool | ||||
| 	disconnected     chan struct{} // disconnected is closed when Disconnect is invoked, regardless of connection state. Allows for ManagedConnection to not leak. | ||||
| 	forcePing        chan bool | ||||
| 	rawEvents        chan json.RawMessage | ||||
| 	wasIntentional   bool | ||||
| @@ -60,14 +59,9 @@ type RTMOptions struct { | ||||
| 
 | ||||
| // Disconnect and wait, blocking until a successful disconnection. | ||||
| func (rtm *RTM) Disconnect() error { | ||||
| 	// this channel is always closed on disconnect. lets the ManagedConnection() function | ||||
| 	// properly clean up. | ||||
| 	close(rtm.disconnected) | ||||
| 
 | ||||
| 	if !rtm.isConnected { | ||||
| 		return errors.New("Invalid call to Disconnect - Slack API is already disconnected") | ||||
| 	} | ||||
| 
 | ||||
| 	rtm.killChannel <- true | ||||
| 	return nil | ||||
| } | ||||
| @@ -99,15 +99,6 @@ func (rtm *RTM) connect(connectionCount int, useRTMStart bool) (*Info, *websocke | ||||
| 			Attempt:  boff.attempts, | ||||
| 			ErrorObj: err, | ||||
| 		}} | ||||
| 
 | ||||
| 		// check if Disconnect() has been invoked. | ||||
| 		select { | ||||
| 		case _ = <-rtm.disconnected: | ||||
| 			rtm.IncomingEvents <- RTMEvent{"disconnected", &DisconnectedEvent{Intentional: true}} | ||||
| 			return nil, nil, fmt.Errorf("disconnect received while trying to connect") | ||||
| 		default: | ||||
| 		} | ||||
| 
 | ||||
| 		// get time we should wait before attempting to connect again | ||||
| 		dur := boff.Duration() | ||||
| 		rtm.Debugf("reconnection %d failed: %s", boff.attempts+1, err) | ||||
| @@ -133,8 +124,7 @@ func (rtm *RTM) startRTMAndDial(useRTMStart bool) (*Info, *websocket.Conn, error | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Only use HTTPS for connections to prevent MITM attacks on the connection. | ||||
| 	conn, err := websocketProxyDial(url, "https://api.slack.com") | ||||
| 	conn, err := websocketProxyDial(url, "http://api.slack.com") | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| @@ -327,13 +317,10 @@ func (rtm *RTM) handleAck(event json.RawMessage) { | ||||
| 		rtm.Debugln(" -> Erroneous 'ack' event:", string(event)) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if ack.Ok { | ||||
| 		rtm.IncomingEvents <- RTMEvent{"ack", ack} | ||||
| 	} else if ack.RTMResponse.Error != nil { | ||||
| 		rtm.IncomingEvents <- RTMEvent{"ack_error", &AckErrorEvent{ack.Error}} | ||||
| 	} else { | ||||
| 		rtm.IncomingEvents <- RTMEvent{"ack_error", &AckErrorEvent{fmt.Errorf("ack decode failure")}} | ||||
| 		rtm.IncomingEvents <- RTMEvent{"ack_error", &AckErrorEvent{ack.Error}} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @@ -32,7 +32,8 @@ func websocketHTTPConnect(proxy, urlString string) (net.Conn, error) { | ||||
| 	} | ||||
| 
 | ||||
| 	cc := httputil.NewProxyClientConn(p, nil) | ||||
| 	if _, err := cc.Do(&req); err != nil { | ||||
| 	cc.Do(&req) | ||||
| 	if err != nil && err != httputil.ErrPersistEOF { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
							
								
								
									
										20
									
								
								vendor/github.com/matterbridge/slack/websocket_utils.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/matterbridge/slack/websocket_utils.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| package slack | ||||
|  | ||||
| import ( | ||||
| 	"net" | ||||
| 	"net/url" | ||||
| ) | ||||
|  | ||||
| var portMapping = map[string]string{"ws": "80", "wss": "443"} | ||||
|  | ||||
| func websocketizeURLPort(orig string) (string, error) { | ||||
| 	urlObj, err := url.ParseRequestURI(orig) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	_, _, err = net.SplitHostPort(urlObj.Host) | ||||
| 	if err != nil { | ||||
| 		return urlObj.Scheme + "://" + urlObj.Host + ":" + portMapping[urlObj.Scheme] + urlObj.Path, nil | ||||
| 	} | ||||
| 	return orig, nil | ||||
| } | ||||
							
								
								
									
										21
									
								
								vendor/github.com/nlopes/slack/examples/channels/channels.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/nlopes/slack/examples/channels/channels.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,21 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/nlopes/slack" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	api := slack.New("YOUR_TOKEN_HERE") | ||||
| 	channels, err := api.GetChannels(false) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("%s\n", err) | ||||
| 		return | ||||
| 	} | ||||
| 	for _, channel := range channels { | ||||
| 		fmt.Println(channel.Name) | ||||
| 		// channel is of type conversation & groupConversation | ||||
| 		// see all available methods in `conversation.go` | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										30
									
								
								vendor/github.com/nlopes/slack/examples/files/files.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/nlopes/slack/examples/files/files.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,30 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/nlopes/slack" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	api := slack.New("YOUR_TOKEN_HERE") | ||||
| 	params := slack.FileUploadParameters{ | ||||
| 		Title: "Batman Example", | ||||
| 		//Filetype: "txt", | ||||
| 		File: "example.txt", | ||||
| 		//Content:  "Nan Nan Nan Nan Nan Nan Nan Nan Batman", | ||||
| 	} | ||||
| 	file, err := api.UploadFile(params) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("%s\n", err) | ||||
| 		return | ||||
| 	} | ||||
| 	fmt.Printf("Name: %s, URL: %s\n", file.Name, file.URL) | ||||
|  | ||||
| 	err = api.DeleteFile(file.ID) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("%s\n", err) | ||||
| 		return | ||||
| 	} | ||||
| 	fmt.Printf("File %s deleted successfully.\n", file.Name) | ||||
| } | ||||
							
								
								
									
										22
									
								
								vendor/github.com/nlopes/slack/examples/groups/groups.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/nlopes/slack/examples/groups/groups.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,22 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/nlopes/slack" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	api := slack.New("YOUR_TOKEN_HERE") | ||||
| 	// If you set debugging, it will log all requests to the console | ||||
| 	// Useful when encountering issues | ||||
| 	// api.SetDebug(true) | ||||
| 	groups, err := api.GetGroups(false) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("%s\n", err) | ||||
| 		return | ||||
| 	} | ||||
| 	for _, group := range groups { | ||||
| 		fmt.Printf("ID: %s, Name: %s\n", group.ID, group.Name) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										21
									
								
								vendor/github.com/nlopes/slack/examples/ims/ims.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/nlopes/slack/examples/ims/ims.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,21 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/nlopes/slack" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	api := slack.New("YOUR_TOKEN_HERE") | ||||
|  | ||||
| 	userID := "USER_ID" | ||||
|  | ||||
| 	_, _, channelID, err := api.OpenIMChannel(userID) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("%s\n", err) | ||||
| 	} | ||||
|  | ||||
| 	api.PostMessage(channelID, "Hello World!", slack.PostMessageParameters{}) | ||||
| } | ||||
							
								
								
									
										32
									
								
								vendor/github.com/nlopes/slack/examples/messages/messages.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										32
									
								
								vendor/github.com/nlopes/slack/examples/messages/messages.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,32 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/nlopes/slack" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	api := slack.New("YOUR_TOKEN_HERE") | ||||
| 	params := slack.PostMessageParameters{} | ||||
| 	attachment := slack.Attachment{ | ||||
| 		Pretext: "some pretext", | ||||
| 		Text:    "some text", | ||||
| 		// Uncomment the following part to send a field too | ||||
| 		/* | ||||
| 			Fields: []slack.AttachmentField{ | ||||
| 				slack.AttachmentField{ | ||||
| 					Title: "a", | ||||
| 					Value: "no", | ||||
| 				}, | ||||
| 			}, | ||||
| 		*/ | ||||
| 	} | ||||
| 	params.Attachments = []slack.Attachment{attachment} | ||||
| 	channelID, timestamp, err := api.PostMessage("CHANNEL_ID", "Some text", params) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("%s\n", err) | ||||
| 		return | ||||
| 	} | ||||
| 	fmt.Printf("Message successfully sent to channel %s at %s", channelID, timestamp) | ||||
| } | ||||
							
								
								
									
										123
									
								
								vendor/github.com/nlopes/slack/examples/pins/pins.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										123
									
								
								vendor/github.com/nlopes/slack/examples/pins/pins.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,123 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/nlopes/slack" | ||||
| ) | ||||
|  | ||||
| /* | ||||
|    WARNING: This example is destructive in the sense that it create a channel called testpinning | ||||
| */ | ||||
| func main() { | ||||
| 	var ( | ||||
| 		apiToken string | ||||
| 		debug    bool | ||||
| 	) | ||||
|  | ||||
| 	flag.StringVar(&apiToken, "token", "YOUR_TOKEN_HERE", "Your Slack API Token") | ||||
| 	flag.BoolVar(&debug, "debug", false, "Show JSON output") | ||||
| 	flag.Parse() | ||||
|  | ||||
| 	api := slack.New(apiToken) | ||||
| 	if debug { | ||||
| 		api.SetDebug(true) | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		postAsUserName  string | ||||
| 		postAsUserID    string | ||||
| 		postToChannelID string | ||||
| 	) | ||||
|  | ||||
| 	// Find the user to post as. | ||||
| 	authTest, err := api.AuthTest() | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error getting channels: %s\n", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	channelName := "testpinning" | ||||
|  | ||||
| 	// Post as the authenticated user. | ||||
| 	postAsUserName = authTest.User | ||||
| 	postAsUserID = authTest.UserID | ||||
|  | ||||
| 	// Create a temporary channel | ||||
| 	channel, err := api.CreateChannel(channelName) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		// If the channel exists, that means we just need to unarchive it | ||||
| 		if err.Error() == "name_taken" { | ||||
| 			err = nil | ||||
| 			channels, err := api.GetChannels(false) | ||||
| 			if err != nil { | ||||
| 				fmt.Println("Could not retrieve channels") | ||||
| 				return | ||||
| 			} | ||||
| 			for _, archivedChannel := range channels { | ||||
| 				if archivedChannel.Name == channelName { | ||||
| 					if archivedChannel.IsArchived { | ||||
| 						err = api.UnarchiveChannel(archivedChannel.ID) | ||||
| 						if err != nil { | ||||
| 							fmt.Printf("Could not unarchive %s: %s\n", archivedChannel.ID, err) | ||||
| 							return | ||||
| 						} | ||||
| 					} | ||||
| 					channel = &archivedChannel | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			fmt.Printf("Error setting test channel for pinning: %s\n", err) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	postToChannelID = channel.ID | ||||
|  | ||||
| 	fmt.Printf("Posting as %s (%s) in channel %s\n", postAsUserName, postAsUserID, postToChannelID) | ||||
|  | ||||
| 	// Post a message. | ||||
| 	postParams := slack.PostMessageParameters{} | ||||
| 	channelID, timestamp, err := api.PostMessage(postToChannelID, "Is this any good?", postParams) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error posting message: %s\n", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Grab a reference to the message. | ||||
| 	msgRef := slack.NewRefToMessage(channelID, timestamp) | ||||
|  | ||||
| 	// Add message pin to channel | ||||
| 	if err := api.AddPin(channelID, msgRef); err != nil { | ||||
| 		fmt.Printf("Error adding pin: %s\n", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// List all of the users pins. | ||||
| 	listPins, _, err := api.ListPins(channelID) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error listing pins: %s\n", err) | ||||
| 		return | ||||
| 	} | ||||
| 	fmt.Printf("\n") | ||||
| 	fmt.Printf("All pins by %s...\n", authTest.User) | ||||
| 	for _, item := range listPins { | ||||
| 		fmt.Printf(" > Item type: %s\n", item.Type) | ||||
| 	} | ||||
|  | ||||
| 	// Remove the pin. | ||||
| 	err = api.RemovePin(channelID, msgRef) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error remove pin: %s\n", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if err = api.ArchiveChannel(channelID); err != nil { | ||||
| 		fmt.Printf("Error archiving channel: %s\n", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| } | ||||
							
								
								
									
										126
									
								
								vendor/github.com/nlopes/slack/examples/reactions/reactions.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										126
									
								
								vendor/github.com/nlopes/slack/examples/reactions/reactions.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,126 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/nlopes/slack" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	var ( | ||||
| 		apiToken string | ||||
| 		debug    bool | ||||
| 	) | ||||
|  | ||||
| 	flag.StringVar(&apiToken, "token", "YOUR_TOKEN_HERE", "Your Slack API Token") | ||||
| 	flag.BoolVar(&debug, "debug", false, "Show JSON output") | ||||
| 	flag.Parse() | ||||
|  | ||||
| 	api := slack.New(apiToken) | ||||
| 	if debug { | ||||
| 		api.SetDebug(true) | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		postAsUserName  string | ||||
| 		postAsUserID    string | ||||
| 		postToUserName  string | ||||
| 		postToUserID    string | ||||
| 		postToChannelID string | ||||
| 	) | ||||
|  | ||||
| 	// Find the user to post as. | ||||
| 	authTest, err := api.AuthTest() | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error getting channels: %s\n", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Post as the authenticated user. | ||||
| 	postAsUserName = authTest.User | ||||
| 	postAsUserID = authTest.UserID | ||||
|  | ||||
| 	// Posting to DM with self causes a conversation with slackbot. | ||||
| 	postToUserName = authTest.User | ||||
| 	postToUserID = authTest.UserID | ||||
|  | ||||
| 	// Find the channel. | ||||
| 	_, _, chanID, err := api.OpenIMChannel(postToUserID) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error opening IM: %s\n", err) | ||||
| 		return | ||||
| 	} | ||||
| 	postToChannelID = chanID | ||||
|  | ||||
| 	fmt.Printf("Posting as %s (%s) in DM with %s (%s), channel %s\n", postAsUserName, postAsUserID, postToUserName, postToUserID, postToChannelID) | ||||
|  | ||||
| 	// Post a message. | ||||
| 	postParams := slack.PostMessageParameters{} | ||||
| 	channelID, timestamp, err := api.PostMessage(postToChannelID, "Is this any good?", postParams) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error posting message: %s\n", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Grab a reference to the message. | ||||
| 	msgRef := slack.NewRefToMessage(channelID, timestamp) | ||||
|  | ||||
| 	// React with :+1: | ||||
| 	if err := api.AddReaction("+1", msgRef); err != nil { | ||||
| 		fmt.Printf("Error adding reaction: %s\n", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// React with :-1: | ||||
| 	if err := api.AddReaction("cry", msgRef); err != nil { | ||||
| 		fmt.Printf("Error adding reaction: %s\n", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Get all reactions on the message. | ||||
| 	msgReactions, err := api.GetReactions(msgRef, slack.NewGetReactionsParameters()) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error getting reactions: %s\n", err) | ||||
| 		return | ||||
| 	} | ||||
| 	fmt.Printf("\n") | ||||
| 	fmt.Printf("%d reactions to message...\n", len(msgReactions)) | ||||
| 	for _, r := range msgReactions { | ||||
| 		fmt.Printf("  %d users say %s\n", r.Count, r.Name) | ||||
| 	} | ||||
|  | ||||
| 	// List all of the users reactions. | ||||
| 	listReactions, _, err := api.ListReactions(slack.NewListReactionsParameters()) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error listing reactions: %s\n", err) | ||||
| 		return | ||||
| 	} | ||||
| 	fmt.Printf("\n") | ||||
| 	fmt.Printf("All reactions by %s...\n", authTest.User) | ||||
| 	for _, item := range listReactions { | ||||
| 		fmt.Printf("%d on a %s...\n", len(item.Reactions), item.Type) | ||||
| 		for _, r := range item.Reactions { | ||||
| 			fmt.Printf("  %s (along with %d others)\n", r.Name, r.Count-1) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Remove the :cry: reaction. | ||||
| 	err = api.RemoveReaction("cry", msgRef) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error remove reaction: %s\n", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Get all reactions on the message. | ||||
| 	msgReactions, err = api.GetReactions(msgRef, slack.NewGetReactionsParameters()) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error getting reactions: %s\n", err) | ||||
| 		return | ||||
| 	} | ||||
| 	fmt.Printf("\n") | ||||
| 	fmt.Printf("%d reactions to message after removing cry...\n", len(msgReactions)) | ||||
| 	for _, r := range msgReactions { | ||||
| 		fmt.Printf("  %d users say %s\n", r.Count, r.Name) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										46
									
								
								vendor/github.com/nlopes/slack/examples/stars/stars.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										46
									
								
								vendor/github.com/nlopes/slack/examples/stars/stars.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,46 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/nlopes/slack" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	var ( | ||||
| 		apiToken string | ||||
| 		debug    bool | ||||
| 	) | ||||
|  | ||||
| 	flag.StringVar(&apiToken, "token", "YOUR_TOKEN_HERE", "Your Slack API Token") | ||||
| 	flag.BoolVar(&debug, "debug", false, "Show JSON output") | ||||
| 	flag.Parse() | ||||
|  | ||||
| 	api := slack.New(apiToken) | ||||
| 	if debug { | ||||
| 		api.SetDebug(true) | ||||
| 	} | ||||
|  | ||||
| 	// Get all stars for the usr. | ||||
| 	params := slack.NewStarsParameters() | ||||
| 	starredItems, _, err := api.GetStarred(params) | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("Error getting stars: %s\n", err) | ||||
| 		return | ||||
| 	} | ||||
| 	for _, s := range starredItems { | ||||
| 		var desc string | ||||
| 		switch s.Type { | ||||
| 		case slack.TYPE_MESSAGE: | ||||
| 			desc = s.Message.Text | ||||
| 		case slack.TYPE_FILE: | ||||
| 			desc = s.File.Name | ||||
| 		case slack.TYPE_FILE_COMMENT: | ||||
| 			desc = s.File.Name + " - " + s.Comment.Comment | ||||
| 		case slack.TYPE_CHANNEL, slack.TYPE_IM, slack.TYPE_GROUP: | ||||
| 			desc = s.Channel | ||||
| 		} | ||||
| 		fmt.Printf("Starred %s: %s\n", s.Type, desc) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										25
									
								
								vendor/github.com/nlopes/slack/examples/team/team.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/nlopes/slack/examples/team/team.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,25 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/nlopes/slack" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	api := slack.New("YOUR_TOKEN_HERE") | ||||
| 	//Example for single user | ||||
| 	billingActive, err := api.GetBillableInfo("U023BECGF") | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("%s\n", err) | ||||
| 		return | ||||
| 	} | ||||
| 	fmt.Printf("ID: U023BECGF, BillingActive: %v\n\n\n", billingActive["U023BECGF"]) | ||||
|  | ||||
| 	//Example for team | ||||
| 	billingActiveForTeam, _ := api.GetBillableInfoForTeam() | ||||
| 	for id, value := range billingActiveForTeam { | ||||
| 		fmt.Printf("ID: %v, BillingActive: %v\n", id, value) | ||||
| 	} | ||||
|  | ||||
| } | ||||
							
								
								
									
										17
									
								
								vendor/github.com/nlopes/slack/examples/users/users.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/nlopes/slack/examples/users/users.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,17 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/nlopes/slack" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	api := slack.New("YOUR_TOKEN_HERE") | ||||
| 	user, err := api.GetUserInfo("U023BECGF") | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("%s\n", err) | ||||
| 		return | ||||
| 	} | ||||
| 	fmt.Printf("ID: %s, Fullname: %s, Email: %s\n", user.ID, user.Profile.RealName, user.Profile.Email) | ||||
| } | ||||
							
								
								
									
										54
									
								
								vendor/github.com/nlopes/slack/examples/websocket/websocket.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										54
									
								
								vendor/github.com/nlopes/slack/examples/websocket/websocket.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,54 +0,0 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"os" | ||||
|  | ||||
| 	"github.com/nlopes/slack" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	api := slack.New("YOUR TOKEN HERE") | ||||
| 	logger := log.New(os.Stdout, "slack-bot: ", log.Lshortfile|log.LstdFlags) | ||||
| 	slack.SetLogger(logger) | ||||
| 	api.SetDebug(true) | ||||
|  | ||||
| 	rtm := api.NewRTM() | ||||
| 	go rtm.ManageConnection() | ||||
|  | ||||
| 	for msg := range rtm.IncomingEvents { | ||||
| 		fmt.Print("Event Received: ") | ||||
| 		switch ev := msg.Data.(type) { | ||||
| 		case *slack.HelloEvent: | ||||
| 			// Ignore hello | ||||
|  | ||||
| 		case *slack.ConnectedEvent: | ||||
| 			fmt.Println("Infos:", ev.Info) | ||||
| 			fmt.Println("Connection counter:", ev.ConnectionCount) | ||||
| 			// Replace C2147483705 with your Channel ID | ||||
| 			rtm.SendMessage(rtm.NewOutgoingMessage("Hello world", "C2147483705")) | ||||
|  | ||||
| 		case *slack.MessageEvent: | ||||
| 			fmt.Printf("Message: %v\n", ev) | ||||
|  | ||||
| 		case *slack.PresenceChangeEvent: | ||||
| 			fmt.Printf("Presence Change: %v\n", ev) | ||||
|  | ||||
| 		case *slack.LatencyReport: | ||||
| 			fmt.Printf("Current latency: %v\n", ev.Value) | ||||
|  | ||||
| 		case *slack.RTMError: | ||||
| 			fmt.Printf("Error: %s\n", ev.Error()) | ||||
|  | ||||
| 		case *slack.InvalidAuthEvent: | ||||
| 			fmt.Printf("Invalid credentials") | ||||
| 			return | ||||
|  | ||||
| 		default: | ||||
|  | ||||
| 			// Ignore other events.. | ||||
| 			// fmt.Printf("Unexpected: %v\n", msg.Data) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										21
									
								
								vendor/github.com/shazow/rateio/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/shazow/rateio/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,21 +0,0 @@ | ||||
| The MIT License (MIT) | ||||
|  | ||||
| Copyright (c) 2015 Andrey Petrov | ||||
|  | ||||
| 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. | ||||
							
								
								
									
										29
									
								
								vendor/github.com/shazow/rateio/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/shazow/rateio/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,29 +0,0 @@ | ||||
| /* | ||||
| Package rateio provides an io interfaces for rate-limiting. | ||||
|  | ||||
| This can be used to apply rate limiting to any type that implements an io-style interface. | ||||
|  | ||||
| For example, we can use it to restrict the reading rate of a net.Conn: | ||||
|  | ||||
| 	type limitedConn struct { | ||||
| 		net.Conn | ||||
| 		io.Reader // Our rate-limited io.Reader for net.Conn | ||||
| 	} | ||||
|  | ||||
| 	func (r *limitedConn) Read(p []byte) (n int, err error) { | ||||
| 		return r.Reader.Read(p) | ||||
| 	} | ||||
|  | ||||
| 	// ReadLimitConn returns a net.Conn whose io.Reader interface is rate-limited by limiter. | ||||
| 	func ReadLimitConn(conn net.Conn, limiter rateio.Limiter) net.Conn { | ||||
| 		return &limitedConn{ | ||||
| 			Conn:   conn, | ||||
| 			Reader: rateio.NewReader(conn, limiter), | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| Then we can use ReadLimitConn to wrap our existing net.Conn and continue using | ||||
| the wrapped version in its place. | ||||
|  | ||||
| */ | ||||
| package rateio | ||||
							
								
								
									
										62
									
								
								vendor/github.com/shazow/rateio/limiter.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										62
									
								
								vendor/github.com/shazow/rateio/limiter.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,62 +0,0 @@ | ||||
| package rateio | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| const minInt = -int(^uint(0)>>1) - 1 | ||||
|  | ||||
| // The error returned when the read rate exceeds our specification. | ||||
| var ErrRateExceeded = errors.New("Read rate exceeded.") | ||||
|  | ||||
| // Limiter is an interface for a rate limiter. | ||||
| // There are a few example limiters included in the package, but feel free to go wild with your own. | ||||
| type Limiter interface { | ||||
| 	// Apply this many bytes to the limiter, return ErrRateExceeded if the defined rate is exceeded. | ||||
| 	Count(int) error | ||||
| } | ||||
|  | ||||
| // simpleLimiter is a rate limiter that restricts Amount bytes in Frequency duration. | ||||
| type simpleLimiter struct { | ||||
| 	Amount    int | ||||
| 	Frequency time.Duration | ||||
|  | ||||
| 	numRead  int | ||||
| 	timeRead time.Time | ||||
| } | ||||
|  | ||||
| // NewSimpleLimiter creates a Limiter that restricts a given number of bytes per frequency. | ||||
| func NewSimpleLimiter(amount int, frequency time.Duration) Limiter { | ||||
| 	return &simpleLimiter{ | ||||
| 		Amount:    amount, | ||||
| 		Frequency: frequency, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // NewGracefulLimiter returns a Limiter that is the same as a | ||||
| // SimpleLimiter but adds a grace period at the start of the rate | ||||
| // limiting where it allows unlimited bytes to be read during that | ||||
| // period. | ||||
| func NewGracefulLimiter(amount int, frequency time.Duration, grace time.Duration) Limiter { | ||||
| 	return &simpleLimiter{ | ||||
| 		Amount:    amount, | ||||
| 		Frequency: frequency, | ||||
| 		numRead:   minInt, | ||||
| 		timeRead:  time.Now().Add(grace), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Count applies n bytes to the limiter. | ||||
| func (limit *simpleLimiter) Count(n int) error { | ||||
| 	now := time.Now() | ||||
| 	if now.After(limit.timeRead) { | ||||
| 		limit.numRead = 0 | ||||
| 		limit.timeRead = now.Add(limit.Frequency) | ||||
| 	} | ||||
| 	limit.numRead += n | ||||
| 	if limit.numRead > limit.Amount { | ||||
| 		return ErrRateExceeded | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										25
									
								
								vendor/github.com/shazow/rateio/reader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/shazow/rateio/reader.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,25 +0,0 @@ | ||||
| package rateio | ||||
|  | ||||
| import "io" | ||||
|  | ||||
| type reader struct { | ||||
| 	io.Reader | ||||
| 	Limiter | ||||
| } | ||||
|  | ||||
| // Read reads data into p. | ||||
| // Returns ErrRateExceeded error if our specified read is exceeded. | ||||
| func (r *reader) Read(p []byte) (n int, err error) { | ||||
| 	n, err = r.Reader.Read(p) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	err = r.Limiter.Count(n) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // NewReader proxies an io.Reader but keeps track of bytes read based on our Limiter. | ||||
| func NewReader(r io.Reader, limiter Limiter) io.Reader { | ||||
| 	return &reader{r, limiter} | ||||
| } | ||||
							
								
								
									
										25
									
								
								vendor/github.com/shazow/rateio/writer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/shazow/rateio/writer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,25 +0,0 @@ | ||||
| package rateio | ||||
|  | ||||
| import "io" | ||||
|  | ||||
| type writer struct { | ||||
| 	io.Writer | ||||
| 	Limiter | ||||
| } | ||||
|  | ||||
| // Write writes the contents of p into the buffer. | ||||
| // Returns ErrRateExceeded error if our specified read is exceeded. | ||||
| func (w *writer) Write(p []byte) (n int, err error) { | ||||
| 	n, err = w.Writer.Write(p) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	err = w.Limiter.Count(n) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // NewWriter proxies an io.Writer but keeps track of bytes read based on our Limiter. | ||||
| func NewWriter(w io.Writer, limiter Limiter) io.Writer { | ||||
| 	return &writer{w, limiter} | ||||
| } | ||||
							
								
								
									
										21
									
								
								vendor/github.com/shazow/ssh-chat/sshd/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/shazow/ssh-chat/sshd/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,21 +0,0 @@ | ||||
| The MIT License (MIT) | ||||
|  | ||||
| Copyright (c) 2014 Andrey Petrov | ||||
|  | ||||
| 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. | ||||
							
								
								
									
										72
									
								
								vendor/github.com/shazow/ssh-chat/sshd/auth.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										72
									
								
								vendor/github.com/shazow/ssh-chat/sshd/auth.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,72 +0,0 @@ | ||||
| package sshd | ||||
|  | ||||
| import ( | ||||
| 	"crypto/sha256" | ||||
| 	"encoding/base64" | ||||
| 	"errors" | ||||
| 	"net" | ||||
|  | ||||
| 	"golang.org/x/crypto/ssh" | ||||
| ) | ||||
|  | ||||
| // Auth is used to authenticate connections based on public keys. | ||||
| type Auth interface { | ||||
| 	// Whether to allow connections without a public key. | ||||
| 	AllowAnonymous() bool | ||||
| 	// Given address and public key, return if the connection should be permitted. | ||||
| 	Check(net.Addr, ssh.PublicKey) (bool, error) | ||||
| } | ||||
|  | ||||
| // MakeAuth makes an ssh.ServerConfig which performs authentication against an Auth implementation. | ||||
| func MakeAuth(auth Auth) *ssh.ServerConfig { | ||||
| 	config := ssh.ServerConfig{ | ||||
| 		NoClientAuth: false, | ||||
| 		// Auth-related things should be constant-time to avoid timing attacks. | ||||
| 		PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { | ||||
| 			ok, err := auth.Check(conn.RemoteAddr(), key) | ||||
| 			if !ok { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			perm := &ssh.Permissions{Extensions: map[string]string{ | ||||
| 				"pubkey": string(key.Marshal()), | ||||
| 			}} | ||||
| 			return perm, nil | ||||
| 		}, | ||||
| 		KeyboardInteractiveCallback: func(conn ssh.ConnMetadata, challenge ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error) { | ||||
| 			if !auth.AllowAnonymous() { | ||||
| 				return nil, errors.New("public key authentication required") | ||||
| 			} | ||||
| 			_, err := auth.Check(conn.RemoteAddr(), nil) | ||||
| 			return nil, err | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	return &config | ||||
| } | ||||
|  | ||||
| // MakeNoAuth makes a simple ssh.ServerConfig which allows all connections. | ||||
| // Primarily used for testing. | ||||
| func MakeNoAuth() *ssh.ServerConfig { | ||||
| 	config := ssh.ServerConfig{ | ||||
| 		NoClientAuth: false, | ||||
| 		// Auth-related things should be constant-time to avoid timing attacks. | ||||
| 		PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { | ||||
| 			perm := &ssh.Permissions{Extensions: map[string]string{ | ||||
| 				"pubkey": string(key.Marshal()), | ||||
| 			}} | ||||
| 			return perm, nil | ||||
| 		}, | ||||
| 		KeyboardInteractiveCallback: func(conn ssh.ConnMetadata, challenge ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error) { | ||||
| 			return nil, nil | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	return &config | ||||
| } | ||||
|  | ||||
| // Fingerprint performs a SHA256 BASE64 fingerprint of the PublicKey, similar to OpenSSH. | ||||
| // See: https://anongit.mindrot.org/openssh.git/commit/?id=56d1c83cdd1ac | ||||
| func Fingerprint(k ssh.PublicKey) string { | ||||
| 	hash := sha256.Sum256(k.Marshal()) | ||||
| 	return "SHA256:" + base64.StdEncoding.EncodeToString(hash[:]) | ||||
| } | ||||
							
								
								
									
										76
									
								
								vendor/github.com/shazow/ssh-chat/sshd/client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										76
									
								
								vendor/github.com/shazow/ssh-chat/sshd/client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,76 +0,0 @@ | ||||
| package sshd | ||||
|  | ||||
| import ( | ||||
| 	"crypto/rand" | ||||
| 	"crypto/rsa" | ||||
| 	"io" | ||||
|  | ||||
| 	"golang.org/x/crypto/ssh" | ||||
| ) | ||||
|  | ||||
| // NewRandomSigner generates a random key of a desired bit length. | ||||
| func NewRandomSigner(bits int) (ssh.Signer, error) { | ||||
| 	key, err := rsa.GenerateKey(rand.Reader, bits) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return ssh.NewSignerFromKey(key) | ||||
| } | ||||
|  | ||||
| // NewClientConfig creates a barebones ssh.ClientConfig to be used with ssh.Dial. | ||||
| func NewClientConfig(name string) *ssh.ClientConfig { | ||||
| 	return &ssh.ClientConfig{ | ||||
| 		User: name, | ||||
| 		Auth: []ssh.AuthMethod{ | ||||
| 			ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) (answers []string, err error) { | ||||
| 				return | ||||
| 			}), | ||||
| 		}, | ||||
| 		HostKeyCallback: ssh.InsecureIgnoreHostKey(), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ConnectShell makes a barebones SSH client session, used for testing. | ||||
| func ConnectShell(host string, name string, handler func(r io.Reader, w io.WriteCloser) error) error { | ||||
| 	config := NewClientConfig(name) | ||||
| 	conn, err := ssh.Dial("tcp", host, config) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer conn.Close() | ||||
|  | ||||
| 	session, err := conn.NewSession() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer session.Close() | ||||
|  | ||||
| 	in, err := session.StdinPipe() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	out, err := session.StdoutPipe() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 		err = session.RequestPty("xterm", 80, 40, ssh.TerminalModes{}) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	*/ | ||||
|  | ||||
| 	err = session.Shell() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	_, err = session.SendRequest("ping", true, nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return handler(out, in) | ||||
| } | ||||
							
								
								
									
										34
									
								
								vendor/github.com/shazow/ssh-chat/sshd/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								vendor/github.com/shazow/ssh-chat/sshd/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,34 +0,0 @@ | ||||
| package sshd | ||||
|  | ||||
| /* | ||||
|  | ||||
| 	signer, err := ssh.ParsePrivateKey(privateKey) | ||||
|  | ||||
| 	config := MakeNoAuth() | ||||
| 	config.AddHostKey(signer) | ||||
|  | ||||
| 	s, err := ListenSSH("0.0.0.0:2022", config) | ||||
| 	if err != nil { | ||||
| 		// Handle opening socket error | ||||
| 	} | ||||
| 	defer s.Close() | ||||
|  | ||||
| 	terminals := s.ServeTerminal() | ||||
|  | ||||
| 	for term := range terminals { | ||||
| 		go func() { | ||||
| 			defer term.Close() | ||||
| 			term.SetPrompt("...") | ||||
| 			term.AutoCompleteCallback = nil // ... | ||||
|  | ||||
| 			for { | ||||
| 				line, err := term.ReadLine() | ||||
| 				if err != nil { | ||||
| 					break | ||||
| 				} | ||||
| 				term.Write(...) | ||||
| 			} | ||||
|  | ||||
| 		}() | ||||
| 	} | ||||
| */ | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user