-
Notifications
You must be signed in to change notification settings - Fork 5
/
handler.go
138 lines (115 loc) · 3.9 KB
/
handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright (c) 2016 Tristan Colgate-McFarlane
//
// This file is part of hugot.
//
// hugot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// hugot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with hugot. If not, see <http://www.gnu.org/licenses/>.
package hugot
import (
"flag"
"fmt"
"io"
"runtime/debug"
"context"
"github.com/golang/glog"
)
// Describer returns the name and description of a handler. This
// is used to identify the handler within Command and HTTP Muxs,
// and to provide a descriptive name for the handler in help text.
type Describer interface {
Describe() (string, string)
}
// HandlerFunc describes a function that can be used as a hugot handler.
type HandlerFunc func(ctx context.Context, w ResponseWriter, m *Message) error
// Handler is a handler with no actual functionality
type Handler interface {
Describer
ProcessMessage(ctx context.Context, w ResponseWriter, m *Message) error
}
// NewNullResponseWriter creates a ResponseWriter that discards all
// message sent to it.
func NewNullResponseWriter(m Message) ResponseWriter {
return NewResponseWriter(nullSender{}, m, "null")
}
// ResponseWriter is used to Send messages back to a user.
type ResponseWriter interface {
Sender
io.Writer
SetChannel(c string) // Forces messages to a certain channel
SetTo(to string) // Forces messages to a certain user
SetSender(a Sender) // Forces messages to a different sender or adapter
Copy() ResponseWriter // Returns a copy of this response writer
}
type responseWriter struct {
snd Sender
msg Message
an string
}
// NewResponseWriter creates a response writer that will send mesages via the
// provided sender.
func NewResponseWriter(s Sender, m Message, adapterName string) ResponseWriter {
return &responseWriter{s, m, adapterName}
}
// ResponseWriterFromContext constructs a ResponseWriter from the adapter
// stored in the context. A destination Channel/User must be set to send
// messages..
func ResponseWriterFromContext(ctx context.Context) (ResponseWriter, bool) {
s, ok := SenderFromContext(ctx)
if !ok {
return nil, false
}
an := fmt.Sprintf("%T", s)
return NewResponseWriter(s, Message{}, an), true
}
// Write implements the io.Writer interface. All writes create a single
// new message that is then sent to the ResoneWriter's current adapter
func (w *responseWriter) Write(bs []byte) (int, error) {
nmsg := w.msg
nmsg.Text = string(bs)
w.Send(context.TODO(), &nmsg)
return len(bs), nil
}
// SetChannel sets the outbound channel for message sent via this writer
func (w *responseWriter) SetChannel(s string) {
w.msg.Channel = s
}
// SetChannel sets the target user for message sent via this writer
func (w *responseWriter) SetTo(s string) {
w.msg.To = s
}
// SetSender sets the target adapter for sender sent via this writer
func (w *responseWriter) SetSender(s Sender) {
w.snd = s
}
// Send implements the Sender interface
func (w *responseWriter) Send(ctx context.Context, m *Message) {
w.snd.Send(ctx, m)
}
// Copy returns a copy of this response writer
func (w *responseWriter) Copy() ResponseWriter {
return &responseWriter{w.snd, Message{}, w.an}
}
// nullSender is a sender which discards anything sent to it, this is
// useful for the help handler.
type nullSender struct {
}
// Send implements Send, and discards the message
func (nullSender) Send(ctx context.Context, m *Message) {
}
func glogPanic() {
err := recover()
if err != nil && err != flag.ErrHelp {
glog.Error(err)
glog.Error(string(debug.Stack()))
}
}