Add refresh guilds button
This commit is contained in:
parent
52bd71eab4
commit
3a98761b77
74
app/http/endpoints/api/reloadguilds.go
Normal file
74
app/http/endpoints/api/reloadguilds.go
Normal file
@ -0,0 +1,74 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/TicketsBot/GoPanel/messagequeue"
|
||||
"github.com/TicketsBot/GoPanel/utils"
|
||||
"github.com/TicketsBot/GoPanel/utils/discord"
|
||||
"github.com/gin-gonic/contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ReloadGuildsHandler(ctx *gin.Context) {
|
||||
userId := ctx.Keys["userid"].(uint64)
|
||||
|
||||
key := fmt.Sprintf("tickets:dashboard:guildreload:%d", userId)
|
||||
res, err := messagequeue.Client.SetNX(key, 1, time.Second*10).Result()
|
||||
if err != nil {
|
||||
ctx.JSON(500, utils.ErrorToResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
if !res {
|
||||
ttl, err := messagequeue.Client.TTL(key).Result()
|
||||
if err != nil {
|
||||
ctx.JSON(500, utils.ErrorToResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
// handle redis error codes
|
||||
if ttl < 0 {
|
||||
ttl = 0
|
||||
}
|
||||
|
||||
ctx.JSON(429, utils.ErrorStr("You're doing this too quickly: try again in %d seconds", int(ttl.Seconds())))
|
||||
return
|
||||
}
|
||||
|
||||
store := sessions.Default(ctx)
|
||||
if store == nil {
|
||||
ctx.JSON(200, gin.H{
|
||||
"success": false,
|
||||
"reauthenticate_required": true,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
accessToken := store.Get("access_token").(string)
|
||||
expiry := store.Get("expiry").(int64)
|
||||
if expiry > (time.Now().UnixNano() / int64(time.Second)) {
|
||||
res, err := discord.RefreshToken(store.Get("refresh_token").(string))
|
||||
if err != nil { // Tell client to re-authenticate
|
||||
ctx.JSON(200, gin.H{
|
||||
"success": false,
|
||||
"reauthenticate_required": true,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
accessToken = res.AccessToken
|
||||
|
||||
store.Set("access_token", res.AccessToken)
|
||||
store.Set("refresh_token", res.RefreshToken)
|
||||
store.Set("expiry", (time.Now().UnixNano()/int64(time.Second))+int64(res.ExpiresIn))
|
||||
store.Save()
|
||||
}
|
||||
|
||||
if err := utils.LoadGuilds(accessToken, userId); err != nil {
|
||||
ctx.JSON(500, utils.ErrorToResponse(err))
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSON(200, utils.SuccessResponse)
|
||||
}
|
@ -3,16 +3,12 @@ package root
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/TicketsBot/GoPanel/config"
|
||||
dbclient "github.com/TicketsBot/GoPanel/database"
|
||||
"github.com/TicketsBot/GoPanel/utils"
|
||||
"github.com/TicketsBot/GoPanel/utils/discord"
|
||||
userEndpoint "github.com/TicketsBot/GoPanel/utils/discord/endpoints/user"
|
||||
"github.com/TicketsBot/database"
|
||||
"github.com/apex/log"
|
||||
"github.com/gin-gonic/contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/rxdn/gdl/objects/guild"
|
||||
"github.com/rxdn/gdl/objects/user"
|
||||
"github.com/rxdn/gdl/rest"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@ -65,8 +61,7 @@ func CallbackHandler(ctx *gin.Context) {
|
||||
store.Set("expiry", (time.Now().UnixNano()/int64(time.Second))+int64(res.ExpiresIn))
|
||||
|
||||
// Get ID + name
|
||||
var currentUser user.User
|
||||
err, _ = userEndpoint.CurrentUser.Request(store, nil, nil, ¤tUser)
|
||||
currentUser, err := rest.GetCurrentUser(fmt.Sprintf("Bearer %s", res.AccessToken), nil)
|
||||
if err != nil {
|
||||
ctx.String(500, err.Error())
|
||||
return
|
||||
@ -79,37 +74,10 @@ func CallbackHandler(ctx *gin.Context) {
|
||||
store.Set("avatar", currentUser.AvatarUrl(256))
|
||||
store.Save()
|
||||
|
||||
var guilds []guild.Guild
|
||||
err, _ = userEndpoint.CurrentUserGuilds.Request(store, nil, nil, &guilds)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
handleRedirect(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
if err := utils.LoadGuilds(res.AccessToken, currentUser.Id); err == nil {
|
||||
store.Set("has_guilds", true)
|
||||
store.Save()
|
||||
|
||||
var wrappedGuilds []database.UserGuild
|
||||
|
||||
// endpoint's partial guild doesn't include ownerid
|
||||
// we only user cached guilds on the index page, so it doesn't matter if we don't have have the real owner id
|
||||
// if the user isn't the owner, as we pull from the cache on other endpoints
|
||||
for _, guild := range guilds {
|
||||
if guild.Owner {
|
||||
guild.OwnerId = currentUser.Id
|
||||
}
|
||||
|
||||
wrappedGuilds = append(wrappedGuilds, database.UserGuild{
|
||||
GuildId: guild.Id,
|
||||
Name: guild.Name,
|
||||
Owner: guild.Owner,
|
||||
UserPermissions: int32(guild.Permissions),
|
||||
Icon: guild.Icon,
|
||||
})
|
||||
}
|
||||
|
||||
if err := dbclient.Client.UserGuilds.Set(currentUser.Id, wrappedGuilds); err != nil {
|
||||
} else {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
|
||||
|
@ -128,6 +128,7 @@ func StartServer() {
|
||||
userGroup := router.Group("/user", middleware.AuthenticateToken)
|
||||
{
|
||||
userGroup.GET("/guilds", api.GetGuilds)
|
||||
userGroup.POST("/guilds/reload", api.ReloadGuildsHandler)
|
||||
userGroup.GET("/permissionlevel", api.GetPermissionLevel)
|
||||
|
||||
{
|
||||
|
4
go.mod
4
go.mod
@ -15,14 +15,14 @@ require (
|
||||
github.com/gin-contrib/static v0.0.0-20191128031702-f81c604d8ac2
|
||||
github.com/gin-gonic/contrib v0.0.0-20191209060500-d6e26eeaa607
|
||||
github.com/gin-gonic/gin v1.6.2
|
||||
github.com/go-redis/redis v6.15.8+incompatible
|
||||
github.com/go-redis/redis v6.15.9+incompatible
|
||||
github.com/gofrs/uuid v3.3.0+incompatible
|
||||
github.com/gorilla/sessions v1.2.0 // indirect
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/jackc/pgx/v4 v4.7.1
|
||||
github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rxdn/gdl v0.0.0-20201214225805-4ae598a98327
|
||||
github.com/rxdn/gdl v0.0.0-20210105220812-1d2789cb2f0b
|
||||
github.com/sirupsen/logrus v1.5.0
|
||||
github.com/ulule/limiter/v3 v3.5.0
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a
|
||||
|
@ -208,12 +208,15 @@ html > ::-webkit-scrollbar {
|
||||
}
|
||||
|
||||
.guild {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25);
|
||||
|
||||
width: 33%;
|
||||
background-color: #121212;
|
||||
height: 100px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@ -240,3 +243,23 @@ html > ::-webkit-scrollbar {
|
||||
color: white !important;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.flex-container {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#guild-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#refresh-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
margin-top: 20px;
|
||||
color: white;
|
||||
}
|
@ -36,3 +36,11 @@ function appendButton(tr, content, onclick) {
|
||||
tdRemove.appendChild(removeButton);
|
||||
tr.appendChild(tdRemove);
|
||||
}
|
||||
|
||||
function prependChild(parent, child) {
|
||||
if (parent.children.length === 0) {
|
||||
parent.appendChild(child);
|
||||
} else {
|
||||
parent.insertBefore(child, parent.children[0]);
|
||||
}
|
||||
}
|
||||
|
@ -9,22 +9,17 @@
|
||||
</div>
|
||||
<div class="card-body" id="card">
|
||||
<div class="card-body table-responsive">
|
||||
<p class="center-align white" style="padding-top: 50px; font-size: 16px; display: none" id="no-guilds">
|
||||
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"><button class="btn btn-primary btn-fill"><i class="fas fa-plus"></i> Invite</button></a>
|
||||
</p>
|
||||
<div class="container-fluid">
|
||||
<div class="row" id="guild-container">
|
||||
<div class="col-md-4">
|
||||
<div class="guild align-items-center" onclick="invite();">
|
||||
<div class="flex-container" id="guild-container">
|
||||
<div class="guild" onclick="invite();" id="invite-container">
|
||||
<i class="fas fa-plus fa-2x guild-icon-fa"></i>
|
||||
<div class="align-items-center">
|
||||
<span class="guild-name">Invite to your server</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-container" id="refresh-container">
|
||||
<button class="btn btn-primary btn-fill" onclick="refreshGuilds()">
|
||||
<i class="fas fa-sync"></i> Refresh list
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -61,15 +56,11 @@
|
||||
async function loadData() {
|
||||
const res = await axios.get('/user/guilds');
|
||||
|
||||
if (res.data.length > 0) {
|
||||
const container = document.getElementById('guild-container');
|
||||
|
||||
for (guild of res.data) {
|
||||
const col = document.createElement('div');
|
||||
col.classList.add('col-md-4');
|
||||
|
||||
const guildContainer = document.createElement('div');
|
||||
guildContainer.classList.add('guild', 'align-items-center');
|
||||
guildContainer.classList.add('guild');
|
||||
|
||||
if (guild.icon === undefined || guild.icon === null || guild.icon === "") {
|
||||
const icon = document.createElement('i');
|
||||
@ -89,7 +80,6 @@
|
||||
}
|
||||
|
||||
const nameContainer = document.createElement('div');
|
||||
nameContainer.classList.add('align-items-center');
|
||||
|
||||
const name = document.createElement('span');
|
||||
name.classList.add('guild-name');
|
||||
@ -99,14 +89,33 @@
|
||||
guildContainer.appendChild(nameContainer);
|
||||
|
||||
const guildId = guild.id
|
||||
guildContainer.onclick = async () => { await goto(guildId) };
|
||||
guildContainer.onclick = async () => {
|
||||
await goto(guildId)
|
||||
};
|
||||
|
||||
col.appendChild(guildContainer);
|
||||
container.appendChild(col);
|
||||
container.insertBefore(guildContainer, container.children[container.children.length - 1]);
|
||||
}
|
||||
} else {
|
||||
document.getElementById('no-guilds').style.display = 'block';
|
||||
}
|
||||
|
||||
async function refreshGuilds() {
|
||||
await withLoadingScreen(async () => {
|
||||
const res = await axios.post('/user/guilds/reload');
|
||||
if (res.status !== 200) {
|
||||
notifyError(res.data.error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!res.data.success && res.data['reauthenticate_required'] === true) {
|
||||
window.location.href = "/login";
|
||||
return;
|
||||
}
|
||||
|
||||
const inviteContainer = document.getElementById('invite-container');
|
||||
document.getElementById('guild-container').innerHTML = ``;
|
||||
document.getElementById('guild-container').appendChild(inviteContainer);
|
||||
|
||||
await loadData();
|
||||
});
|
||||
}
|
||||
|
||||
withLoadingScreen(async () => {
|
||||
|
@ -20,7 +20,6 @@
|
||||
<tr>
|
||||
<th>Channel</th>
|
||||
<th>Panel Title</th>
|
||||
<th>Panel Content</th>
|
||||
<th>Ticket Channel Category</th>
|
||||
<th>Edit</th>
|
||||
<th>Delete</th>
|
||||
@ -377,7 +376,6 @@
|
||||
|
||||
appendTd(tr, `#${getChannelName(channels, panel.channel_id)}`);
|
||||
appendTd(tr, panel.title);
|
||||
appendTd(tr, panel.content);
|
||||
appendTd(tr, getChannelName(channels, panel.category_id));
|
||||
|
||||
// build edit button
|
||||
|
38
utils/guildutils.go
Normal file
38
utils/guildutils.go
Normal file
@ -0,0 +1,38 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
dbclient "github.com/TicketsBot/GoPanel/database"
|
||||
"github.com/TicketsBot/database"
|
||||
"github.com/rxdn/gdl/rest"
|
||||
)
|
||||
|
||||
func LoadGuilds(accessToken string, userId uint64) error {
|
||||
authHeader := fmt.Sprintf("Bearer %s", accessToken)
|
||||
|
||||
data := rest.CurrentUserGuildsData{
|
||||
Limit: 100,
|
||||
}
|
||||
|
||||
guilds, err := rest.GetCurrentUserGuilds(authHeader, nil, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var wrappedGuilds []database.UserGuild
|
||||
|
||||
// endpoint's partial guild doesn't include ownerid
|
||||
// we only user cached guilds on the index page, so it doesn't matter if we don't have have the real owner id
|
||||
// if the user isn't the owner, as we pull from the cache on other endpoints
|
||||
for _, guild := range guilds {
|
||||
wrappedGuilds = append(wrappedGuilds, database.UserGuild{
|
||||
GuildId: guild.Id,
|
||||
Name: guild.Name,
|
||||
Owner: guild.Owner,
|
||||
UserPermissions: int32(guild.Permissions),
|
||||
Icon: guild.Icon,
|
||||
})
|
||||
}
|
||||
|
||||
return dbclient.Client.UserGuilds.Set(userId, wrappedGuilds)
|
||||
}
|
@ -1,11 +1,18 @@
|
||||
package utils
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func ErrorToResponse(err error) map[string]interface{} {
|
||||
return ErrorStr(err.Error())
|
||||
}
|
||||
|
||||
func ErrorStr(err string, format ...interface{}) map[string]interface{} {
|
||||
return gin.H {
|
||||
"success": false,
|
||||
"error": err.Error(),
|
||||
"error": fmt.Sprintf(err, format...),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user