forked from shilch/mensabot
commit
233b628639
76 changed files with 16020 additions and 0 deletions
@ -0,0 +1,95 @@
@@ -0,0 +1,95 @@
|
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"github.com/bwmarrin/discordgo" |
||||
"github.com/kiliankoe/openmensa" |
||||
"os" |
||||
"os/signal" |
||||
"strings" |
||||
"syscall" |
||||
"time" |
||||
) |
||||
|
||||
var canteen *openmensa.Canteen |
||||
|
||||
func main() { |
||||
if len(os.Args) <= 0 { |
||||
println("Please add token as cli argument.") |
||||
return |
||||
} |
||||
dg, err := discordgo.New(fmt.Sprintf("Bot %s", os.Args[1])) |
||||
canteens, err := openmensa.GetCanteens(175) |
||||
if err != nil { |
||||
fmt.Println("error creating discord bot: ", err) |
||||
return |
||||
} |
||||
dg.AddHandler(messageCreate) |
||||
canteen = canteens[0] |
||||
|
||||
// Open a websocket connection to Discord and begin listening.
|
||||
err = dg.Open() |
||||
if err != nil { |
||||
fmt.Println("error opening connection,", err) |
||||
return |
||||
} |
||||
|
||||
// Wait here until CTRL-C or other term signal is received.
|
||||
fmt.Println("Bot is now running. Press CTRL-C to exit.") |
||||
sc := make(chan os.Signal, 1) |
||||
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill) |
||||
<-sc |
||||
|
||||
// Cleanly close down the Discord session.
|
||||
dg.Close() |
||||
} |
||||
|
||||
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { |
||||
// Ignore all messages created by the bot itself
|
||||
// This isn't required in this specific example but it's a good practice.
|
||||
if m.Author.ID == s.State.User.ID { |
||||
return |
||||
} |
||||
|
||||
if m.Content == "!mensa" { |
||||
sendMealsForDate(s, time.Now(), m.ChannelID) |
||||
} |
||||
} |
||||
|
||||
func sendMealsForDate(s *discordgo.Session, t time.Time, channel string) { |
||||
msg, err := s.ChannelMessageSend(channel, "Just a second...") |
||||
if err != nil { |
||||
println("error sending message: ", err) |
||||
return |
||||
} |
||||
meals, err := canteen.GetMeals(t) |
||||
if err != nil { |
||||
s.ChannelMessageEdit(channel, msg.ID, "An error occured :angry:") |
||||
return |
||||
} |
||||
var messages = make([]*discordgo.MessageEmbedField, len(meals)) |
||||
var footer = "" |
||||
for i, meal := range meals { |
||||
messages[i] = &discordgo.MessageEmbedField{ |
||||
Name: fmt.Sprintf("%s: %s", meal.Category, meal.Name), |
||||
Value: fmt.Sprintf("%.2fโฌ", *meal.Prices.Students), |
||||
} |
||||
if len(meal.Notes) > 0 { |
||||
footer += fmt.Sprintf("[%d] %s\n", i + 1, strings.Join(meal.Notes, ", ")) |
||||
} |
||||
} |
||||
empty := "" |
||||
s.ChannelMessageEditComplex(&discordgo.MessageEdit{ |
||||
Embed: &discordgo.MessageEmbed{ |
||||
Title: fmt.Sprintf("** :spaghetti: Menรผ vom %s**", t.Format("02.01.2006")), |
||||
Fields: messages, |
||||
Footer: &discordgo.MessageEmbedFooter{ |
||||
IconURL: "https://pbs.twimg.com/profile_images/643755515118505984/xzZMK7fU_400x400.png", |
||||
Text: footer, |
||||
}, |
||||
}, |
||||
ID: msg.ID, |
||||
Channel: msg.ChannelID, |
||||
Content: &empty, |
||||
}) |
||||
} |
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
module git.jonasfranz.software/mensabot |
||||
|
||||
require ( |
||||
github.com/bwmarrin/discordgo v0.18.0 |
||||
github.com/gorilla/websocket v1.4.0 // indirect |
||||
github.com/kiliankoe/openmensa v0.0.0-20160914233745-a68c3aca59c0 |
||||
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774 // indirect |
||||
) |
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
language: go |
||||
go: |
||||
- 1.7 |
||||
- 1.8 |
||||
- 1.9 |
||||
install: |
||||
- go get github.com/bwmarrin/discordgo |
||||
- go get -v . |
||||
- go get -v github.com/golang/lint/golint |
||||
script: |
||||
- diff <(gofmt -d .) <(echo -n) |
||||
- go vet -x ./... |
||||
- golint -set_exit_status ./... |
||||
- go test -v -race ./... |
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
Copyright (c) 2015, Bruce Marriner |
||||
All rights reserved. |
||||
|
||||
Redistribution and use in source and binary forms, with or without |
||||
modification, are permitted provided that the following conditions are met: |
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this |
||||
list of conditions and the following disclaimer. |
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, |
||||
this list of conditions and the following disclaimer in the documentation |
||||
and/or other materials provided with the distribution. |
||||
|
||||
* Neither the name of discordgo nor the names of its |
||||
contributors may be used to endorse or promote products derived from |
||||
this software without specific prior written permission. |
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
@ -0,0 +1,130 @@
@@ -0,0 +1,130 @@
|
||||
# DiscordGo |
||||
|
||||
[](https://godoc.org/github.com/bwmarrin/discordgo) [](http://goreportcard.com/report/bwmarrin/discordgo) [](https://travis-ci.org/bwmarrin/discordgo) [](https://discord.gg/0f1SbxBZjYoCtNPP) [](https://discord.gg/0SBTUU1wZTWT6sqd) |
||||
|
||||
<img align="right" src="http://bwmarrin.github.io/discordgo/img/discordgo.png"> |
||||
|
||||
DiscordGo is a [Go](https://golang.org/) package that provides low level |
||||
bindings to the [Discord](https://discordapp.com/) chat client API. DiscordGo |
||||
has nearly complete support for all of the Discord API endpoints, websocket |
||||
interface, and voice interface. |
||||
|
||||
If you would like to help the DiscordGo package please use |
||||
[this link](https://discordapp.com/oauth2/authorize?client_id=173113690092994561&scope=bot) |
||||
to add the official DiscordGo test bot **dgo** to your server. This provides |
||||
indispensable help to this project. |
||||
|
||||
* See [dgVoice](https://github.com/bwmarrin/dgvoice) package for an example of |
||||
additional voice helper functions and features for DiscordGo |
||||
|
||||
* See [dca](https://github.com/bwmarrin/dca) for an **experimental** stand alone |
||||
tool that wraps `ffmpeg` to create opus encoded audio appropriate for use with |
||||
Discord (and DiscordGo) |
||||
|
||||
**For help with this package or general Go discussion, please join the [Discord |
||||
Gophers](https://discord.gg/0f1SbxBZjYq9jLBk) chat server.** |
||||
|
||||
## Getting Started |
||||
|
||||
### master vs develop Branch |
||||
* The master branch represents the latest released version of DiscordGo. This |
||||
branch will always have a stable and tested version of the library. Each release |
||||
is tagged and you can easily download a specific release and view release notes |
||||
on the github [releases](https://github.com/bwmarrin/discordgo/releases) page. |
||||
|
||||
* The develop branch is where all development happens and almost always has |
||||
new features over the master branch. However breaking changes are frequently |
||||
added to develop and even sometimes bugs are introduced. Bugs get fixed and |
||||
the breaking changes get documented before pushing to master. |
||||
|
||||
*So, what should you use?* |
||||
|
||||
If you can accept the constant changing nature of *develop* then it is the |
||||
recommended branch to use. Otherwise, if you want to tail behind development |
||||
slightly and have a more stable package with documented releases then use *master* |
||||
|
||||
### Installing |
||||
|
||||
This assumes you already have a working Go environment, if not please see |
||||
[this page](https://golang.org/doc/install) first. |
||||
|
||||
`go get` *will always pull the latest released version from the master branch.* |
||||
|
||||
```sh |
||||
go get github.com/bwmarrin/discordgo |
||||
``` |
||||
|
||||
If you want to use the develop branch, follow these steps next. |
||||
|
||||
```sh |
||||
cd $GOPATH/src/github.com/bwmarrin/discordgo |
||||
git checkout develop |
||||
``` |
||||
|
||||
### Usage |
||||
|
||||
Import the package into your project. |
||||
|
||||
```go |
||||
import "github.com/bwmarrin/discordgo" |
||||
``` |
||||
|
||||
Construct a new Discord client which can be used to access the variety of |
||||
Discord API functions and to set callback functions for Discord events. |
||||
|
||||
```go |
||||
discord, err := discordgo.New("authentication token") |
||||
``` |
||||
|
||||
See Documentation and Examples below for more detailed information. |
||||
|
||||
|
||||
## Documentation |
||||
|
||||
**NOTICE** : This library and the Discord API are unfinished. |
||||
Because of that there may be major changes to library in the future. |
||||
|
||||
The DiscordGo code is fairly well documented at this point and is currently |
||||
the only documentation available. Both GoDoc and GoWalker (below) present |
||||
that information in a nice format. |
||||
|
||||
- [](https://godoc.org/github.com/bwmarrin/discordgo) |
||||
- [](https://gowalker.org/github.com/bwmarrin/discordgo) |
||||
- Hand crafted documentation coming eventually. |
||||
|
||||
|
||||
## Examples |
||||
|
||||
Below is a list of examples and other projects using DiscordGo. Please submit |
||||
an issue if you would like your project added or removed from this list |
||||
|
||||
- [DiscordGo Examples](https://github.com/bwmarrin/discordgo/tree/master/examples) A collection of example programs written with DiscordGo |
||||
- [Awesome DiscordGo](https://github.com/bwmarrin/discordgo/wiki/Awesome-DiscordGo) A curated list of high quality projects using DiscordGo |
||||
|
||||
## Troubleshooting |
||||
For help with common problems please reference the |
||||
[Troubleshooting](https://github.com/bwmarrin/discordgo/wiki/Troubleshooting) |
||||
section of the project wiki. |
||||
|
||||
|
||||
## Contributing |
||||
Contributions are very welcomed, however please follow the below guidelines. |
||||
|
||||
- First open an issue describing the bug or enhancement so it can be |
||||
discussed. |
||||
- Fork the develop branch and make your changes. |
||||
- Try to match current naming conventions as closely as possible. |
||||
- This package is intended to be a low level direct mapping of the Discord API |
||||
so please avoid adding enhancements outside of that scope without first |
||||
discussing it. |
||||
- Create a Pull Request with your changes against the develop branch. |
||||
|
||||
|
||||
## List of Discord APIs |
||||
|
||||
See [this chart](https://abal.moe/Discord/Libraries.html) for a feature |
||||
comparison and list of other Discord API libraries. |
||||
|
||||
## Special Thanks |
||||
|
||||
[Chris Rhodes](https://github.com/iopred) - For the DiscordGo logo and tons of PRs |
@ -0,0 +1,146 @@
@@ -0,0 +1,146 @@
|
||||
// Discordgo - Discord bindings for Go
|
||||
// Available at https://github.com/bwmarrin/discordgo
|
||||
|
||||
// Copyright 2015-2016 Bruce Marriner <bruce@sqls.net>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file contains high level helper functions and easy entry points for the
|
||||
// entire discordgo package. These functions are beling developed and are very
|
||||
// experimental at this point. They will most likley change so please use the
|
||||
// low level functions if that's a problem.
|
||||
|
||||
// Package discordgo provides Discord binding for Go
|
||||
package discordgo |
||||
|
||||
import ( |
||||
"errors" |
||||
"fmt" |
||||
"net/http" |
||||
"time" |
||||
) |
||||
|
||||
// VERSION of DiscordGo, follows Semantic Versioning. (http://semver.org/)
|
||||
const VERSION = "0.18.0" |
||||
|
||||
// ErrMFA will be risen by New when the user has 2FA.
|
||||
var ErrMFA = errors.New("account has 2FA enabled") |
||||
|
||||
// New creates a new Discord session and will automate some startup
|
||||
// tasks if given enough information to do so. Currently you can pass zero
|
||||
// arguments and it will return an empty Discord session.
|
||||
// There are 3 ways to call New:
|
||||
// With a single auth token - All requests will use the token blindly,
|
||||
// no verification of the token will be done and requests may fail.
|
||||
// IF THE TOKEN IS FOR A BOT, IT MUST BE PREFIXED WITH `BOT `
|
||||
// eg: `"Bot <token>"`
|
||||
// With an email and password - Discord will sign in with the provided
|
||||
// credentials.
|
||||
// With an email, password and auth token - Discord will verify the auth
|
||||
// token, if it is invalid it will sign in with the provided
|
||||
// credentials. This is the Discord recommended way to sign in.
|
||||
//
|
||||
// NOTE: While email/pass authentication is supported by DiscordGo it is
|
||||
// HIGHLY DISCOURAGED by Discord. Please only use email/pass to obtain a token
|
||||
// and then use that authentication token for all future connections.
|
||||
// Also, doing any form of automation with a user (non Bot) account may result
|
||||
// in that account being permanently banned from Discord.
|
||||
func New(args ...interface{}) (s *Session, err error) { |
||||
|
||||
// Create an empty Session interface.
|
||||
s = &Session{ |
||||
State: NewState(), |
||||
Ratelimiter: NewRatelimiter(), |
||||
StateEnabled: true, |
||||
Compress: true, |
||||
ShouldReconnectOnError: true, |
||||
ShardID: 0, |
||||
ShardCount: 1, |
||||
MaxRestRetries: 3, |
||||
Client: &http.Client{Timeout: (20 * time.Second)}, |
||||
sequence: new(int64), |
||||
LastHeartbeatAck: time.Now().UTC(), |
||||
} |
||||
|
||||
// If no arguments are passed return the empty Session interface.
|
||||
if args == nil { |
||||
return |
||||
} |
||||
|
||||
// Variables used below when parsing func arguments
|
||||
var auth, pass string |
||||
|
||||
// Parse passed arguments
|
||||
for _, arg := range args { |
||||
|
||||
switch v := arg.(type) { |
||||
|
||||
case []string: |
||||
if len(v) > 3 { |
||||
err = fmt.Errorf("too many string parameters provided") |
||||
return |
||||
} |
||||
|
||||
// First string is either token or username
|
||||
if len(v) > 0 { |
||||
auth = v[0] |
||||
} |
||||
|
||||
// If second string exists, it must be a password.
|
||||
if len(v) > 1 { |
||||
pass = v[1] |
||||
} |
||||
|
||||
// If third string exists, it must be an auth token.
|
||||
if len(v) > 2 { |
||||
s.Token = v[2] |
||||
} |
||||
|
||||
case string: |
||||
// First string must be either auth token or username.
|
||||
// Second string must be a password.
|
||||
// Only 2 input strings are supported.
|
||||
|
||||
if auth == "" { |
||||
auth = v |
||||
} else if pass == "" { |
||||
pass = v |
||||
} else if s.Token == "" { |
||||
s.Token = v |
||||
} else { |
||||
err = fmt.Errorf("too many string parameters provided") |
||||
return |
||||
} |
||||
|
||||
// case Config:
|
||||
// TODO: Parse configuration struct
|
||||
|
||||
default: |
||||
err = fmt.Errorf("unsupported parameter type provided") |
||||
return |
||||
} |
||||
} |
||||
|
||||
// If only one string was provided, assume it is an auth token.
|
||||
// Otherwise get auth token from Discord, if a token was specified
|
||||
// Discord will verify it for free, or log the user in if it is
|
||||
// invalid.
|
||||
if pass == "" { |
||||
s.Token = auth |
||||
} else { |
||||
err = s.Login(auth, pass) |
||||
if err != nil || s.Token == "" { |
||||
if s.MFA { |
||||
err = ErrMFA |
||||
} else { |
||||
err = fmt.Errorf("Unable to fetch discord authentication token. %v", err) |
||||
} |
||||
return |
||||
} |
||||
} |
||||
|
||||
// The Session is now able to have RestAPI methods called on it.
|
||||
// It is recommended that you now call Open() so that events will trigger.
|
||||
|
||||
return |
||||
} |
@ -0,0 +1,136 @@
@@ -0,0 +1,136 @@
|
||||
// Discordgo - Discord bindings for Go
|
||||
// Available at https://github.com/bwmarrin/discordgo
|
||||
|
||||
// Copyright 2015-2016 Bruce Marriner <bruce@sqls.net>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file contains variables for all known Discord end points. All functions
|
||||
// throughout the Discordgo package use these variables for all connections
|
||||
// to Discord. These are all exported and you may modify them if needed.
|
||||
|
||||
package discordgo |
||||
|
||||
// APIVersion is the Discord API version used for the REST and Websocket API.
|
||||
var APIVersion = "6" |
||||
|
||||
// Known Discord API Endpoints.
|
||||
var ( |
||||
EndpointStatus = "https://status.discordapp.com/api/v2/" |
||||
EndpointSm = EndpointStatus + "scheduled-maintenances/" |
||||
EndpointSmActive = EndpointSm + "active.json" |
||||
EndpointSmUpcoming = EndpointSm + "upcoming.json" |
||||
|
||||
EndpointDiscord = "https://discordapp.com/" |
||||
EndpointAPI = EndpointDiscord + "api/v" + APIVersion + "/" |
||||
EndpointGuilds = EndpointAPI + "guilds/" |
||||
EndpointChannels = EndpointAPI + "channels/" |
||||
EndpointUsers = EndpointAPI + "users/" |
||||
EndpointGateway = EndpointAPI + "gateway" |
||||
EndpointGatewayBot = EndpointGateway + "/bot" |
||||
EndpointWebhooks = EndpointAPI + "webhooks/" |
||||
|
||||
EndpointCDN = "https://cdn.discordapp.com/" |
||||
EndpointCDNAttachments = EndpointCDN + "attachments/" |
||||
EndpointCDNAvatars = EndpointCDN + "avatars/" |
||||
EndpointCDNIcons = EndpointCDN + "icons/" |
||||
EndpointCDNSplashes = EndpointCDN + "splashes/" |
||||
EndpointCDNChannelIcons = EndpointCDN + "channel-icons/" |
||||
|
||||
EndpointAuth = EndpointAPI + "auth/" |
||||
EndpointLogin = EndpointAuth + "login" |
||||
EndpointLogout = EndpointAuth + "logout" |
||||
EndpointVerify = EndpointAuth + "verify" |
||||
EndpointVerifyResend = EndpointAuth + "verify/resend" |
||||
EndpointForgotPassword = EndpointAuth + "forgot" |
||||
EndpointResetPassword = EndpointAuth + "reset" |
||||
EndpointRegister = EndpointAuth + "register" |
||||
|
||||
EndpointVoice = EndpointAPI + "/voice/" |
||||
EndpointVoiceRegions = EndpointVoice + "regions" |
||||
EndpointVoiceIce = EndpointVoice + "ice" |
||||
|
||||
EndpointTutorial = EndpointAPI + "tutorial/" |
||||
EndpointTutorialIndicators = EndpointTutorial + "indicators" |
||||
|
||||
EndpointTrack = EndpointAPI + "track" |
||||
EndpointSso = EndpointAPI + "sso" |
||||
EndpointReport = EndpointAPI + "report" |
||||
EndpointIntegrations = EndpointAPI + "integrations" |
||||
|
||||
EndpointUser = func(uID string) string { return EndpointUsers + uID } |
||||
EndpointUserAvatar = func(uID, aID string) string { return EndpointCDNAvatars + uID + "/" + aID + ".png" } |
||||
EndpointUserAvatarAnimated = func(uID, aID string) string { return EndpointCDNAvatars + uID + "/" + aID + ".gif" } |
||||
EndpointUserSettings = func(uID string) string { return EndpointUsers + uID + "/settings" } |
||||
EndpointUserGuilds = func(uID string) string { return EndpointUsers + uID + "/guilds" } |
||||
EndpointUserGuild = func(uID, gID string) string { return EndpointUsers + uID + "/guilds/" + gID } |
||||
EndpointUserGuildSettings = func(uID, gID string) string { return EndpointUsers + uID + "/guilds/" + gID + "/settings" } |
||||
EndpointUserChannels = func(uID string) string { return EndpointUsers + uID + "/channels" } |
||||
EndpointUserDevices = func(uID string) string { return EndpointUsers + uID + "/devices" } |
||||
EndpointUserConnections = func(uID string) string { return EndpointUsers + uID + "/connections" } |
||||
EndpointUserNotes = func(uID string) string { return EndpointUsers + "@me/notes/" + uID } |
||||
|
||||
EndpointGuild = func(gID string) string { return EndpointGuilds + gID } |
||||
EndpointGuildChannels = func(gID string) string { return EndpointGuilds + gID + "/channels" } |
||||
EndpointGuildMembers = func(gID string) string { return EndpointGuilds + gID + "/members" } |
||||
EndpointGuildMember = func(gID, uID string) string { return EndpointGuilds + gID + "/members/" + uID } |
||||
EndpointGuildMemberRole = func(gID, uID, rID string) string { return EndpointGuilds + gID + "/members/" + uID + "/roles/" + rID } |
||||
EndpointGuildBans = func(gID string) string { return EndpointGuilds + gID + "/bans" } |
||||
EndpointGuildBan = func(gID, uID string) string { return EndpointGuilds + gID + "/bans/" + uID } |
||||
EndpointGuildIntegrations = func(gID string) string { return EndpointGuilds + gID + "/integrations" } |
||||
EndpointGuildIntegration = func(gID, iID string) string { return EndpointGuilds + gID + "/integrations/" + iID } |
||||
EndpointGuildIntegrationSync = func(gID, iID string) string { return EndpointGuilds + gID + "/integrations/" + iID + "/sync" } |
||||
EndpointGuildRoles = func(gID string) string { return EndpointGuilds + gID + "/roles" } |
||||
EndpointGuildRole = func(gID, rID string) string { return EndpointGuilds + gID + "/roles/" + rID } |
||||
EndpointGuildInvites = func(gID string) string { return EndpointGuilds + gID + "/invites" } |
||||
EndpointGuildEmbed = func(gID string) string { return EndpointGuilds + gID + "/embed" } |
||||
EndpointGuildPrune = func(gID string) string { return EndpointGuilds + gID + "/prune" } |
||||
EndpointGuildIcon = func(gID, hash string) string { return EndpointCDNIcons + gID + "/" + hash + ".png" } |
||||
EndpointGuildSplash = func(gID, hash string) string { return EndpointCDNSplashes + gID + "/" + hash + ".png" } |
||||
EndpointGuildWebhooks = func(gID string) string { return EndpointGuilds + gID + "/webhooks" } |
||||
|
||||
EndpointChannel = func(cID string) string { return EndpointChannels + cID } |
||||
EndpointChannelPermissions = func(cID string) string { return EndpointChannels + cID + "/permissions" } |
||||
EndpointChannelPermission = func(cID, tID string) string { return EndpointChannels + cID + "/permissions/" + tID } |
||||
EndpointChannelInvites = func(cID string) string { return EndpointChannels + cID + "/invites" } |
||||
EndpointChannelTyping = func(cID string) string { return EndpointChannels + cID + "/typing" } |
||||
EndpointChannelMessages = func(cID string) string { return EndpointChannels + cID + "/messages" } |
||||
EndpointChannelMessage = func(cID, mID string) string { return EndpointChannels + cID + "/messages/" + mID } |
||||
EndpointChannelMessageAck = func(cID, mID string) string { return EndpointChannels + cID + "/messages/" + mID + "/ack" } |
||||
EndpointChannelMessagesBulkDelete = func(cID string) string { return EndpointChannel(cID) + "/messages/bulk-delete" } |
||||
EndpointChannelMessagesPins = func(cID string) string { return EndpointChannel(cID) + "/pins" } |
||||
EndpointChannelMessagePin = func(cID, mID string) string { return EndpointChannel(cID) + "/pins/" + mID } |
||||
|
||||
EndpointGroupIcon = func(cID, hash string) string { return EndpointCDNChannelIcons + cID + "/" + hash + ".png" } |
||||
|
||||
EndpointChannelWebhooks = func(cID string) string { return EndpointChannel(cID) + "/webhooks" } |
||||
EndpointWebhook = func(wID string) string { return EndpointWebhooks + wID } |
||||
EndpointWebhookToken = func(wID, token string) string { return EndpointWebhooks + wID + "/" + token } |
||||
|
||||
EndpointMessageReactionsAll = func(cID, mID string) string { |
||||
return EndpointChannelMessage(cID, mID) + "/reactions" |
||||
} |
||||
EndpointMessageReactions = func(cID, mID, eID string) string { |
||||
return EndpointChannelMessage(cID, mID) + "/reactions/" + eID |
||||
} |
||||
EndpointMessageReaction = func(cID, mID, eID, uID string) string { |
||||
return EndpointMessageReactions(cID, mID, eID) + "/" + uID |
||||
} |
||||
|
||||
EndpointRelationships = func() string { return EndpointUsers + "@me" + "/relationships" } |
||||
EndpointRelationship = func(uID string) string { return EndpointRelationships() + "/" + uID } |
||||
EndpointRelationshipsMutual = func(uID string) string { return EndpointUsers + uID + "/relationships" } |
||||
|
||||
EndpointGuildCreate = EndpointAPI + "guilds" |
||||
|
||||
EndpointInvite = func(iID string) string { return EndpointAPI + "invite/" + iID } |
||||
|
||||
EndpointIntegrationsJoin = func(iID string) string { return EndpointAPI + "integrations/" + iID + "/join" } |
||||
|
||||
EndpointEmoji = func(eID string) string { return EndpointAPI + "emojis/" + eID + ".png" } |
||||
|
||||
EndpointOauth2 = EndpointAPI + "oauth2/" |
||||
EndpointApplications = EndpointOauth2 + "applications" |
||||
EndpointApplication = func(aID string) string { return EndpointApplications + "/" + aID } |
||||
EndpointApplicationsBot = func(aID string) string { return EndpointApplications + "/" + aID + "/bot" } |
||||
) |
@ -0,0 +1,238 @@
@@ -0,0 +1,238 @@
|
||||
package discordgo |
||||
|
||||
// EventHandler is an interface for Discord events.
|
||||
type EventHandler interface { |
||||
// Type returns the type of event this handler belongs to.
|
||||
Type() string |
||||
|
||||
// Handle is called whenever an event of Type() happens.
|
||||
// It is the receivers responsibility to type assert that the interface
|
||||
// is the expected struct.
|
||||
Handle(*Session, interface{}) |
||||
} |
||||
|
||||
// EventInterfaceProvider is an interface for providing empty interfaces for
|
||||
// Discord events.
|
||||
type EventInterfaceProvider interface { |
||||
// Type is the type of event this handler belongs to.
|
||||
Type() string |
||||
|
||||
// New returns a new instance of the struct this event handler handles.
|
||||
// This is called once per event.
|
||||
// The struct is provided to all handlers of the same Type().
|
||||
New() interface{} |
||||
} |
||||
|
||||
// interfaceEventType is the event handler type for interface{} events.
|
||||
const interfaceEventType = "__INTERFACE__" |
||||
|
||||
// interfaceEventHandler is an event handler for interface{} events.
|
||||
type interfaceEventHandler func(*Session, interface{}) |
||||
|
||||
// Type returns the event type for interface{} events.
|
||||
func (eh interfaceEventHandler) Type() string { |
||||
return interfaceEventType |
||||
} |
||||
|
||||
// Handle is the handler for an interface{} event.
|
||||
func (eh interfaceEventHandler) Handle(s *Session, i interface{}) { |
||||
eh(s, i) |
||||
} |
||||
|
||||
var registeredInterfaceProviders = map[string]EventInterfaceProvider{} |
||||
|
||||
// registerInterfaceProvider registers a provider so that DiscordGo can
|
||||
// access it's New() method.
|
||||
func registerInterfaceProvider(eh EventInterfaceProvider) { |
||||
if _, ok := registeredInterfaceProviders[eh.Type()]; ok { |
||||
return |
||||
// XXX:
|
||||
// if we should error here, we need to do something with it.
|
||||
// fmt.Errorf("event %s already registered", eh.Type())
|
||||
} |
||||
registeredInterfaceProviders[eh.Type()] = eh |
||||
return |
||||
} |
||||
|
||||
// eventHandlerInstance is a wrapper around an event handler, as functions
|
||||
// cannot be compared directly.
|
||||
type eventHandlerInstance struct { |
||||
eventHandler EventHandler |
||||
} |
||||
|
||||
// addEventHandler adds an event handler that will be fired anytime
|
||||
// the Discord WSAPI matching eventHandler.Type() fires.
|
||||
func (s *Session) addEventHandler(eventHandler EventHandler) func() { |
||||
s.handlersMu.Lock() |
||||
defer s.handlersMu.Unlock() |
||||
|
||||
if s.handlers == nil { |
||||
s.handlers = map[string][]*eventHandlerInstance{} |
||||
} |
||||
|
||||
ehi := &eventHandlerInstance{eventHandler} |
||||
s.handlers[eventHandler.Type()] = append(s.handlers[eventHandler.Type()], ehi) |
||||
|
||||
return func() { |
||||
s.removeEventHandlerInstance(eventHandler.Type(), ehi) |
||||
} |
||||
} |
||||
|
||||
// addEventHandler adds an event handler that will be fired the next time
|
||||
// the Discord WSAPI matching eventHandler.Type() fires.
|
||||
func (s *Session) addEventHandlerOnce(eventHandler EventHandler) func() { |
||||
s.handlersMu.Lock() |
||||
defer s.handlersMu.Unlock() |
||||
|
||||
if s.onceHandlers == nil { |
||||
s.onceHandlers = map[string][]*eventHandlerInstance{} |
||||
} |
||||
|
||||
ehi := &eventHandlerInstance{eventHandler} |
||||
s.onceHandlers[eventHandler.Type()] = append(s.onceHandlers[eventHandler.Type()], ehi) |
||||
|
||||
return func() { |
||||
s.removeEventHandlerInstance(eventHandler.Type(), ehi) |
||||
} |
||||
} |
||||
|
||||
// AddHandler allows you to add an event handler that will be fired anytime
|
||||
// the Discord WSAPI event that matches the function fires.
|
||||
// events.go contains all the Discord WSAPI events that can be fired.
|
||||
// eg:
|
||||
// Session.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
// })
|
||||
//
|
||||
// or:
|
||||
// Session.AddHandler(func(s *discordgo.Session, m *discordgo.PresenceUpdate) {
|
||||
// })
|
||||
// The return value of this method is a function, that when called will remove the
|
||||
// event handler.
|
||||
func (s *Session) AddHandler(handler interface{}) func() { |
||||
eh := handlerForInterface(handler) |
||||
|
||||
if eh == nil { |
||||
s.log(LogError, "Invalid handler type, handler will never be called") |
||||
return func() {} |
||||
} |
||||
|
||||
return s.addEventHandler(eh) |
||||
} |
||||
|
||||
// AddHandlerOnce allows you to add an event handler that will be fired the next time
|
||||
// the Discord WSAPI event that matches the function fires.
|
||||
// See AddHandler for more details.
|
||||
func (s *Session) AddHandlerOnce(handler interface{}) func() { |
||||
eh := handlerForInterface(handler) |
||||
|
||||
if eh == nil { |
||||
s.log(LogError, "Invalid handler type, handler will never be called") |
||||
return func() {} |
||||
} |
||||
|
||||
return s.addEventHandlerOnce(eh) |
||||
} |
||||
|
||||
// removeEventHandler instance removes an event handler instance.
|
||||
func (s *Session) removeEventHandlerInstance(t string, ehi *eventHandlerInstance) { |
||||
s.handlersMu.Lock() |
||||
defer s.handlersMu.Unlock() |
||||
|
||||
handlers := s.handlers[t] |
||||
for i := range handlers { |
||||
if handlers[i] == ehi { |
||||
s.handlers[t] = append(handlers[:i], handlers[i+1:]...) |
||||
} |
||||
} |
||||
|
||||
onceHandlers := s.onceHandlers[t] |
||||
for i := range onceHandlers { |
||||
if onceHandlers[i] == ehi { |
||||
s.onceHandlers[t] = append(onceHandlers[:i], handlers[i+1:]...) |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Handles calling permanent and once handlers for an event type.
|
||||
func (s *Session) handle(t string, i interface{}) { |
||||
for _, eh := range s.handlers[t] { |
||||
if s.SyncEvents { |
||||
eh.eventHandler.Handle(s, i) |
||||
} else { |
||||
go eh.eventHandler.Handle(s, i) |
||||
} |
||||
} |
||||
|
||||
if len(s.onceHandlers[t]) > 0 { |
||||
for _, eh := range s.onceHandlers[t] { |
||||
if s.SyncEvents { |
||||
eh.eventHandler.Handle(s, i) |
||||
} else { |
||||
go eh.eventHandler.Handle(s, i) |
||||
} |
||||
} |
||||
s.onceHandlers[t] = nil |
||||
} |
||||
} |
||||
|
||||
// Handles an event type by calling internal methods, firing handlers and firing the
|
||||
// interface{} event.
|
||||
func (s *Session) handleEvent(t string, i interface{}) { |
||||
s.handlersMu.RLock() |
||||
defer s.handlersMu.RUnlock() |
||||
|
||||
// All events are dispatched internally first.
|
||||
s.onInterface(i) |
||||
|
||||
// Then they are dispatched to anyone handling interface{} events.
|
||||
s.handle(interfaceEventType, i) |
||||
|
||||
// Finally they are dispatched to any typed handlers.
|
||||
s.handle(t, i) |
||||
} |
||||
|
||||
// setGuildIds will set the GuildID on all the members of a guild.
|
||||
// This is done as event data does not have it set.
|
||||
func setGuildIds(g *Guild) { |
||||
for _, c := range g.Channels { |
||||
c.GuildID = g.ID |
||||
} |
||||
|
||||
for _, m := range g.Members { |
||||
m.GuildID = g.ID |
||||
} |
||||
|
||||
for _, vs := range g.VoiceStates { |
||||
vs.GuildID = g.ID |
||||
} |
||||
} |
||||
|
||||
// onInterface handles all internal events and routes them to the appropriate internal handler.
|
||||
func (s *Session) onInterface(i interface{}) { |
||||
switch t := i.(type) { |
||||
case *Ready: |
||||
for _, g := range t.Guilds { |
||||
setGuildIds(g) |
||||
} |
||||
s.onReady(t) |
||||
case *GuildCreate: |
||||
setGuildIds(t.Guild) |
||||
case *GuildUpdate: |
||||
setGuildIds(t.Guild) |
||||
case *VoiceServerUpdate: |
||||
go s.onVoiceServerUpdate(t) |
||||
case *VoiceStateUpdate: |
||||
go s.onVoiceStateUpdate(t) |
||||
} |
||||
err := s.State.OnInterface(s, i) |
||||
if err != nil { |
||||
s.log(LogDebug, "error dispatching internal event, %s", err) |
||||
} |
||||
} |
||||
|
||||
// onReady handles the ready event.
|
||||
func (s *Session) onReady(r *Ready) { |
||||
|
||||
// Store the SessionID within the Session struct.
|
||||
s.sessionID = r.SessionID |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,253 @@
@@ -0,0 +1,253 @@
|
||||
package discordgo |
||||
|
||||
import ( |
||||
"encoding/json" |
||||
) |
||||
|
||||
// This file contains all the possible structs that can be
|
||||
// handled by AddHandler/EventHandler.
|
||||
// DO NOT ADD ANYTHING BUT EVENT HANDLER STRUCTS TO THIS FILE.
|
||||
//go:generate go run tools/cmd/eventhandlers/main.go
|
||||
|
||||
// Connect is the data for a Connect event.
|
||||
// This is a sythetic event and is not dispatched by Discord.
|
||||
type Connect struct{} |
||||
|
||||
// Disconnect is the data for a Disconnect event.
|
||||
// This is a sythetic event and is not dispatched by Discord.
|
||||
type Disconnect struct{} |
||||
|
||||
// RateLimit is the data for a RateLimit event.
|
||||
// This is a sythetic event and is not dispatched by Discord.
|
||||
type RateLimit struct { |
||||
*TooManyRequests |
||||
URL string |
||||
} |
||||
|
||||
// Event provides a basic initial struct for all websocket events.
|
||||
type Event struct { |
||||
Operation int `json:"op"` |
||||
Sequence int64 `json:"s"` |
||||
Type string `json:"t"` |
||||
RawData json.RawMessage `json:"d"` |
||||
// Struct contains one of the other types in this file.
|
||||
Struct interface{} `json:"-"` |
||||
} |
||||
|
||||
// A Ready stores all data for the websocket READY event.
|
||||
type Ready struct { |
||||
Version int `json:"v"` |
||||
SessionID string `json:"session_id"` |
||||
User *User `json:"user"` |
||||
ReadState []*ReadState `json:"read_state"` |
||||
PrivateChannels []*Channel `json:"private_channels"` |
||||
Guilds []*Guild `json:"guilds"` |
||||
|
||||
// Undocumented fields
|
||||
Settings *Settings `json:"user_settings"` |
||||
UserGuildSettings []*UserGuildSettings `json:"user_guild_settings"` |
||||
Relationships []*Relationship `json:"relationships"` |
||||
Presences []*Presence `json:"presences"` |
||||
Notes map[string]string `json:"notes"` |
||||
} |
||||
|
||||
// ChannelCreate is the data for a ChannelCreate event.
|
||||
type ChannelCreate struct { |
||||
*Channel |
||||
} |
||||
|
||||
// ChannelUpdate is the data for a ChannelUpdate event.
|
||||
type ChannelUpdate struct { |
||||
*Channel |
||||
} |
||||
|
||||
// ChannelDelete is the data for a ChannelDelete event.
|
||||
type ChannelDelete struct { |
||||
*Channel |
||||
} |
||||
|
||||
// ChannelPinsUpdate stores data for a ChannelPinsUpdate event.
|
||||
type ChannelPinsUpdate struct { |
||||
LastPinTimestamp string `json:"last_pin_timestamp"` |
||||
ChannelID string `json:"channel_id"` |
||||
} |
||||
|
||||
// GuildCreate is the data for a GuildCreate event.
|
||||
type GuildCreate struct { |
||||
*Guild |
||||
} |
||||
|
||||
// GuildUpdate is the data for a GuildUpdate event.
|
||||
type GuildUpdate struct { |
||||
*Guild |
||||
} |
||||
|
||||
// GuildDelete is the data for a GuildDelete event.
|
||||
type GuildDelete struct { |
||||
*Guild |
||||
} |
||||
|
||||
// GuildBanAdd is the data for a GuildBanAdd event.
|
||||
type GuildBanAdd struct { |
||||
User *User `json:"user"` |
||||
GuildID string `json:"guild_id"` |
||||
} |
||||
|
||||
// GuildBanRemove is the data for a GuildBanRemove event.
|
||||
type GuildBanRemove struct { |
||||
User *User `json:"user"` |
||||
GuildID string `json:"guild_id"` |
||||
} |
||||
|
||||
// GuildMemberAdd is the data for a GuildMemberAdd event.
|
||||
type GuildMemberAdd struct { |
||||
*Member |
||||
} |
||||
|
||||
// GuildMemberUpdate is the data for a GuildMemberUpdate event.
|
||||
type GuildMemberUpdate struct { |
||||
*Member |
||||
} |
||||
|
||||
// GuildMemberRemove is the data for a GuildMemberRemove event.
|
||||
type GuildMemberRemove struct { |
||||
*Member |
||||
} |
||||
|
||||
// GuildRoleCreate is the data for a GuildRoleCreate event.
|
||||
type GuildRoleCreate struct { |
||||
*GuildRole |
||||
} |
||||
|
||||
// GuildRoleUpdate is the data for a GuildRoleUpdate event.
|
||||
type GuildRoleUpdate struct { |
||||
*GuildRole |
||||
} |
||||
|
||||
// A GuildRoleDelete is the data for a GuildRoleDelete event.
|
||||
type GuildRoleDelete struct { |
||||
RoleID string `json:"role_id"` |
||||
GuildID string `json:"guild_id"` |
||||
} |
||||
|
||||
// A GuildEmojisUpdate is the data for a guild emoji update event.
|
||||
type GuildEmojisUpdate struct { |
||||
GuildID string `json:"guild_id"` |
||||
Emojis []*Emoji `json:"emojis"` |
||||
} |
||||
|
||||
// A GuildMembersChunk is the data for a GuildMembersChunk event.
|
||||
type GuildMembersChunk struct { |
||||
GuildID string `json:"guild_id"` |
||||
Members []*Member `json:"members"` |
||||
} |
||||
|
||||
// GuildIntegrationsUpdate is the data for a GuildIntegrationsUpdate event.
|
||||
type GuildIntegrationsUpdate struct { |
||||
GuildID string `json:"guild_id"` |
||||
} |
||||
|
||||
// MessageAck is the data for a MessageAck event.
|
||||
type MessageAck struct { |
||||
MessageID string `json:"message_id"` |
||||
ChannelID string `json:"channel_id"` |
||||
} |
||||
|
||||
// MessageCreate is the data for a MessageCreate event.
|
||||
type MessageCreate struct { |
||||
*Message |
||||
} |
||||
|
||||
// MessageUpdate is the data for a MessageUpdate event.
|
||||
type MessageUpdate struct { |
||||
*Message |
||||
} |
||||
|
||||
// MessageDelete is the data for a MessageDelete event.
|
||||
type MessageDelete struct { |
||||
*Message |
||||
} |
||||
|
||||
// MessageReactionAdd is the data for a MessageReactionAdd event.
|
||||
type MessageReactionAdd struct { |
||||
*MessageReaction |
||||
} |
||||
|
||||
// MessageReactionRemove is the data for a MessageReactionRemove event.
|
||||
type MessageReactionRemove struct { |
||||
*MessageReaction |
||||
} |
||||
|
||||
// MessageReactionRemoveAll is the data for a MessageReactionRemoveAll event.
|
||||
type MessageReactionRemoveAll struct { |
||||
*MessageReaction |
||||
} |
||||
|
||||
// PresencesReplace is the data for a PresencesReplace event.
|
||||
type PresencesReplace []*Presence |
||||
|
||||
// PresenceUpdate is the data for a PresenceUpdate event.
|
||||
type PresenceUpdate struct { |
||||
Presence |
||||
GuildID string `json:"guild_id"` |
||||
Roles []string `json:"roles"` |
||||
} |
||||
|
||||
// Resumed is the data for a Resumed event.
|
||||
type Resumed struct { |
||||
Trace []string `json:"_trace"` |
||||
} |
||||
|
||||
// RelationshipAdd is the data for a RelationshipAdd event.
|
||||
type RelationshipAdd struct { |
||||
*Relationship |
||||
} |
||||
|
||||
// RelationshipRemove is the data for a RelationshipRemove event.
|
||||
type RelationshipRemove struct { |
||||
*Relationship |
||||
} |
||||
|
||||
// TypingStart is the data for a TypingStart event.
|
||||
type TypingStart struct { |
||||
UserID string `json:"user_id"` |
||||
ChannelID string `json:"channel_id"` |
||||
Timestamp int `json:"timestamp"` |
||||
} |
||||
|
||||
// UserUpdate is the data for a UserUpdate event.
|
||||
type UserUpdate struct { |
||||
*User |
||||
} |
||||
|
||||
// UserSettingsUpdate is the data for a UserSettingsUpdate event.
|
||||
type UserSettingsUpdate map[string]interface{} |
||||
|
||||
// UserGuildSettingsUpdate is the data for a UserGuildSettingsUpdate event.
|
||||
type UserGuildSettingsUpdate struct { |
||||
*UserGuildSettings |
||||
} |
||||
|
||||
// UserNoteUpdate is the data for a UserNoteUpdate event.
|
||||
type UserNoteUpdate struct { |
||||
ID string `json:"id"` |
||||
Note string `json:"note"` |
||||
} |
||||
|
||||
// VoiceServerUpdate is the data for a VoiceServerUpdate event.
|
||||
type VoiceServerUpdate struct { |
||||
Token string `json:"token"` |
||||
GuildID string `json:"guild_id"` |
||||
Endpoint string `json:"endpoint"` |
||||
} |
||||
|
||||
// VoiceStateUpdate is the data for a VoiceStateUpdate event.
|
||||
type VoiceStateUpdate struct { |
||||
*VoiceState |
||||
} |
||||
|
||||
// MessageDeleteBulk is the data for a MessageDeleteBulk event
|
||||
type MessageDeleteBulk struct { |
||||
Messages []string `json:"ids"` |
||||
ChannelID string `json:"channel_id"` |
||||
} |
@ -0,0 +1,103 @@
@@ -0,0 +1,103 @@
|
||||
// Discordgo - Discord bindings for Go
|
||||
// Available at https://github.com/bwmarrin/discordgo
|
||||
|
||||
// Copyright 2015-2016 Bruce Marriner <bruce@sqls.net>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file contains code related to discordgo package logging
|
||||
|
||||
package discordgo |
||||
|
||||
import ( |
||||
"fmt" |
||||
"log" |
||||
"runtime" |
||||
"strings" |
||||
) |
||||
|
||||
const ( |
||||
|
||||
// LogError level is used for critical errors that could lead to data loss
|
||||
// or panic that would not be returned to a calling function.
|
||||
LogError int = iota |
||||
|
||||
// LogWarning level is used for very abnormal events and errors that are
|
||||
// also returned to a calling function.
|
||||
LogWarning |
||||
|
||||
// LogInformational level is used for normal non-error activity
|
||||
LogInformational |
||||
|
||||
// LogDebug level is for very detailed non-error activity. This is
|
||||
// very spammy and will impact performance.
|
||||
LogDebug |
||||
) |
||||
|
||||
// Logger can be used to replace the standard logging for discordgo
|
||||
var Logger func(msgL, caller int, format string, a ...interface{}) |
||||
|
||||
// msglog provides package wide logging consistancy for discordgo
|
||||
// the format, a... portion this command follows that of fmt.Printf
|
||||
// msgL : LogLevel of the message
|
||||
// caller : 1 + the number of callers away from the message source
|
||||
// format : Printf style message format
|
||||
// a ... : comma separated list of values to pass
|
||||
func msglog(msgL, caller int, format string, a ...interface{}) { |
||||
|
||||
if Logger != nil { |
||||
Logger(msgL, caller, format, a...) |
||||
} else { |
||||
|
||||
pc, file, line, _ := runtime.Caller(caller) |
||||
|
||||
files := strings.Split(file, "/") |
||||
file = files[len(files)-1] |
||||
|
||||
name := runtime.FuncForPC(pc).Name() |
||||
fns := strings.Split(name, ".") |
||||
name = fns[len(fns)-1] |
||||
|
||||
msg := fmt.Sprintf(format, a...) |
||||
|
||||
log.Printf("[DG%d] %s:%d:%s() %s\n", msgL, file, line, name, msg) |
||||
} |
||||
} |
||||
|
||||
// helper function that wraps msglog for the Session struct
|
||||
// This adds a check to insure the message is only logged
|
||||
// if the session log level is equal or higher than the
|
||||
// message log level
|
||||
func (s *Session) log(msgL int, format string, a ...interface{}) { |
||||
|
||||
if msgL > s.LogLevel { |
||||
return |
||||
} |
||||
|
||||
msglog(msgL, 2, format, a...) |
||||
} |
||||
|
||||
// helper function that wraps msglog for the VoiceConnection struct
|
||||
// This adds a check to insure the message is only logged
|
||||
// if the voice connection log level is equal or higher than the
|
||||
// message log level
|
||||
func (v *VoiceConnection) log(msgL int, format string, a ...interface{}) { |
||||
|
||||
if msgL > v.LogLevel { |
||||
return |
||||
} |
||||
|
||||
msglog(msgL, 2, format, a...) |
||||
} |
||||
|
||||
// printJSON is a helper function to display JSON data in a easy to read format.
|
||||
/* NOT USED ATM |
||||
func printJSON(body []byte) { |
||||
var prettyJSON bytes.Buffer |
||||
error := json.Indent(&prettyJSON, body, "", "\t") |
||||
if error != nil { |
||||
log.Print("JSON parse error: ", error) |
||||
} |
||||
log.Println(string(prettyJSON.Bytes())) |
||||
} |
||||
*/ |
@ -0,0 +1,252 @@
@@ -0,0 +1,252 @@
|
||||
// Discordgo - Discord bindings for Go
|
||||
// Available at https://github.com/bwmarrin/discordgo
|
||||
|
||||
// Copyright 2015-2016 Bruce Marriner <bruce@sqls.net>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file contains code related to the Message struct
|
||||
|
||||
package discordgo |
||||
|
||||
import ( |
||||
"io" |
||||
"regexp" |
||||
"strings" |
||||
) |
||||
|
||||
// MessageType is the type of Message
|
||||
type MessageType int |
||||
|
||||
// Block contains the valid known MessageType values
|
||||
const ( |
||||
MessageTypeDefault MessageType = iota |
||||
MessageTypeRecipientAdd |
||||
MessageTypeRecipientRemove |
||||
MessageTypeCall |
||||
MessageTypeChannelNameChange |
||||
MessageTypeChannelIconChange |
||||
MessageTypeChannelPinnedMessage |
||||
MessageTypeGuildMemberJoin |
||||
) |
||||
|
||||
// A Message stores all data related to a specific Discord message.
|
||||
type Message struct { |
||||
ID string `json:"id"` |
||||
ChannelID string `json:"channel_id"` |
||||
Content string `json:"content"` |
||||
Timestamp Timestamp `json:"timestamp"` |
||||
EditedTimestamp Timestamp `json:"edited_timestamp"` |
||||
MentionRoles []string `json:"mention_roles"` |
||||
Tts bool `json:"tts"` |
||||
MentionEveryone bool `json:"mention_everyone"` |
||||
Author *User `json:"author"` |
||||
Attachments []*MessageAttachment `json:"attachments"` |
||||
Embeds []*MessageEmbed `json:"embeds"` |
||||
Mentions []*User `json:"mentions"` |
||||
Reactions []*MessageReactions `json:"reactions"` |
||||
Type MessageType `json:"type"` |
||||
} |
||||
|
||||
// File stores info about files you e.g. send in messages.
|
||||
type File struct { |
||||
Name string |
||||
ContentType string |
||||
Reader io.Reader |
||||
} |
||||
|
||||
// MessageSend stores all parameters you can send with ChannelMessageSendComplex.
|
||||
type MessageSend struct { |
||||
Content string `json:"content,omitempty"` |
||||
Embed *MessageEmbed `json:"embed,omitempty"` |
||||
Tts bool `json:"tts"` |
||||
Files []*File `json:"-"` |
||||
|
||||
// TODO: Remove this when compatibility is not required.
|
||||
File *File `json:"-"` |
||||
} |
||||
|
||||
// MessageEdit is used to chain parameters via ChannelMessageEditComplex, which
|
||||
// is also where you should get the instance from.
|
||||
type MessageEdit struct { |
||||
Content *string `json:"content,omitempty"` |
||||
Embed *MessageEmbed `json:"embed,omitempty"` |
||||
|
||||
ID string |
||||
Channel string |
||||
} |
||||
|
||||
// NewMessageEdit returns a MessageEdit struct, initialized
|
||||
// with the Channel and ID.
|
||||
func NewMessageEdit(channelID string, messageID string) *MessageEdit { |
||||
return &MessageEdit{ |
||||
Channel: channelID, |
||||
ID: messageID, |
||||
} |
||||
} |
||||
|
||||
// SetContent is the same as setting the variable Content,
|
||||
// except it doesn't take a pointer.
|
||||
func (m *MessageEdit) SetContent(str string) *MessageEdit { |
||||
m.Content = &str |
||||
return m |
||||
} |
||||
|
||||
// SetEmbed is a convenience function for setting the embed,
|
||||
// so you can chain commands.
|
||||
func (m *MessageEdit) SetEmbed(embed *MessageEmbed) *MessageEdit { |
||||
m.Embed = embed |
||||
return m |
||||
} |
||||
|
||||
// A MessageAttachment stores data for message attachments.
|
||||
type MessageAttachment struct { |
||||
ID string `json:"id"` |
||||
URL string `json:"url"` |
||||
ProxyURL string `json:"proxy_url"` |
||||
Filename string `json:"filename"` |
||||
Width int `json:"width"` |
||||
Height int `json:"height"` |
||||
Size int `json:"size"` |
||||
} |
||||
|
||||
// MessageEmbedFooter is a part of a MessageEmbed struct.
|
||||
type MessageEmbedFooter struct { |
||||
Text string `json:"text,omitempty"` |
||||
IconURL string `json:"icon_url,omitempty"` |
||||
ProxyIconURL string `json:"proxy_icon_url,omitempty"` |
||||
} |
||||
|
||||
// MessageEmbedImage is a part of a MessageEmbed struct.
|
||||
type MessageEmbedImage struct { |
||||
URL string `json:"url,omitempty"` |
||||
ProxyURL string `json:"proxy_url,omitempty"` |
||||
Width int `json:"width,omitempty"` |
||||
Height int `json:"height,omitempty"` |
||||
} |
||||
|
||||
// MessageEmbedThumbnail is a part of a MessageEmbed struct.
|
||||
type MessageEmbedThumbnail struct { |
||||
URL string `json:"url,omitempty"` |
||||
ProxyURL string `json:"proxy_url,omitempty"` |
||||
Width int `json:"width,omitempty"` |
||||
Height int `json:"height,omitempty"` |
||||
} |
||||
|
||||
// MessageEmbedVideo is a part of a MessageEmbed struct.
|
||||
type MessageEmbedVideo struct { |
||||
URL string `json:"url,omitempty"` |
||||
ProxyURL string `json:"proxy_url,omitempty"` |
||||
Width int `json:"width,omitempty"` |
||||
Height int `json:"height,omitempty"` |
||||
} |
||||
|
||||
// MessageEmbedProvider is a part of a MessageEmbed struct.
|
||||
type MessageEmbedProvider struct { |
||||
URL string `json:"url,omitempty"` |
||||
Name string `json:"name,omitempty"` |
||||
} |
||||
|
||||
// MessageEmbedAuthor is a part of a MessageEmbed struct.
|
||||
type MessageEmbedAuthor struct { |
||||
URL string `json:"url,omitempty"` |
||||
Name string `json:"name,omitempty"` |
||||
IconURL string `json:"icon_url,omitempty"` |
||||
ProxyIconURL string `json:"proxy_icon_url,omitempty"` |
||||
} |
||||
|
||||
// MessageEmbedField is a part of a MessageEmbed struct.
|
||||
type MessageEmbedField struct { |
||||
Name string `json:"name,omitempty"` |
||||
Value string `json:"value,omitempty"` |
||||
Inline bool `json:"inline,omitempty"` |
||||
} |
||||
|
||||
// An MessageEmbed stores data for message embeds.
|
||||
type MessageEmbed struct { |
||||
URL string `json:"url,omitempty"` |
||||
Type string `json:"type,omitempty"` |
||||
Title string `json:"title,omitempty"` |
||||
Description string `json:"description,omitempty"` |
||||
Timestamp string `json:"timestamp,omitempty"` |
||||
Color int `json:"color,omitempty"` |
||||
Footer *MessageEmbedFooter `json:"footer,omitempty"` |
||||
Image *MessageEmbedImage `json:"image,omitempty"` |
||||
Thumbnail *MessageEmbedThumbnail `json:"thumbnail,omitempty"` |
||||
Video *MessageEmbedVideo `json:"video,omitempty"` |
||||
Provider *MessageEmbedProvider `json:"provider,omitempty"` |
||||
Author *MessageEmbedAuthor `json:"author,omitempty"` |
||||
Fields []*MessageEmbedField `json:"fields,omitempty"` |
||||
} |
||||
|
||||
// MessageReactions holds a reactions object for a message.
|
||||
type MessageReactions struct { |
||||
Count int `json:"count"` |
||||
Me bool `json:"me"` |
||||
Emoji *Emoji `json:"emoji"` |
||||
} |
||||
|
||||
// ContentWithMentionsReplaced will replace all @<id> mentions with the
|
||||
// username of the mention.
|
||||
func (m *Message) ContentWithMentionsReplaced() (content string) { |
||||
content = m.Content |
||||
|
||||
for _, user := range m.Mentions { |
||||
content = strings.NewReplacer( |
||||
"<@"+user.ID+">", "@"+user.Username, |
||||
"<@!"+user.ID+">", "@"+user.Username, |
||||
).Replace(content) |
||||
} |
||||
return |
||||
} |
||||
|
||||
var patternChannels = regexp.MustCompile("<#[^>]*>") |
||||
|
||||
// ContentWithMoreMentionsReplaced will replace all @<id> mentions with the
|
||||
// username of the mention, but also role IDs and more.
|
||||
func (m *Message) ContentWithMoreMentionsReplaced(s *Session) (content string, err error) { |
||||
content = m.Content |
||||
|
||||
if !s.StateEnabled { |
||||
content = m.ContentWithMentionsReplaced() |
||||
return |
||||
} |
||||
|
||||
channel, err := s.State.Channel(m.ChannelID) |
||||
if err != nil { |
||||
content = m.ContentWithMentionsReplaced() |
||||
return |
||||
} |
||||
|
||||
for _, user := range m.Mentions { |
||||
nick := user.Username |
||||
|
||||
member, err := s.State.Member(channel.GuildID, user.ID) |
||||
if err == nil && member.Nick != "" { |
||||
nick = member.Nick |
||||
} |
||||
|
||||
content = strings.NewReplacer( |
||||
"<@"+user.ID+">", "@"+user.Username, |
||||
"<@!"+user.ID+">", "@"+nick, |
||||
).Replace(content) |
||||
} |
||||
for _, roleID := range m.MentionRoles { |
||||
role, err := s.State.Role(channel.GuildID, roleID) |
||||
if err != nil || !role.Mentionable { |
||||
continue |
||||
} |
||||
|
||||
content = strings.Replace(content, "<&"+role.ID+">", "@"+role.Name, -1) |
||||
} |
||||
|
||||
content = patternChannels.ReplaceAllStringFunc(content, func(mention string) string { |
||||
channel, err := s.State.Channel(mention[2 : len(mention)-1]) |
||||
if err != nil || channel.Type == ChannelTypeGuildVoice { |
||||
return mention |
||||
} |
||||
|
||||
return "#" + channel.Name |
||||
}) |
||||
return |
||||
} |
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
site_name: DiscordGo |
||||
site_author: Bruce Marriner |
||||
site_url: http://bwmarrin.github.io/discordgo/ |
||||
repo_url: https://github.com/bwmarrin/discordgo |
||||
|
||||
dev_addr: 0.0.0.0:8000 |
||||
theme: yeti |
||||
|
||||
markdown_extensions: |
||||
- smarty |
||||
- toc: |
||||
permalink: True |
||||
- sane_lists |
||||
|
||||
pages: |
||||
- 'Home': 'index.md' |
||||
- 'Getting Started': 'GettingStarted.md' |
@ -0,0 +1,126 @@
@@ -0,0 +1,126 @@
|
||||
// Discordgo - Discord bindings for Go
|
||||
// Available at https://github.com/bwmarrin/discordgo
|
||||
|
||||
// Copyright 2015-2016 Bruce Marriner <bruce@sqls.net>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file contains functions related to Discord OAuth2 endpoints
|
||||
|
||||
package discordgo |
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Code specific to Discord OAuth2 Applications
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
// An Application struct stores values for a Discord OAuth2 Application
|
||||
type Application struct { |
||||
ID string `json:"id,omitempty"` |
||||
Name string `json:"name"` |
||||
Description string `json:"description,omitempty"` |
||||
Icon string `json:"icon,omitempty"` |
||||
Secret string `json:"secret,omitempty"` |
||||
RedirectURIs *[]string `json:"redirect_uris,omitempty"` |
||||
BotRequireCodeGrant bool `json:"bot_require_code_grant,omitempty"` |
||||
BotPublic bool `json:"bot_public,omitempty"` |
||||
RPCApplicationState int `json:"rpc_application_state,omitempty"` |
||||
Flags int `json:"flags,omitempty"` |
||||
Owner *User `json:"owner"` |
||||
Bot *User `json:"bot"` |
||||
} |
||||
|
||||
// Application returns an Application structure of a specific Application
|
||||
// appID : The ID of an Application
|
||||
func (s *Session) Application(appID string) (st *Application, err error) { |
||||
|
||||
body, err := s.RequestWithBucketID("GET", EndpointApplication(appID), nil, EndpointApplication("")) |
||||
if err != nil { |
||||
return |
||||
} |
||||
|
||||
err = unmarshal(body, &st) |
||||
return |
||||
} |
||||
|
||||
// Applications returns all applications for the authenticated user
|
||||
func (s *Session) Applications() (st []*Application, err error) { |
||||
|
||||
body, err := s.RequestWithBucketID("GET", EndpointApplications, nil, EndpointApplications) |
||||
if err != nil { |
||||
return |
||||
} |
||||
|
||||
err = unmarshal(body, &st) |
||||
return |
||||
} |
||||
|
||||
// ApplicationCreate creates a new Application
|
||||
// name : Name of Application / Bot
|
||||
// uris : Redirect URIs (Not required)
|
||||
func (s *Session) ApplicationCreate(ap *Application) (st *Application, err error) { |
||||
|
||||
data := struct { |
||||
Name string `json:"name"` |
||||
Description string `json:"description"` |
||||
RedirectURIs *[]string `json:"redirect_uris,omitempty"` |
||||
}{ap.Name, ap.Description, ap.RedirectURIs} |
||||
|
||||
body, err := s.RequestWithBucketID("POST", EndpointApplications, data, EndpointApplications) |
||||
if err != nil { |
||||
return |
||||
} |
||||
|
||||
err = unmarshal(body, &st) |
||||
return |
||||
} |
||||
|
||||
// ApplicationUpdate updates an existing Application
|
||||
// var : desc
|
||||
func (s *Session) ApplicationUpdate(appID string, ap *Application) (st *Application, err error) { |
||||
|
||||