latest
This commit is contained in:
parent
9c871edc17
commit
4822ba54a3
1
app/database/database.go
Normal file
1
app/database/database.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package database
|
67
app/http/endpoints/callback.go
Normal file
67
app/http/endpoints/callback.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package endpoints
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TicketsBot/GoPanel/utils/discord"
|
||||||
|
"github.com/TicketsBot/GoPanel/utils/discord/endpoints/user"
|
||||||
|
"github.com/TicketsBot/GoPanel/utils/discord/objects"
|
||||||
|
"github.com/gin-gonic/contrib/sessions"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type(
|
||||||
|
TokenData struct {
|
||||||
|
ClientId string `qs:"client_id"`
|
||||||
|
ClientSecret string `qs:"client_secret"`
|
||||||
|
GrantType string `qs:"grant_type"`
|
||||||
|
Code string `qs:"code"`
|
||||||
|
RedirectUri string `qs:"redirect_uri"`
|
||||||
|
Scope string `qs:"scope"`
|
||||||
|
}
|
||||||
|
|
||||||
|
TokenResponse struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
TokenType string `json:"token_type"`
|
||||||
|
ExpiresIn int `json:"expires_in"`
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
Scope string `json:"scope"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func CallbackHandler(ctx *gin.Context) {
|
||||||
|
store := sessions.Default(ctx)
|
||||||
|
if store == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer store.Save()
|
||||||
|
|
||||||
|
code := ctx.DefaultQuery("code", "")
|
||||||
|
if code == "" {
|
||||||
|
ctx.String(400, "Discord provided an invalid Oauth2 code")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := discord.AccessToken(code); if err != nil {
|
||||||
|
ctx.String(500, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
store.Set("access_token", res.AccessToken)
|
||||||
|
store.Set("refresh_token", res.RefreshToken)
|
||||||
|
store.Set("expiry", (time.Now().UnixNano() / int64(time.Second)) + int64(res.ExpiresIn))
|
||||||
|
|
||||||
|
// Get ID + name
|
||||||
|
var currentUser objects.User
|
||||||
|
err = user.CurrentUser.Request(store, nil, nil, ¤tUser); if err != nil {
|
||||||
|
ctx.String(500, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
store.Set("userid", currentUser.Id)
|
||||||
|
store.Set("name", currentUser.Username)
|
||||||
|
|
||||||
|
// Get Guilds
|
||||||
|
var currentUserGuilds []objects.Guild
|
||||||
|
err = user.CurrentUserGuilds.Request(store, nil, nil, ¤tUserGuilds); if err != nil {
|
||||||
|
ctx.String(500, err.Error())
|
||||||
|
}
|
||||||
|
}
|
22
app/http/endpoints/index.go
Normal file
22
app/http/endpoints/index.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package endpoints
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TicketsBot/GoPanel/utils"
|
||||||
|
"github.com/gin-gonic/contrib/sessions"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func IndexHandler(ctx *gin.Context) {
|
||||||
|
store := sessions.Default(ctx)
|
||||||
|
if store == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer store.Save()
|
||||||
|
|
||||||
|
if utils.IsLoggedIn(store) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ctx.Redirect(302, "/login")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
20
app/http/endpoints/login.go
Normal file
20
app/http/endpoints/login.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package endpoints
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/TicketsBot/GoPanel/config"
|
||||||
|
"github.com/gin-gonic/contrib/sessions"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoginHandler(ctx *gin.Context) {
|
||||||
|
store := sessions.Default(ctx)
|
||||||
|
if store == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer store.Save()
|
||||||
|
|
||||||
|
redirect := url.QueryEscape(fmt.Sprintf("%s/callback", config.Conf.Server.BaseUrl))
|
||||||
|
ctx.Redirect(302, fmt.Sprintf("https://discordapp.com/oauth2/authorize?response_type=code&redirect_uri=%s&scope=identify+guilds&client_id=%d", redirect, config.Conf.Oauth.Id))
|
||||||
|
}
|
25
app/http/layouts.go
Normal file
25
app/http/layouts.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TicketsBot/GoPanel/app/http/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Layout string
|
||||||
|
|
||||||
|
const(
|
||||||
|
Main Layout = "main"
|
||||||
|
)
|
||||||
|
|
||||||
|
var(
|
||||||
|
layouts = map[string]template.Layout{
|
||||||
|
Main.ToString(): template.LoadLayout(Main.ToString()),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (l Layout) ToString() string {
|
||||||
|
return string(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l Layout) GetInstance() template.Layout {
|
||||||
|
return layouts[l.ToString()]
|
||||||
|
}
|
50
app/http/server.go
Normal file
50
app/http/server.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/TicketsBot/GoPanel/app/http/endpoints"
|
||||||
|
"github.com/TicketsBot/GoPanel/config"
|
||||||
|
"github.com/gin-contrib/static"
|
||||||
|
"github.com/gin-gonic/contrib/sessions"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StartServer() {
|
||||||
|
log.Println("Starting HTTP server")
|
||||||
|
|
||||||
|
router := gin.Default()
|
||||||
|
|
||||||
|
// Sessions
|
||||||
|
store, err := sessions.NewRedisStore(
|
||||||
|
config.Conf.Server.Session.Threads,
|
||||||
|
"tcp", fmt.Sprintf("%s:%d", config.Conf.Redis.Host, config.Conf.Redis.Port),
|
||||||
|
config.Conf.Redis.Password,
|
||||||
|
[]byte(config.Conf.Server.Session.Secret))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
router.Use(sessions.Sessions("panel", store))
|
||||||
|
|
||||||
|
// Handle static asset requests
|
||||||
|
router.Use(static.Serve("/assets/", static.LocalFile("./public/static", false)))
|
||||||
|
|
||||||
|
// Root
|
||||||
|
router.GET("/", func(c *gin.Context) {
|
||||||
|
endpoints.IndexHandler(c)
|
||||||
|
})
|
||||||
|
|
||||||
|
// /login
|
||||||
|
router.GET("/login", func(c *gin.Context) {
|
||||||
|
endpoints.LoginHandler(c)
|
||||||
|
})
|
||||||
|
|
||||||
|
// /callback
|
||||||
|
router.GET("/callback", func(c *gin.Context) {
|
||||||
|
endpoints.CallbackHandler(c)
|
||||||
|
})
|
||||||
|
|
||||||
|
if err := router.Run(config.Conf.Server.Host); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
22
app/http/template/layout.go
Normal file
22
app/http/template/layout.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/TicketsBot/GoPanel/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Layout struct {
|
||||||
|
Name string
|
||||||
|
Content string
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadLayout(name string) Layout {
|
||||||
|
content, err := utils.ReadFile(fmt.Sprintf("./public/templates/layouts/%s.mustache", name)); if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Layout{
|
||||||
|
Name: name,
|
||||||
|
Content: content,
|
||||||
|
}
|
||||||
|
}
|
27
app/http/template/template.go
Normal file
27
app/http/template/template.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package template
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/TicketsBot/GoPanel/utils"
|
||||||
|
"github.com/hoisie/mustache"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Template struct {
|
||||||
|
Layout Layout
|
||||||
|
Content string
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadTemplate(layout Layout, name string) Template {
|
||||||
|
content, err := utils.ReadFile(fmt.Sprintf("./public/templates/views/%s.mustache", name)); if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Template{
|
||||||
|
Layout: layout,
|
||||||
|
Content: content,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Template) Render(context ...interface{}) string {
|
||||||
|
return mustache.RenderInLayout(t.Content, t.Layout.Content, context)
|
||||||
|
}
|
28
app/http/templates.go
Normal file
28
app/http/templates.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import "github.com/TicketsBot/GoPanel/app/http/template"
|
||||||
|
|
||||||
|
type Template string
|
||||||
|
|
||||||
|
const(
|
||||||
|
Index Template = "index"
|
||||||
|
)
|
||||||
|
|
||||||
|
var(
|
||||||
|
templates = map[string]template.Template{
|
||||||
|
Index.ToString(): template.LoadTemplate(Main.GetInstance(), Index.ToString()),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t Template) ToString() string {
|
||||||
|
return string(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Template) GetInstance() template.Template {
|
||||||
|
return templates[t.ToString()]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Template) Render(context ...interface{}) string {
|
||||||
|
temp := t.GetInstance()
|
||||||
|
return temp.Render(context)
|
||||||
|
}
|
@ -1,7 +1,17 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/TicketsBot/PanelV2/config"
|
import (
|
||||||
|
"github.com/TicketsBot/GoPanel/app/http"
|
||||||
|
"github.com/TicketsBot/GoPanel/config"
|
||||||
|
"github.com/TicketsBot/GoPanel/database"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
rand.Seed(time.Now().UnixNano() % 3497)
|
||||||
|
|
||||||
config.LoadConfig()
|
config.LoadConfig()
|
||||||
|
database.ConnectToDatabase()
|
||||||
|
http.StartServer()
|
||||||
}
|
}
|
||||||
|
@ -6,22 +6,22 @@ mainSite="https://ticketsbot.net"
|
|||||||
window=10
|
window=10
|
||||||
max=600
|
max=600
|
||||||
[server.session]
|
[server.session]
|
||||||
database="session"
|
threads=10
|
||||||
|
secret="secret"
|
||||||
|
|
||||||
[oauth]
|
[oauth]
|
||||||
id=1
|
id=
|
||||||
secret="secret"
|
secret=""
|
||||||
|
redirectUri=""
|
||||||
|
|
||||||
[mariadb]
|
[mariadb]
|
||||||
host="127.0.0.1"
|
host="127.0.0.1"
|
||||||
username="root"
|
username="ryan"
|
||||||
password="root"
|
password="ryan"
|
||||||
database="tickets"
|
database="tickets"
|
||||||
threads=5
|
threads=5
|
||||||
|
|
||||||
[bot]
|
|
||||||
key=""
|
|
||||||
httpServers=[]
|
|
||||||
|
|
||||||
[redis]
|
[redis]
|
||||||
uri="redis://:pwd@127.0.0.1:6379/0"
|
host="127.0.0.1"
|
||||||
|
port=6379
|
||||||
|
password=""
|
||||||
|
@ -9,6 +9,7 @@ type(
|
|||||||
Config struct {
|
Config struct {
|
||||||
Server Server
|
Server Server
|
||||||
Oauth Oauth
|
Oauth Oauth
|
||||||
|
MariaDB MariaDB
|
||||||
Bot Bot
|
Bot Bot
|
||||||
Redis Redis
|
Redis Redis
|
||||||
}
|
}
|
||||||
@ -27,12 +28,14 @@ type(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Session struct {
|
Session struct {
|
||||||
Database string
|
Threads int
|
||||||
|
Secret string
|
||||||
}
|
}
|
||||||
|
|
||||||
Oauth struct {
|
Oauth struct {
|
||||||
Id int64
|
Id int64
|
||||||
Secret string
|
Secret string
|
||||||
|
RedirectUri string
|
||||||
}
|
}
|
||||||
|
|
||||||
MariaDB struct {
|
MariaDB struct {
|
||||||
@ -49,7 +52,9 @@ type(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Redis struct {
|
Redis struct {
|
||||||
Uri string
|
Host string
|
||||||
|
Port int
|
||||||
|
Password string
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
31
database/database.go
Normal file
31
database/database.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/TicketsBot/GoPanel/config"
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/jinzhu/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
var(
|
||||||
|
database **gorm.DB
|
||||||
|
)
|
||||||
|
|
||||||
|
func ConnectToDatabase() {
|
||||||
|
uri := fmt.Sprintf(
|
||||||
|
"%s:%s@tcp(%s:3306)/%s?charset=utf8mb4&parseTime=True&loc=Local",
|
||||||
|
config.Conf.MariaDB.Username,
|
||||||
|
config.Conf.MariaDB.Password,
|
||||||
|
config.Conf.MariaDB.Host,
|
||||||
|
config.Conf.MariaDB.Database,
|
||||||
|
)
|
||||||
|
|
||||||
|
db, err := gorm.Open("mysql", uri); if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
db.DB().SetMaxOpenConns(config.Conf.MariaDB.Threads)
|
||||||
|
db.DB().SetMaxIdleConns(0)
|
||||||
|
|
||||||
|
database = &db
|
||||||
|
}
|
@ -1,18 +0,0 @@
|
|||||||
package http
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/TicketsBot/PanelV2/config"
|
|
||||||
"github.com/qiangxue/fasthttp-routing"
|
|
||||||
"github.com/valyala/fasthttp"
|
|
||||||
"log"
|
|
||||||
)
|
|
||||||
|
|
||||||
func StartServer() {
|
|
||||||
log.Println("Starting HTTP server")
|
|
||||||
|
|
||||||
router := routing.New()
|
|
||||||
|
|
||||||
err := fasthttp.ListenAndServe(config.Conf.Server.Host, router.HandleRequest); if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
42
public/templates/layouts/main.mustache
Normal file
42
public/templates/layouts/main.mustache
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Tickets | A Discord Support Manager Bot</title>
|
||||||
|
|
||||||
|
<!-- Meta -->
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="Management panel for the Discord Tickets bot">
|
||||||
|
|
||||||
|
<!-- Custom CSS -->
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: 'Open Sans',sans-serif;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- Materialize -->
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
|
||||||
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav>
|
||||||
|
<div class="nav-wrapper grey darken-4">
|
||||||
|
<ul id="nav-mobile" class="left hide-on-med-and-down">
|
||||||
|
<li><a href="{{mainsite}}">Main Site</a></li>
|
||||||
|
<li><a href="/">Servers</a></li>
|
||||||
|
</ul>
|
||||||
|
<ul id="nav-mobile" class="right hide-on-med-and-down">
|
||||||
|
<li><a href="/logout">Logout</a></li>
|
||||||
|
<li><a href="#">Hi, {{name}}</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
{{{body}}}
|
||||||
|
</body>
|
||||||
|
</html>
|
23
public/templates/views/index.mustache
Normal file
23
public/templates/views/index.mustache
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s12">
|
||||||
|
{{#if isNotAdmin}}
|
||||||
|
<p class="center-align" style="padding-top: 50px; font-size: 16px">
|
||||||
|
You are not the admin of any guilds that the bot is in. Click below to invite the bot:
|
||||||
|
<br />
|
||||||
|
<a href="https://invite.ticketsbot.net">Invite</a>
|
||||||
|
</p>
|
||||||
|
{{else}}
|
||||||
|
<p class="center-align" style="padding-top: 50px; font-size: 16px">
|
||||||
|
Select a server to manage below
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul class="collection">
|
||||||
|
{{#each guilds}}
|
||||||
|
<li class="collection-item"><a href="{{baseUrl}}/manage/{{id}}/settings">{{name}}</a></li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
93
public/templates/views/logs.mustache
Normal file
93
public/templates/views/logs.mustache
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s12">
|
||||||
|
<ul class="pagination center-align" style="padding-top: 50px">
|
||||||
|
<li class="waves-effect"><a href="#"><i class="material-icons">chevron_left</i></a></li>
|
||||||
|
<li class="waves-effect"><a href="/manage/{{guildId}}/settings">Settings</a></li>
|
||||||
|
<li class="active indigo darken-1"><a href="#">Logs</a></li>
|
||||||
|
<li class="disabled"><a href="#"><i class="material-icons">chevron_right</i></a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<ul class="collapsible">
|
||||||
|
<li>
|
||||||
|
<div class="collapsible-header"><i class="material-icons">search</i>Filter Logs</div>
|
||||||
|
<div class="collapsible-body">
|
||||||
|
<div class="container" style="width: 100%">
|
||||||
|
<div class="row">
|
||||||
|
<form class="col s12" action="/manage/{{guildId}}/logs/page/1" method="get">
|
||||||
|
<div class="row">
|
||||||
|
<div class="input-field col s6">
|
||||||
|
<input placeholder="Ticket ID" name="ticketid" id="ticketid" type="text" class="validate">
|
||||||
|
<label for="ticketid">Ticket ID</label>
|
||||||
|
</div>
|
||||||
|
<div class="input-field col s6">
|
||||||
|
<input placeholder="Username" name="username" id="username" type="text" class="validate">
|
||||||
|
<label for="username">Username</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row center-align">
|
||||||
|
<div class="input-field col s6 center-align">
|
||||||
|
<input placeholder="User ID" name="userid" id="userid" type="text" class="validate">
|
||||||
|
<label for="userid">User ID</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row center-align">
|
||||||
|
<button class="btn waves-effect waves-light center-align indigo darken-1" type="submit" name="action">Search
|
||||||
|
<i class="material-icons right">search</i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s12">
|
||||||
|
<table class="striped centered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Ticket ID</th>
|
||||||
|
<th>User</th>
|
||||||
|
<th>User ID</th>
|
||||||
|
<th>Log URL</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{#each logs}}
|
||||||
|
{{{baseUrl}}}
|
||||||
|
<tr>
|
||||||
|
<td>{{TICKETID}}</td>
|
||||||
|
<td>{{USERNAME}}</td>
|
||||||
|
<td>{{USERID}}</td>
|
||||||
|
<td><a href="{{baseUrl}}/logs/{{UUID}}">{{UUID}}</a></td>
|
||||||
|
</tr>
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row center-align">
|
||||||
|
<div class="col s12 center-align">
|
||||||
|
<p class="center-align">Pages</p>
|
||||||
|
<ul class="pagination center-align">
|
||||||
|
{{#if isPageOne}}
|
||||||
|
<li class="disabled"><a href="#"><i class="material-icons">chevron_left</i></a></li>
|
||||||
|
{{else}}
|
||||||
|
<li class="waves-effect"><a href="/manage/{{guildId}}/logs/page/{{previousPage}}"><i class="material-icons">chevron_left</i></a></li>
|
||||||
|
{{/if}}
|
||||||
|
<li class="waves-effect"><a href="/manage/{{guildId}}/logs/page/{{nextPage}}"><i class="material-icons">chevron_right</i></a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
M.AutoInit();
|
||||||
|
</script>
|
84
public/templates/views/settings.mustache
Normal file
84
public/templates/views/settings.mustache
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<script>
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
var elems = document.querySelectorAll('select');
|
||||||
|
var instances = M.FormSelect.init(elems, {});
|
||||||
|
});
|
||||||
|
|
||||||
|
{{#if invalidPrefix}}
|
||||||
|
M.toast({html: 'Prefixes must be between 1 and 8 characters'})
|
||||||
|
{{/if}}
|
||||||
|
{{#if invalidMessage}}
|
||||||
|
M.toast({html: 'Welcome messages must be between 1 and 1000 characters'})
|
||||||
|
{{/if}}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s12">
|
||||||
|
<ul class="pagination center-align" style="padding-top: 50px">
|
||||||
|
<li class="disabled"><a href="#!"><i class="material-icons">chevron_left</i></a></li>
|
||||||
|
<li class="active indigo darken-1"><a href="#!">Settings</a></li>
|
||||||
|
<li class="waves-effect"><a href="/manage/{{guildId}}/logs/page/1">Logs</a></li>
|
||||||
|
<li class="waves-effect"><a href="/manage/{{guildId}}/logs/page/1"><i class="material-icons">chevron_right</i></a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<form class="col s12" action="/manage/{{guildId}}/settings" method="get">
|
||||||
|
<div class="row">
|
||||||
|
<div class="input-field col s12">
|
||||||
|
<p><b>Prefix</b></p>
|
||||||
|
<input id="prefix" name="prefix" type="text" class="validate" value="{{prefix}}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="input-field col s12">
|
||||||
|
<p><b>Welcome Message</b></p>
|
||||||
|
<textarea id="welcomeMessage" name="welcomeMessage" class="materialize-textarea">{{welcomeMessage}}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="input-field col s12">
|
||||||
|
<p><b>Ticket Limit</b></p>
|
||||||
|
<p class="range-field">
|
||||||
|
<input type="range" id="ticketlimit" name="ticketlimit" min="1" max="10" value="{{ticketLimit}}" />
|
||||||
|
</p>
|
||||||
|
<p id="output">Limit: -1</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="input-field col s12">
|
||||||
|
<p><b>Channel Category</b></p>
|
||||||
|
<select name="category">
|
||||||
|
{{#each categories}}
|
||||||
|
{{#if active}}
|
||||||
|
<option value="{{id}}" selected>{{name}}</option>
|
||||||
|
{{else}}
|
||||||
|
<option value="{{id}}">{{name}}</option>
|
||||||
|
{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s12 center-align">
|
||||||
|
<button class="btn waves-effect waves-light indigo darken-1" type="submit" name="action">Save
|
||||||
|
<i class="material-icons right">send</i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var slider = document.getElementById("ticketlimit");
|
||||||
|
var output = document.getElementById("output");
|
||||||
|
output.innerHTML = "Limit: " + slider.value;
|
||||||
|
slider.oninput = () => {
|
||||||
|
output.innerHTML = "Limit: " + slider.value;
|
||||||
|
}
|
||||||
|
</script>
|
113
utils/discord/auth.go
Normal file
113
utils/discord/auth.go
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
package discord
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/TicketsBot/GoPanel/config"
|
||||||
|
"github.com/pasztorpisti/qs"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type(
|
||||||
|
TokenData struct {
|
||||||
|
ClientId string `qs:"client_id"`
|
||||||
|
ClientSecret string `qs:"client_secret"`
|
||||||
|
GrantType string `qs:"grant_type"`
|
||||||
|
Code string `qs:"code"`
|
||||||
|
RedirectUri string `qs:"redirect_uri"`
|
||||||
|
Scope string `qs:"scope"`
|
||||||
|
}
|
||||||
|
|
||||||
|
RefreshData struct {
|
||||||
|
ClientId string `qs:"client_id"`
|
||||||
|
ClientSecret string `qs:"client_secret"`
|
||||||
|
GrantType string `qs:"grant_type"`
|
||||||
|
RefreshToken string `qs:"refresh_token"`
|
||||||
|
RedirectUri string `qs:"redirect_uri"`
|
||||||
|
Scope string `qs:"scope"`
|
||||||
|
}
|
||||||
|
|
||||||
|
TokenResponse struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
TokenType string `json:"token_type"`
|
||||||
|
ExpiresIn int `json:"expires_in"`
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
Scope string `json:"scope"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const TokenEndpoint = "https://discordapp.com/api/oauth2/token"
|
||||||
|
|
||||||
|
func AccessToken(code string) (TokenResponse, error) {
|
||||||
|
data := TokenData{
|
||||||
|
ClientId: strconv.Itoa(int(config.Conf.Oauth.Id)),
|
||||||
|
ClientSecret: config.Conf.Oauth.Secret,
|
||||||
|
GrantType: "authorization_code",
|
||||||
|
Code: code,
|
||||||
|
RedirectUri: config.Conf.Oauth.RedirectUri,
|
||||||
|
Scope: "identify guilds",
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := tokenPost(data); if err != nil {
|
||||||
|
return TokenResponse{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var unmarshalled TokenResponse
|
||||||
|
if err = json.Unmarshal(res, &unmarshalled); err != nil {
|
||||||
|
return TokenResponse{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return unmarshalled, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RefreshToken(refreshToken string) (TokenResponse, error) {
|
||||||
|
data := RefreshData{
|
||||||
|
ClientId: strconv.Itoa(int(config.Conf.Oauth.Id)),
|
||||||
|
ClientSecret: config.Conf.Oauth.Secret,
|
||||||
|
GrantType: "refresh_token",
|
||||||
|
RefreshToken: refreshToken,
|
||||||
|
RedirectUri: config.Conf.Oauth.RedirectUri,
|
||||||
|
Scope: "identify guilds",
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := tokenPost(data); if err != nil {
|
||||||
|
return TokenResponse{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var unmarshalled TokenResponse
|
||||||
|
if err = json.Unmarshal(res, &unmarshalled); err != nil {
|
||||||
|
return TokenResponse{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return unmarshalled, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func tokenPost(body ...interface{}) ([]byte, error) {
|
||||||
|
str, err := qs.Marshal(body[0]); if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
encoded := []byte(str)
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", TokenEndpoint, bytes.NewBuffer([]byte(encoded))); if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", string(ApplicationFormUrlEncoded))
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
client.Timeout = 3 * time.Second
|
||||||
|
|
||||||
|
res, err := client.Do(req); if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
content, err := ioutil.ReadAll(res.Body); if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return content, nil
|
||||||
|
}
|
104
utils/discord/endpoints.go
Normal file
104
utils/discord/endpoints.go
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
package discord
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/gin-gonic/contrib/sessions"
|
||||||
|
"github.com/pasztorpisti/qs"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RequestType string
|
||||||
|
type ContentType string
|
||||||
|
|
||||||
|
const(
|
||||||
|
GET RequestType = "GET"
|
||||||
|
POST RequestType = "POST"
|
||||||
|
PATCH RequestType = "PATCH"
|
||||||
|
|
||||||
|
ApplicationJson ContentType = "application/json"
|
||||||
|
ApplicationFormUrlEncoded ContentType = "application/x-www-form-urlencoded"
|
||||||
|
|
||||||
|
BASE_URL = "https://discordapp.com/api/v6"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Endpoint struct {
|
||||||
|
RequestType RequestType
|
||||||
|
Endpoint string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Endpoint) Request(store sessions.Session, contentType *ContentType, body interface{}, response interface{}) error {
|
||||||
|
url := BASE_URL + e.Endpoint
|
||||||
|
|
||||||
|
// Create req
|
||||||
|
var req *http.Request
|
||||||
|
var err error
|
||||||
|
if body == nil || contentType == nil {
|
||||||
|
req, err = http.NewRequest(string(e.RequestType), url, nil)
|
||||||
|
} else {
|
||||||
|
// Encode body
|
||||||
|
var encoded []byte
|
||||||
|
if *contentType == ApplicationJson {
|
||||||
|
raw, err := json.Marshal(body); if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
encoded = raw
|
||||||
|
} else if *contentType == ApplicationFormUrlEncoded {
|
||||||
|
str, err := qs.Marshal(body); if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
encoded = []byte(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create req
|
||||||
|
req, err = http.NewRequest(string(e.RequestType), url, bytes.NewBuffer(encoded))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set content type and user agent
|
||||||
|
if contentType != nil {
|
||||||
|
req.Header.Set("Content-Type", string(*contentType))
|
||||||
|
}
|
||||||
|
req.Header.Set("User-Agent", "DiscordBot (https://github.com/TicketsBot/GoPanel 1.0.0)")
|
||||||
|
|
||||||
|
// Auth
|
||||||
|
accessToken := store.Get("access_token").(string)
|
||||||
|
expiry := store.Get("expiry").(int64)
|
||||||
|
refreshToken := store.Get("refresh_token").(string)
|
||||||
|
|
||||||
|
// Check if needs refresh
|
||||||
|
if (time.Now().UnixNano() / int64(time.Second)) > int64(expiry) {
|
||||||
|
res, err := RefreshToken(refreshToken); if err != nil {
|
||||||
|
store.Clear()
|
||||||
|
_ = store.Save()
|
||||||
|
return errors.New("Please login again!")
|
||||||
|
}
|
||||||
|
|
||||||
|
store.Set("access_token", res.AccessToken)
|
||||||
|
store.Set("expiry", (time.Now().UnixNano() / int64(time.Second)) + int64(res.ExpiresIn))
|
||||||
|
store.Set("refresh_token", res.RefreshToken)
|
||||||
|
|
||||||
|
accessToken = res.AccessToken
|
||||||
|
}
|
||||||
|
req.Header.Set("Authorization", "Bearer " + accessToken)
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
client.Timeout = 3 * time.Second
|
||||||
|
|
||||||
|
res, err := client.Do(req); if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
content, err := ioutil.ReadAll(res.Body); if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Unmarshal(content, response)
|
||||||
|
}
|
13
utils/discord/endpoints/guild/getGuild.go
Normal file
13
utils/discord/endpoints/guild/getGuild.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package guild
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/TicketsBot/GoPanel/utils/discord"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetGuild(id int) discord.Endpoint {
|
||||||
|
return discord.Endpoint{
|
||||||
|
RequestType: discord.GET,
|
||||||
|
Endpoint: fmt.Sprintf("/guilds/%d", id),
|
||||||
|
}
|
||||||
|
}
|
8
utils/discord/endpoints/user/currentUser.go
Normal file
8
utils/discord/endpoints/user/currentUser.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import "github.com/TicketsBot/GoPanel/utils/discord"
|
||||||
|
|
||||||
|
var CurrentUser = discord.Endpoint{
|
||||||
|
RequestType: discord.GET,
|
||||||
|
Endpoint: "/users/@me",
|
||||||
|
}
|
8
utils/discord/endpoints/user/currentUserGuilds.go
Normal file
8
utils/discord/endpoints/user/currentUserGuilds.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import "github.com/TicketsBot/GoPanel/utils/discord"
|
||||||
|
|
||||||
|
var CurrentUserGuilds = discord.Endpoint{
|
||||||
|
RequestType: discord.GET,
|
||||||
|
Endpoint: "/users/@me/guilds",
|
||||||
|
}
|
16
utils/discord/objects/activity.go
Normal file
16
utils/discord/objects/activity.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package objects
|
||||||
|
|
||||||
|
type Activity struct {
|
||||||
|
Name string
|
||||||
|
Type int
|
||||||
|
Url string
|
||||||
|
Timestamps Timestamp
|
||||||
|
ApplicationId string
|
||||||
|
Details string
|
||||||
|
State string
|
||||||
|
Party Party
|
||||||
|
Assets Asset
|
||||||
|
Secrets Secret
|
||||||
|
Instance bool
|
||||||
|
Flags int
|
||||||
|
}
|
8
utils/discord/objects/asset.go
Normal file
8
utils/discord/objects/asset.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package objects
|
||||||
|
|
||||||
|
type Asset struct {
|
||||||
|
LargeImage string
|
||||||
|
LargeText string
|
||||||
|
SmallImage string
|
||||||
|
SmallText string
|
||||||
|
}
|
22
utils/discord/objects/channel.go
Normal file
22
utils/discord/objects/channel.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package objects
|
||||||
|
|
||||||
|
type Channel struct {
|
||||||
|
Id string
|
||||||
|
Type int
|
||||||
|
GuildId string
|
||||||
|
Position int
|
||||||
|
PermissionsOverwrites []Overwrite
|
||||||
|
Name string
|
||||||
|
Topic string
|
||||||
|
Nsfw bool
|
||||||
|
LastMessageId string
|
||||||
|
Bitrate int
|
||||||
|
userLimit int
|
||||||
|
RateLimitPerUser int
|
||||||
|
Recipients []User
|
||||||
|
Icon string
|
||||||
|
Ownerid string
|
||||||
|
ApplicationId string
|
||||||
|
ParentId string
|
||||||
|
LastPinTimestamp string
|
||||||
|
}
|
7
utils/discord/objects/clientstatus.go
Normal file
7
utils/discord/objects/clientstatus.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package objects
|
||||||
|
|
||||||
|
type ClientStatus struct {
|
||||||
|
Desktop string
|
||||||
|
Mobile string
|
||||||
|
Web string
|
||||||
|
}
|
11
utils/discord/objects/emoji.go
Normal file
11
utils/discord/objects/emoji.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package objects
|
||||||
|
|
||||||
|
type Emoji struct {
|
||||||
|
Id string
|
||||||
|
Name string
|
||||||
|
Roles []string
|
||||||
|
User User
|
||||||
|
RequireColons bool
|
||||||
|
Managed bool
|
||||||
|
Animated bool
|
||||||
|
}
|
40
utils/discord/objects/guild.go
Normal file
40
utils/discord/objects/guild.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package objects
|
||||||
|
|
||||||
|
type Guild struct {
|
||||||
|
Id string
|
||||||
|
Name string
|
||||||
|
Icon string
|
||||||
|
Splash string
|
||||||
|
Owner bool
|
||||||
|
OwnerId string
|
||||||
|
Permissions int
|
||||||
|
Region string
|
||||||
|
AfkChannelid string
|
||||||
|
AfkTimeout int
|
||||||
|
EmbedEnabled bool
|
||||||
|
EmbedChannelId string
|
||||||
|
VerificationLevel int
|
||||||
|
DefaultMessageNotifications int
|
||||||
|
ExplicitContentFilter int
|
||||||
|
Roles []Role
|
||||||
|
Emojis []Emoji
|
||||||
|
Features []string
|
||||||
|
MfaLevel int
|
||||||
|
ApplicationId string
|
||||||
|
WidgetEnabled bool
|
||||||
|
WidgetChannelId string
|
||||||
|
SystemChannelId string
|
||||||
|
JoinedAt string
|
||||||
|
Large bool
|
||||||
|
Unavailable bool
|
||||||
|
MemberCount int
|
||||||
|
VoiceStates []VoiceState
|
||||||
|
Members []Member
|
||||||
|
Channels []Channel
|
||||||
|
Presences []Presence
|
||||||
|
MaxPresences int
|
||||||
|
Maxmembers int
|
||||||
|
VanityUrlCode string
|
||||||
|
Description string
|
||||||
|
Banner string
|
||||||
|
}
|
10
utils/discord/objects/member.go
Normal file
10
utils/discord/objects/member.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package objects
|
||||||
|
|
||||||
|
type Member struct {
|
||||||
|
User User
|
||||||
|
Nick string
|
||||||
|
Roles []string
|
||||||
|
JoinedAt string
|
||||||
|
Deaf bool
|
||||||
|
Mute bool
|
||||||
|
}
|
8
utils/discord/objects/overwrite.go
Normal file
8
utils/discord/objects/overwrite.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package objects
|
||||||
|
|
||||||
|
type Overwrite struct {
|
||||||
|
Id string
|
||||||
|
Type string
|
||||||
|
Allow int
|
||||||
|
Deny int
|
||||||
|
}
|
6
utils/discord/objects/party.go
Normal file
6
utils/discord/objects/party.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package objects
|
||||||
|
|
||||||
|
type Party struct {
|
||||||
|
Id string
|
||||||
|
Size []int
|
||||||
|
}
|
11
utils/discord/objects/presence.go
Normal file
11
utils/discord/objects/presence.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package objects
|
||||||
|
|
||||||
|
type Presence struct {
|
||||||
|
User User
|
||||||
|
Roles []string
|
||||||
|
Game Activity
|
||||||
|
GuildId string
|
||||||
|
Status string
|
||||||
|
Activities []Activity
|
||||||
|
ClientStatus ClientStatus
|
||||||
|
}
|
12
utils/discord/objects/role.go
Normal file
12
utils/discord/objects/role.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package objects
|
||||||
|
|
||||||
|
type Role struct {
|
||||||
|
Id string
|
||||||
|
Name string
|
||||||
|
Color int
|
||||||
|
Hoist bool
|
||||||
|
Position int
|
||||||
|
Permissions int
|
||||||
|
Managed bool
|
||||||
|
Mentionable bool
|
||||||
|
}
|
7
utils/discord/objects/secret.go
Normal file
7
utils/discord/objects/secret.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package objects
|
||||||
|
|
||||||
|
type Secret struct {
|
||||||
|
Join string
|
||||||
|
Spectate string
|
||||||
|
Match string
|
||||||
|
}
|
6
utils/discord/objects/timestamp.go
Normal file
6
utils/discord/objects/timestamp.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package objects
|
||||||
|
|
||||||
|
type Timestamp struct {
|
||||||
|
Start int
|
||||||
|
End int
|
||||||
|
}
|
12
utils/discord/objects/user.go
Normal file
12
utils/discord/objects/user.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package objects
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Id string
|
||||||
|
Username string
|
||||||
|
Discriminator string
|
||||||
|
Avatar string
|
||||||
|
Verified bool
|
||||||
|
Email string
|
||||||
|
Flags int
|
||||||
|
PremiumType int
|
||||||
|
}
|
14
utils/discord/objects/voicestate.go
Normal file
14
utils/discord/objects/voicestate.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package objects
|
||||||
|
|
||||||
|
type VoiceState struct {
|
||||||
|
GuildId string
|
||||||
|
ChannelId string
|
||||||
|
UserId string
|
||||||
|
Member Member
|
||||||
|
SessionId string
|
||||||
|
Deaf bool
|
||||||
|
Mute bool
|
||||||
|
SelfDeaf bool
|
||||||
|
SelfMute bool
|
||||||
|
Suppress bool
|
||||||
|
}
|
11
utils/fileutils.go
Normal file
11
utils/fileutils.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import "io/ioutil"
|
||||||
|
|
||||||
|
func ReadFile(path string) (string, error) {
|
||||||
|
content, err := ioutil.ReadFile(path); if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(content), nil
|
||||||
|
}
|
9
utils/sessionutils.go
Normal file
9
utils/sessionutils.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/contrib/sessions"
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsLoggedIn(store sessions.Session) bool {
|
||||||
|
return store.Get("access_token") != nil && store.Get("expiry") != nil && store.Get("refresh_token") != nil && store.Get("userid") != nil && store.Get("name") != nil
|
||||||
|
}
|
13
utils/stringutils.go
Normal file
13
utils/stringutils.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import "math/rand"
|
||||||
|
|
||||||
|
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||||
|
|
||||||
|
func RandStringRunes(length int) string {
|
||||||
|
b := make([]rune, length)
|
||||||
|
for i := range b {
|
||||||
|
b[i] = letterRunes[rand.Intn(len(letterRunes))]
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user