WebUI sessions implemented
This commit is contained in:
@@ -691,6 +691,7 @@ func onMessageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
|
|||||||
// Find the collection for the command we got
|
// Find the collection for the command we got
|
||||||
for _, coll := range COLLECTIONS {
|
for _, coll := range COLLECTIONS {
|
||||||
if scontains(parts[0], coll.Commands...) {
|
if scontains(parts[0], coll.Commands...) {
|
||||||
|
go deleteCommandMessage(s, m.ChannelID, m.ID)
|
||||||
|
|
||||||
// If they passed a specific sound effect, find and select that (otherwise play nothing)
|
// If they passed a specific sound effect, find and select that (otherwise play nothing)
|
||||||
var sound *Sound
|
var sound *Sound
|
||||||
@@ -707,7 +708,6 @@ func onMessageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
go enqueuePlay(m.Author, guild, coll, sound)
|
go enqueuePlay(m.Author, guild, coll, sound)
|
||||||
go deleteCommandMessage(s, m.ChannelID, m.ID)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/* http://meyerweb.com/eric/tools/css/reset/
|
||||||
|
v2.0 | 20110126
|
||||||
|
License: none (public domain)
|
||||||
|
*/
|
||||||
|
|
||||||
|
html, body, div, span, applet, object, iframe,
|
||||||
|
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||||
|
a, abbr, acronym, address, big, cite, code,
|
||||||
|
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||||
|
small, strike, strong, sub, sup, tt, var,
|
||||||
|
b, u, i, center,
|
||||||
|
dl, dt, dd, ol, ul, li,
|
||||||
|
fieldset, form, label, legend,
|
||||||
|
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||||
|
article, aside, canvas, details, embed,
|
||||||
|
figure, figcaption, footer, header, hgroup,
|
||||||
|
menu, nav, output, ruby, section, summary,
|
||||||
|
time, mark, audio, video {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
font-size: 100%;
|
||||||
|
font: inherit;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
/* HTML5 display-role reset for older browsers */
|
||||||
|
article, aside, details, figcaption, figure,
|
||||||
|
footer, header, hgroup, menu, nav, section {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
ol, ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
blockquote, q {
|
||||||
|
quotes: none;
|
||||||
|
}
|
||||||
|
blockquote:before, blockquote:after,
|
||||||
|
q:before, q:after {
|
||||||
|
content: '';
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-size: 13px;
|
||||||
|
font-family: 'Open Sans', sans-serif;
|
||||||
|
padding: 0 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
padding: 30px 0;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header h1 {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{{ define "title"}}<title>Example</title>{{ end }}
|
||||||
|
{{ define "content" }}
|
||||||
|
<a href="/discordLogin">Login with Discord</a>
|
||||||
|
{{ end }}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{{ define "base" }}
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="/static/css/style.css">
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,600,700' rel='stylesheet' type='text/css'>
|
||||||
|
{{template "title" . }}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>Example</h1>
|
||||||
|
</header>
|
||||||
|
<div id="page">
|
||||||
|
{{ template "content" . }}
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
{{ end }}
|
||||||
+75
-21
@@ -1,58 +1,103 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/bwmarrin/discordgo"
|
"github.com/bwmarrin/discordgo"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/gorilla/sessions"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const htmlIndex = `<html><body>
|
const (
|
||||||
<a href="/discordLogin">Log in with discord</a>
|
defaultLayout = "templates/layout.html"
|
||||||
</body></html>
|
templateDir = "templates/"
|
||||||
`
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
discordOauthConfig = &oauth2.Config{
|
discordOauthConfig = &oauth2.Config{
|
||||||
RedirectURL: "",
|
RedirectURL: "",
|
||||||
ClientID: "",
|
ClientID: "",
|
||||||
ClientSecret: "",
|
ClientSecret: "",
|
||||||
Scopes: []string{"connections",
|
Scopes: []string{"identify", "guilds"},
|
||||||
"email",
|
|
||||||
"identify",
|
|
||||||
"guilds"},
|
|
||||||
Endpoint: *endp,
|
Endpoint: *endp,
|
||||||
}
|
}
|
||||||
// Some random string, random for each request
|
// Some random string, random for each request
|
||||||
oauthStateString = "random"
|
oauthStateString string
|
||||||
endp = &oauth2.Endpoint{
|
endp = &oauth2.Endpoint{
|
||||||
AuthURL: "https://discordapp.com/api/oauth2/authorize",
|
AuthURL: "https://discordapp.com/api/oauth2/authorize",
|
||||||
TokenURL: "https://discordapp.com/api/oauth2/token",
|
TokenURL: "https://discordapp.com/api/oauth2/token",
|
||||||
}
|
}
|
||||||
|
tmpls = map[string]*template.Template{}
|
||||||
|
// TODO change secret
|
||||||
|
store *sessions.CookieStore
|
||||||
)
|
)
|
||||||
|
|
||||||
// startWebServer with the port provided
|
// startWebServer
|
||||||
func startWebServer(port string, ci string, cs string, redirectURL string) {
|
func startWebServer(port string, ci string, cs string, redirectURL string) {
|
||||||
|
tmpls["home.html"] = template.Must(template.ParseFiles(templateDir+"home.html", defaultLayout))
|
||||||
|
store = sessions.NewCookieStore([]byte(cs))
|
||||||
discordOauthConfig.ClientID = ci
|
discordOauthConfig.ClientID = ci
|
||||||
discordOauthConfig.ClientSecret = cs
|
discordOauthConfig.ClientSecret = cs
|
||||||
discordOauthConfig.RedirectURL = redirectURL + "/discordCallback"
|
discordOauthConfig.RedirectURL = redirectURL + "/discordCallback"
|
||||||
http.HandleFunc("/", handleMain)
|
|
||||||
http.HandleFunc("/discordLogin", handlediscordLogin)
|
r := mux.NewRouter()
|
||||||
http.HandleFunc("/discordCallback", handlediscordCallback)
|
r.HandleFunc("/", handleMain)
|
||||||
fmt.Println(http.ListenAndServe(":"+port, nil))
|
r.HandleFunc("/logout", handleLogout)
|
||||||
|
r.HandleFunc("/discordLogin", handlediscordLogin)
|
||||||
|
r.HandleFunc("/discordCallback", handlediscordCallback)
|
||||||
|
|
||||||
|
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
|
||||||
|
http.Handle("/", r)
|
||||||
|
http.ListenAndServe(":"+port, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMain(w http.ResponseWriter, r *http.Request) {
|
func handleMain(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Fprintf(w, htmlIndex)
|
session, _ := store.Get(r, "session-name")
|
||||||
|
if session.Values["discordUsername"] != nil {
|
||||||
|
fmt.Fprintf(w, "<html><body>you are logged in as %s. <a href=\"/logout\">logout</a></body></html>", session.Values["discordUsername"])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tmpls["home.html"].ExecuteTemplate(w, "base", map[string]interface{}{})
|
||||||
|
}
|
||||||
|
func handleLogout(w http.ResponseWriter, r *http.Request) {
|
||||||
|
cookie := &http.Cookie{
|
||||||
|
Name: "session-name",
|
||||||
|
Value: "",
|
||||||
|
Path: "/",
|
||||||
|
MaxAge: -1,
|
||||||
|
}
|
||||||
|
http.SetCookie(w, cookie)
|
||||||
|
http.Redirect(w, r, "/", http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handlediscordLogin(w http.ResponseWriter, r *http.Request) {
|
func handlediscordLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
|
b := make([]byte, 16)
|
||||||
|
rand.Read(b)
|
||||||
|
oauthStateString = base64.URLEncoding.EncodeToString(b)
|
||||||
|
|
||||||
|
session, _ := store.Get(r, "session-name")
|
||||||
|
session.Values["state"] = oauthStateString
|
||||||
|
session.Save(r, w)
|
||||||
|
|
||||||
url := discordOauthConfig.AuthCodeURL(oauthStateString)
|
url := discordOauthConfig.AuthCodeURL(oauthStateString)
|
||||||
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
|
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handlediscordCallback(w http.ResponseWriter, r *http.Request) {
|
func handlediscordCallback(w http.ResponseWriter, r *http.Request) {
|
||||||
|
session, err := store.Get(r, "session-name")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(w, "aborted")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r.URL.Query().Get("state") != session.Values["state"] {
|
||||||
|
fmt.Fprintln(w, "no state match; possible csrf OR cookies not enabled")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
state := r.FormValue("state")
|
state := r.FormValue("state")
|
||||||
if state != oauthStateString {
|
if state != oauthStateString {
|
||||||
fmt.Printf("invalid oauth state, expected '%s', got '%s'\n", oauthStateString, state)
|
fmt.Printf("invalid oauth state, expected '%s', got '%s'\n", oauthStateString, state)
|
||||||
@@ -60,11 +105,14 @@ func handlediscordCallback(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
code := r.FormValue("code")
|
token, err := discordOauthConfig.Exchange(oauth2.NoContext, r.FormValue("code"))
|
||||||
token, err := discordOauthConfig.Exchange(oauth2.NoContext, code)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Code exchange failed with ", err)
|
fmt.Fprintln(w, "Code exchange (could not get token) failed with ", err)
|
||||||
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !token.Valid() {
|
||||||
|
fmt.Fprintln(w, "retrieved invalid token")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,5 +122,11 @@ func handlediscordCallback(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
user, _ := dg.User("@me")
|
user, _ := dg.User("@me")
|
||||||
fmt.Fprintf(w, user.Username)
|
|
||||||
|
session.Values["discordUserID"] = user.ID
|
||||||
|
session.Values["discordUsername"] = user.Username
|
||||||
|
session.Values["accessToken"] = token.AccessToken
|
||||||
|
session.Save(r, w)
|
||||||
|
|
||||||
|
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user