-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 11505dc
Showing
8 changed files
with
316 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# traQ BOTサーバーライブラリ | ||
traQ BOTサーバーを簡単に作るためのライブラリです。 | ||
|
||
`traQ--->BOTサーバー`へのイベントの受け取り部分を補助します。`BOTサーバー--->traQ`へのリクエストを行うための、traQ APIクライアントは含まれていません。 | ||
|
||
## サンプル | ||
```go | ||
package main | ||
|
||
import ( | ||
"github.com/traPtitech/traq-bot" | ||
"log" | ||
"os" | ||
) | ||
|
||
func main() { | ||
vt := os.Getenv("VERIFICATION_TOKEN") | ||
|
||
handlers := traqbot.EventHandlers{} | ||
handlers.SetMessageCreatedHandler(func(payload *traqbot.MessageCreatedPayload) { | ||
log.Println("=================================================") | ||
log.Printf("%sさんがメッセージを投稿しました。\n", payload.Message.User.DisplayName) | ||
log.Println("メッセージ:") | ||
log.Println(payload.Message.Text) | ||
log.Println("=================================================") | ||
}) | ||
|
||
server := traqbot.NewBotServer(vt, handlers) | ||
log.Fatal(server.ListenAndServe(":80")) | ||
} | ||
|
||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package traqbot | ||
|
||
import "time" | ||
|
||
// BasePayload ベースペイロード | ||
type BasePayload struct { | ||
// EventTime イベント発生日時 | ||
EventTime time.Time `json:"eventTime"` | ||
} | ||
|
||
// UserPayload ユーザー情報ペイロード | ||
type UserPayload struct { | ||
// ID ユーザーUUID | ||
ID string `json:"id"` | ||
// Name ユーザーのtraQ ID | ||
Name string `json:"name"` | ||
// DisplayName ユーザーの表示名 | ||
DisplayName string `json:"displayName"` | ||
// IconID ユーザーアイコンのファイルUUID | ||
IconID string `json:"iconId"` | ||
// Bot ユーザーがBotかどうか | ||
Bot bool `json:"bot"` | ||
} | ||
|
||
// ChannelPayload チャンネル情報ペイロード | ||
type ChannelPayload struct { | ||
// ID チャンネルUUID | ||
ID string `json:"id"` | ||
// Name チャンネル名 | ||
Name string `json:"name"` | ||
// Path チャンネルパス | ||
Path string `json:"path"` | ||
// ParentID 親チャンネルのUUID | ||
// | ||
// ルートチャンネルの場合は"00000000-0000-0000-0000-000000000000" | ||
ParentID string `json:"parentId"` | ||
// Creator チャンネル作成者 | ||
Creator UserPayload `json:"creator"` | ||
// CreatedAt チャンネル作成日時 | ||
CreatedAt time.Time `json:"createdAt"` | ||
// UpdatedAt チャンネル更新日時 | ||
UpdatedAt time.Time `json:"updatedAt"` | ||
} | ||
|
||
// MessagePayload メッセージ情報ペイロード | ||
type MessagePayload struct { | ||
// ID メッセージUUID | ||
ID string `json:"id"` | ||
// User メッセージ投稿者 | ||
User UserPayload `json:"user"` | ||
// ChannelID 投稿先チャンネルUUID | ||
ChannelID string `json:"channelId"` | ||
// Text 生メッセージ本文 | ||
Text string `json:"text"` | ||
// PlainText メッセージ本文(埋め込み情報・改行なし) | ||
PlainText string `json:"plainText"` | ||
// Embedded メッセージ埋め込み情報の配列 | ||
Embedded []EmbeddedInfoPayload `json:"embedded"` | ||
// CreatedAt メッセージ投稿日時 | ||
CreatedAt time.Time `json:"createdAt"` | ||
// UpdatedAt メッセージ更新日時 | ||
UpdatedAt time.Time `json:"updatedAt"` | ||
} | ||
|
||
// EmbeddedInfoPayload メッセージ埋め込み情報 | ||
type EmbeddedInfoPayload struct { | ||
// Raw 表示文字列 | ||
Raw string `json:"raw"` | ||
// Type タイプ | ||
Type string `json:"type"` | ||
// ID 各種ID(タイプによる) | ||
ID string `json:"id"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package traqbot | ||
|
||
// PingPayload PINGイベントペイロード | ||
type PingPayload struct { | ||
BasePayload | ||
} | ||
|
||
// JoinedPayload JOINEDイベントペイロード | ||
type JoinedPayload struct { | ||
BasePayload | ||
// Channel 参加したチャンネル | ||
Channel ChannelPayload `json:"channel"` | ||
} | ||
|
||
// LeftPayload LEFTイベントペイロード | ||
type LeftPayload struct { | ||
BasePayload | ||
// Channel 退出したチャンネル | ||
Channel ChannelPayload `json:"channel"` | ||
} | ||
|
||
// MessageCreatedPayload MESSAGE_CREATEDイベントペイロード | ||
type MessageCreatedPayload struct { | ||
BasePayload | ||
// Message 投稿されたメッセージ | ||
Message MessagePayload `json:"message"` | ||
} | ||
|
||
// DirectMessageCreatedPayload DIRECT_MESSAGE_CREATEDイベントペイロード | ||
type DirectMessageCreatedPayload struct { | ||
BasePayload | ||
// Message 投稿されたメッセージ | ||
Message MessagePayload `json:"message"` | ||
} | ||
|
||
// ChannelCreatedPayload CHANNEL_CREATEDイベントペイロード | ||
type ChannelCreatedPayload struct { | ||
BasePayload | ||
// Channel 作成されたチャンネル | ||
Channel ChannelPayload `json:"channel"` | ||
} | ||
|
||
// UserCreatedPayload USER_CREATEDイベントペイロード | ||
type UserCreatedPayload struct { | ||
BasePayload | ||
// User 作成されたユーザー | ||
User UserPayload `json:"user"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package traqbot | ||
|
||
const ( | ||
// Ping PINGイベント | ||
Ping = "PING" | ||
// Joined JOINEDイベント | ||
Joined = "JOINED" | ||
// Left LEFTイベント | ||
Left = "LEFT" | ||
// MessageCreated MESSAGE_CREATEDイベント | ||
MessageCreated = "MESSAGE_CREATED" | ||
// DirectMessageCreated DIRECT_MESSAGE_CREATEDイベント | ||
DirectMessageCreated = "DIRECT_MESSAGE_CREATED" | ||
// ChannelCreated CHANNEL_CREATEDイベント | ||
ChannelCreated = "CHANNEL_CREATED" | ||
// UserCreated USER_CREATEDイベント | ||
UserCreated = "USER_CREATED" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module github.com/traPtitech/traq-bot |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package traqbot | ||
|
||
// SetHandler イベントハンドラをセットします | ||
// | ||
// ハンドラにnilを指定すると、ハンドラは削除されます | ||
func (hs EventHandlers) SetHandler(event string, h EventHandler) { | ||
if h == nil { | ||
delete(hs, event) | ||
} else { | ||
hs[event] = h | ||
} | ||
} | ||
|
||
// SetPingHandler イベントハンドラをセットします | ||
func (hs EventHandlers) SetPingHandler(h func(payload *PingPayload)) { | ||
hs.SetHandler(Ping, func(event string, payload interface{}) { h(payload.(*PingPayload)) }) | ||
} | ||
|
||
// SetJoinedHandler イベントハンドラをセットします | ||
func (hs EventHandlers) SetJoinedHandler(h func(payload *JoinedPayload)) { | ||
hs.SetHandler(Joined, func(event string, payload interface{}) { h(payload.(*JoinedPayload)) }) | ||
} | ||
|
||
// SetLeftHandler イベントハンドラをセットします | ||
func (hs EventHandlers) SetLeftHandler(h func(payload *LeftPayload)) { | ||
hs.SetHandler(Left, func(event string, payload interface{}) { h(payload.(*LeftPayload)) }) | ||
} | ||
|
||
// SetMessageCreatedHandler イベントハンドラをセットします | ||
func (hs EventHandlers) SetMessageCreatedHandler(h func(payload *MessageCreatedPayload)) { | ||
hs.SetHandler(MessageCreated, func(event string, payload interface{}) { h(payload.(*MessageCreatedPayload)) }) | ||
} | ||
|
||
// SetDirectMessageCreatedHandler イベントハンドラをセットします | ||
func (hs EventHandlers) SetDirectMessageCreatedHandler(h func(payload *DirectMessageCreatedPayload)) { | ||
hs.SetHandler(DirectMessageCreated, func(event string, payload interface{}) { h(payload.(*DirectMessageCreatedPayload)) }) | ||
} | ||
|
||
// SetChannelCreatedHandler イベントハンドラをセットします | ||
func (hs EventHandlers) SetChannelCreatedHandler(h func(payload *ChannelCreatedPayload)) { | ||
hs.SetHandler(ChannelCreated, func(event string, payload interface{}) { h(payload.(*ChannelCreatedPayload)) }) | ||
} | ||
|
||
// SetUserCreatedHandler イベントハンドラをセットします | ||
func (hs EventHandlers) SetUserCreatedHandler(h func(payload *UserCreatedPayload)) { | ||
hs.SetHandler(UserCreated, func(event string, payload interface{}) { h(payload.(*UserCreatedPayload)) }) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package traqbot | ||
|
||
import ( | ||
"encoding/json" | ||
"net/http" | ||
"strings" | ||
) | ||
|
||
const ( | ||
contentTypeHeader = "Content-Type" | ||
mimeApplicationJson = "application/json" | ||
botTokenHeader = "X-TRAQ-BOT-TOKEN" | ||
botEventHeader = "X-TRAQ-BOT-EVENT" | ||
) | ||
|
||
// EventHandler イベントハンドラ | ||
type EventHandler func(event string, payload interface{}) | ||
|
||
// EventHandlers イベントハンドラマップ | ||
type EventHandlers map[string]EventHandler | ||
|
||
// BotServer BOTサーバー | ||
type BotServer struct { | ||
verificationToken string | ||
handlers EventHandlers | ||
} | ||
|
||
// NewBotServer 新しくBOTサーバーを生成します | ||
func NewBotServer(verification string, handlers EventHandlers) *BotServer { | ||
return &BotServer{ | ||
verificationToken: verification, | ||
handlers: handlers, | ||
} | ||
} | ||
|
||
// ListenAndServe BOTサーバーを起動します | ||
func (bs *BotServer) ListenAndServe(addr string) error { | ||
mux := http.NewServeMux() | ||
mux.Handle("/", bs) | ||
server := &http.Server{Addr: addr, Handler: mux} | ||
return server.ListenAndServe() | ||
} | ||
|
||
// ServeHTTP BOTサーバーハンドラ | ||
func (bs *BotServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { | ||
// VerificationTokenチェック | ||
if req.Header.Get(botTokenHeader) != bs.verificationToken { | ||
rw.WriteHeader(http.StatusForbidden) | ||
return | ||
} | ||
|
||
// Eventヘッダチェック | ||
event := req.Header.Get(botEventHeader) | ||
if len(event) == 0 { | ||
rw.WriteHeader(http.StatusBadRequest) | ||
return | ||
} | ||
|
||
// RequestがJSONかどうか | ||
if !strings.HasPrefix(req.Header.Get(contentTypeHeader), mimeApplicationJson) { | ||
rw.WriteHeader(http.StatusBadRequest) | ||
return | ||
} | ||
|
||
var payload interface{} | ||
switch event { | ||
case Ping: | ||
payload = &PingPayload{} | ||
case Joined: | ||
payload = &JoinedPayload{} | ||
case Left: | ||
payload = &LeftPayload{} | ||
case MessageCreated: | ||
payload = &MessageCreatedPayload{} | ||
case DirectMessageCreated: | ||
payload = &DirectMessageCreatedPayload{} | ||
case ChannelCreated: | ||
payload = &ChannelCreatedPayload{} | ||
case UserCreated: | ||
payload = &UserCreatedPayload{} | ||
default: | ||
rw.WriteHeader(http.StatusNotImplemented) | ||
return | ||
} | ||
|
||
if err := json.NewDecoder(req.Body).Decode(payload); err != nil { | ||
rw.WriteHeader(http.StatusBadRequest) | ||
return | ||
} | ||
rw.WriteHeader(http.StatusNoContent) | ||
|
||
h, ok := bs.handlers[event] | ||
if ok && h != nil { | ||
h(event, payload) | ||
} | ||
} |