Threads
This commit is contained in:
parent
c2239ef882
commit
d745f26dd8
@ -182,7 +182,7 @@ func GetSettingsHandler(ctx *gin.Context) {
|
||||
LanguageNames map[i18n.Language]string `json:"language_names"`
|
||||
}{
|
||||
Settings: settings,
|
||||
Languages: i18n.LanguagesAlphabetical,
|
||||
Languages: i18n.LanguagesAlphabetical[:],
|
||||
LanguageNames: i18n.FullNames,
|
||||
})
|
||||
}
|
||||
|
@ -114,13 +114,17 @@ func (s *Settings) Validate(guildId uint64, premiumTier premium.PremiumTier) err
|
||||
return errors.New("Must be able to view channel to type")
|
||||
}
|
||||
|
||||
if s.Settings.UseThreads {
|
||||
return fmt.Errorf("threads are disabled")
|
||||
if s.Settings.UseThreads && s.TicketNotificationChannel == nil {
|
||||
return errors.New("You must select a ticket notification channel")
|
||||
}
|
||||
|
||||
if !s.Settings.UseThreads {
|
||||
s.TicketNotificationChannel = nil
|
||||
}
|
||||
|
||||
if s.Language != nil {
|
||||
if _, ok := i18n.FullNames[*s.Language]; !ok {
|
||||
return fmt.Errorf("invalid language")
|
||||
return errors.New("Invalid language")
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,6 +226,25 @@ func (s *Settings) Validate(guildId uint64, premiumTier premium.PremiumTier) err
|
||||
return nil
|
||||
})
|
||||
|
||||
group.Go(func() error {
|
||||
if s.Settings.TicketNotificationChannel != nil {
|
||||
ch, ok := cache.Instance.GetChannel(*s.Settings.TicketNotificationChannel)
|
||||
if !ok {
|
||||
return fmt.Errorf("Invalid ticket notification channel")
|
||||
}
|
||||
|
||||
if ch.GuildId != guildId {
|
||||
return fmt.Errorf("Ticket notification channel guild ID does not match")
|
||||
}
|
||||
|
||||
if ch.Type != channel.ChannelTypeGuildText {
|
||||
return fmt.Errorf("Ticket notification channel is not a text channel")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return group.Wait()
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,14 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/TicketsBot/GoPanel/botcontext"
|
||||
dbclient "github.com/TicketsBot/GoPanel/database"
|
||||
"github.com/TicketsBot/GoPanel/utils"
|
||||
"github.com/TicketsBot/database"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/rxdn/gdl/rest"
|
||||
"github.com/rxdn/gdl/rest/request"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
@ -92,11 +96,61 @@ func removeDefaultMember(ctx *gin.Context, guildId, selfId, snowflake uint64, en
|
||||
return
|
||||
}
|
||||
|
||||
// Remove on-call role
|
||||
metadata, err := dbclient.Client.GuildMetadata.Get(guildId)
|
||||
if err != nil {
|
||||
ctx.JSON(500, utils.ErrorJson(err))
|
||||
return
|
||||
}
|
||||
|
||||
if metadata.OnCallRole != nil {
|
||||
botContext, err := botcontext.ContextForGuild(guildId)
|
||||
if err != nil {
|
||||
ctx.JSON(500, utils.ErrorJson(err))
|
||||
return
|
||||
}
|
||||
|
||||
if entityType == entityTypeUser {
|
||||
// If the member is not in the guild we do not have to worry
|
||||
member, err := botContext.GetGuildMember(guildId, snowflake)
|
||||
if err == nil {
|
||||
if member.HasRole(*metadata.OnCallRole) {
|
||||
// Attempt to remove role but ignore failure
|
||||
_ = botContext.RemoveGuildMemberRole(guildId, snowflake, *metadata.OnCallRole)
|
||||
}
|
||||
} else {
|
||||
if err, ok := err.(request.RestError); !ok || err.StatusCode != 404 {
|
||||
ctx.JSON(500, utils.ErrorJson(err))
|
||||
return
|
||||
}
|
||||
}
|
||||
} else if entityType == entityTypeRole {
|
||||
// Recreate role
|
||||
if err := dbclient.Client.GuildMetadata.SetOnCallRole(guildId, nil); err != nil {
|
||||
ctx.JSON(500, utils.ErrorJson(err))
|
||||
return
|
||||
}
|
||||
|
||||
if err := botContext.DeleteGuildRole(guildId, *metadata.OnCallRole); err != nil && !isUnknownRoleError(err) {
|
||||
ctx.JSON(500, utils.ErrorJson(err))
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := createOnCallRole(botContext, guildId, nil); err != nil {
|
||||
ctx.JSON(500, utils.ErrorJson(err))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
ctx.JSON(500, utils.ErrorStr("Infallible"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ctx.JSON(200, utils.SuccessResponse)
|
||||
}
|
||||
|
||||
func removeTeamMember(ctx *gin.Context, teamId int, guildId, snowflake uint64, entityType entityType) {
|
||||
exists, err := dbclient.Client.SupportTeam.Exists(teamId, guildId)
|
||||
team, exists, err := dbclient.Client.SupportTeam.GetById(guildId, teamId)
|
||||
if err != nil {
|
||||
ctx.JSON(500, utils.ErrorJson(err))
|
||||
return
|
||||
@ -107,6 +161,7 @@ func removeTeamMember(ctx *gin.Context, teamId int, guildId, snowflake uint64, e
|
||||
return
|
||||
}
|
||||
|
||||
// Remove from DB
|
||||
switch entityType {
|
||||
case entityTypeUser:
|
||||
err = dbclient.Client.SupportTeamMembers.Delete(teamId, snowflake)
|
||||
@ -119,5 +174,89 @@ func removeTeamMember(ctx *gin.Context, teamId int, guildId, snowflake uint64, e
|
||||
return
|
||||
}
|
||||
|
||||
// Remove on-call role
|
||||
if team.OnCallRole != nil {
|
||||
botContext, err := botcontext.ContextForGuild(guildId)
|
||||
if err != nil {
|
||||
ctx.JSON(500, utils.ErrorJson(err))
|
||||
return
|
||||
}
|
||||
|
||||
if entityType == entityTypeUser {
|
||||
// If the member is not in the guild we do not have to worry
|
||||
member, err := botContext.GetGuildMember(guildId, snowflake)
|
||||
if err == nil {
|
||||
if member.HasRole(*team.OnCallRole) {
|
||||
// Attempt to remove role but ignore failure
|
||||
_ = botContext.RemoveGuildMemberRole(guildId, snowflake, *team.OnCallRole)
|
||||
}
|
||||
} else {
|
||||
if err, ok := err.(request.RestError); !ok || err.StatusCode != 404 {
|
||||
ctx.JSON(500, utils.ErrorJson(err))
|
||||
return
|
||||
}
|
||||
}
|
||||
_ = botContext.RemoveGuildMemberRole(guildId, snowflake, *team.OnCallRole)
|
||||
} else if entityType == entityTypeRole {
|
||||
// Recreate role
|
||||
if err := dbclient.Client.SupportTeam.SetOnCallRole(teamId, nil); err != nil {
|
||||
ctx.JSON(500, utils.ErrorJson(err))
|
||||
return
|
||||
}
|
||||
|
||||
if err := botContext.DeleteGuildRole(guildId, *team.OnCallRole); err != nil && !isUnknownRoleError(err) {
|
||||
ctx.JSON(500, utils.ErrorJson(err))
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := createOnCallRole(botContext, guildId, &team); err != nil {
|
||||
ctx.JSON(500, utils.ErrorJson(err))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
ctx.JSON(500, utils.ErrorStr("Infallible"))
|
||||
}
|
||||
}
|
||||
|
||||
ctx.JSON(200, utils.SuccessResponse)
|
||||
}
|
||||
|
||||
func createOnCallRole(botContext botcontext.BotContext, guildId uint64, team *database.SupportTeam) (uint64, error) {
|
||||
var roleName string
|
||||
if team == nil {
|
||||
roleName = "On Call" // TODO: Translate
|
||||
} else {
|
||||
roleName = utils.StringMax(fmt.Sprintf("On Call - %s", team.Name), 100)
|
||||
}
|
||||
|
||||
data := rest.GuildRoleData{
|
||||
Name: roleName,
|
||||
Hoist: utils.Ptr(false),
|
||||
Mentionable: utils.Ptr(false),
|
||||
}
|
||||
|
||||
role, err := botContext.CreateGuildRole(guildId, data)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if team == nil {
|
||||
if err := dbclient.Client.GuildMetadata.SetOnCallRole(guildId, &role.Id); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
} else {
|
||||
if err := dbclient.Client.SupportTeam.SetOnCallRole(team.Id, &role.Id); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
return role.Id, nil
|
||||
}
|
||||
|
||||
func isUnknownRoleError(err error) bool {
|
||||
if err, ok := err.(request.RestError); ok && err.ApiError.Message == "Unknown Role" {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
@ -95,6 +95,21 @@ func (ctx BotContext) GetGuildMember(guildId, userId uint64) (m member.Member, e
|
||||
return
|
||||
}
|
||||
|
||||
func (ctx BotContext) RemoveGuildMemberRole(guildId, userId, roleId uint64) (err error) {
|
||||
err = rest.RemoveGuildMemberRole(ctx.Token, ctx.RateLimiter, guildId, userId, roleId)
|
||||
return
|
||||
}
|
||||
|
||||
func (ctx BotContext) CreateGuildRole(guildId uint64, data rest.GuildRoleData) (role guild.Role, err error) {
|
||||
role, err = rest.CreateGuildRole(ctx.Token, ctx.RateLimiter, guildId, data)
|
||||
return
|
||||
}
|
||||
|
||||
func (ctx BotContext) DeleteGuildRole(guildId, roleId uint64) (err error) {
|
||||
err = rest.DeleteGuildRole(ctx.Token, ctx.RateLimiter, guildId, roleId)
|
||||
return
|
||||
}
|
||||
|
||||
func (ctx BotContext) GetUser(userId uint64) (u user.User, err error) {
|
||||
u, err = rest.GetUser(ctx.Token, ctx.RateLimiter, userId)
|
||||
if err == nil {
|
||||
|
@ -1,4 +1,4 @@
|
||||
<Dropdown {col1} {col2} {col3} {col4} bind:value label={label}>
|
||||
<Dropdown {col1} {col2} {col3} {col4} bind:value {label} {disabled} >
|
||||
{#if withNull}
|
||||
<option value=null>
|
||||
{nullLabel}
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
export let value;
|
||||
export let label;
|
||||
export let disabled = false;
|
||||
export let channels = [];
|
||||
export let withNull = false;
|
||||
export let nullLabel = "Disabled";
|
||||
|
@ -11,7 +11,14 @@
|
||||
{#if tooltip !== undefined}
|
||||
<div style="">
|
||||
<Tooltip tip={tooltip} top color="#121212">
|
||||
|
||||
{#if tooltipUrl !== undefined}
|
||||
<a href={tooltipUrl} target="_blank">
|
||||
<i class="fas fa-circle-info form-label tooltip-icon"></i>
|
||||
</a>
|
||||
{:else}
|
||||
<i class="fas fa-circle-info form-label tooltip-icon"></i>
|
||||
{/if}
|
||||
</Tooltip>
|
||||
</div>
|
||||
{/if}
|
||||
@ -35,6 +42,7 @@
|
||||
|
||||
export let defaultOpen = false;
|
||||
export let tooltip;
|
||||
export let tooltipUrl;
|
||||
|
||||
let expanded = false;
|
||||
let showOverflow = true;
|
||||
|
27
frontend/src/components/IconBadge.svelte
Normal file
27
frontend/src/components/IconBadge.svelte
Normal file
@ -0,0 +1,27 @@
|
||||
<Badge>
|
||||
<div class="inner">
|
||||
{#if icon !== undefined}
|
||||
<i class="{icon}"></i>
|
||||
{/if}
|
||||
<span class="text">
|
||||
<slot />
|
||||
</span>
|
||||
</div>
|
||||
</Badge>
|
||||
|
||||
<script>
|
||||
import Badge from "./Badge.svelte";
|
||||
|
||||
export let text;
|
||||
export let icon;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.inner {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
@ -1,5 +1,9 @@
|
||||
<div class:col-1={col1} class:col-2={col2} class:col-3={col3} class:col-4={col4}>
|
||||
<label for="input" class="form-label">{label}</label>
|
||||
<slot name="label">
|
||||
<label for="input" class="form-label">
|
||||
{label}
|
||||
</label>
|
||||
</slot>
|
||||
<input id="input" class="form-checkbox" type=checkbox bind:checked={value} on:change {disabled}>
|
||||
</div>
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
{#if label !== undefined}
|
||||
<label for="input" class="form-label">{label}</label>
|
||||
{/if}
|
||||
<select id="input" class="form-input" on:change bind:value={value}>
|
||||
<select id="input" class="form-input" on:change bind:value={value} {disabled}>
|
||||
<slot />
|
||||
</select>
|
||||
</div>
|
||||
@ -16,6 +16,7 @@
|
||||
<script>
|
||||
export let value;
|
||||
export let label;
|
||||
export let disabled = false;
|
||||
|
||||
export let col1 = false;
|
||||
export let col2 = false;
|
||||
|
@ -27,13 +27,27 @@
|
||||
</div>
|
||||
</Collapsible>
|
||||
|
||||
<Collapsible defaultOpen tooltip="Click here to find out more about thread mode" tooltipUrl="https://docs.ticketsbot.net">
|
||||
<span slot="header" class="header">
|
||||
Thread Mode
|
||||
<IconBadge icon="fas fa-flask">Beta</IconBadge>
|
||||
</span>
|
||||
<div slot="content" class="col-1">
|
||||
<div class="row">
|
||||
<Checkbox label="Enabled" bind:value={data.use_threads}/>
|
||||
<ChannelDropdown label="Ticket Notification Channel" col4 {channels} disabled={!data.use_threads}
|
||||
bind:value={data.ticket_notification_channel}/>
|
||||
</div>
|
||||
</div>
|
||||
</Collapsible>
|
||||
|
||||
<Collapsible defaultOpen>
|
||||
<span slot="header">Tickets</span>
|
||||
<div slot="content" class="col-1">
|
||||
<div class="row">
|
||||
<ChannelDropdown label="Archive Channel" col3=true channels={channels} withNull={true}
|
||||
<ChannelDropdown label="Archive Channel" col4 channels={channels} withNull={true}
|
||||
bind:value={data.archive_channel}/>
|
||||
<Dropdown label="Overflow Category" col3=true bind:value={data.overflow_category_id}>
|
||||
<Dropdown label="Overflow Category" col4 bind:value={data.overflow_category_id}>
|
||||
<option value=-1>Disabled</option>
|
||||
<option value=-2>Uncategorised (Appears at top of channel list)</option>
|
||||
{#each channels as channel}
|
||||
@ -197,6 +211,7 @@
|
||||
import PremiumBadge from "../PremiumBadge.svelte";
|
||||
import {toDays, toHours, toMinutes} from "../../js/timeutil";
|
||||
import Toggle from "../form/Toggle.svelte";
|
||||
import IconBadge from "../IconBadge.svelte";
|
||||
|
||||
export let guildId;
|
||||
|
||||
@ -476,6 +491,6 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
gap: 5px;
|
||||
}
|
||||
</style>
|
||||
|
7
go.mod
7
go.mod
@ -6,9 +6,9 @@ require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/TicketsBot/archiverclient v0.0.0-20220326163414-558fd52746dc
|
||||
github.com/TicketsBot/common v0.0.0-20220703211704-f792aa9f0c42
|
||||
github.com/TicketsBot/database v0.0.0-20220804213011-190281e8f797
|
||||
github.com/TicketsBot/database v0.0.0-20220830131231-b5540b57f6cb
|
||||
github.com/TicketsBot/logarchiver v0.0.0-20220326162808-cdf0310f5e1c
|
||||
github.com/TicketsBot/worker v0.0.0-20220802140902-30ca73aea6b8
|
||||
github.com/TicketsBot/worker v0.0.0-20220830131837-12d85aca5c71
|
||||
github.com/apex/log v1.1.2
|
||||
github.com/getsentry/sentry-go v0.13.0
|
||||
github.com/gin-gonic/contrib v0.0.0-20191209060500-d6e26eeaa607
|
||||
@ -25,7 +25,7 @@ require (
|
||||
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-20220726141522-788c9ce67ad0
|
||||
github.com/rxdn/gdl v0.0.0-20220830131333-09a2e5819976
|
||||
github.com/sirupsen/logrus v1.6.0
|
||||
github.com/weppos/publicsuffix-go v0.20.0
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
|
||||
@ -80,6 +80,7 @@ require (
|
||||
github.com/ugorji/go/codec v1.2.6 // indirect
|
||||
go.uber.org/atomic v1.6.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
|
||||
|
20
go.sum
20
go.sum
@ -39,14 +39,14 @@ github.com/TicketsBot/archiverclient v0.0.0-20220326163414-558fd52746dc h1:n15W8
|
||||
github.com/TicketsBot/archiverclient v0.0.0-20220326163414-558fd52746dc/go.mod h1:2KcfHS0JnSsgcxZBs3NyWMXNQzEo67mBSGOyzHPWOCc=
|
||||
github.com/TicketsBot/common v0.0.0-20220703211704-f792aa9f0c42 h1:3/qnbrEfL8gqSbjJ4o7WKkdoPngmhjAGEXFwteEjpqs=
|
||||
github.com/TicketsBot/common v0.0.0-20220703211704-f792aa9f0c42/go.mod h1:WxHh6bY7KhIqdayeOp5f0Zj2NNi/7QqCQfMEqHnpdAM=
|
||||
github.com/TicketsBot/database v0.0.0-20220804213011-190281e8f797 h1:1RIBwjPJqTmVrBztWQxE6OHKZjwTqxfXMRQrPuMaQzk=
|
||||
github.com/TicketsBot/database v0.0.0-20220804213011-190281e8f797/go.mod h1:gAtOoQKZfCkQ4AoNWQUSl51Fnlqk+odzD/hZ1e1sXyI=
|
||||
github.com/TicketsBot/database v0.0.0-20220830131231-b5540b57f6cb h1:mXBn09KBzbVRmg+k1JC67DL8YXisCO74D9nIW/xi9Vg=
|
||||
github.com/TicketsBot/database v0.0.0-20220830131231-b5540b57f6cb/go.mod h1:gAtOoQKZfCkQ4AoNWQUSl51Fnlqk+odzD/hZ1e1sXyI=
|
||||
github.com/TicketsBot/logarchiver v0.0.0-20220326162808-cdf0310f5e1c h1:OqGjFH6mbE6gd+NqI2ARJdtH3UUvhiAkD0r0fhGJK2s=
|
||||
github.com/TicketsBot/logarchiver v0.0.0-20220326162808-cdf0310f5e1c/go.mod h1:jgi2OXQKsd5nUnTIRkwvPmeuD/i7OhN68LKMssuQY1c=
|
||||
github.com/TicketsBot/ttlcache v1.6.1-0.20200405150101-acc18e37b261 h1:NHD5GB6cjlkpZFjC76Yli2S63/J2nhr8MuE6KlYJpQM=
|
||||
github.com/TicketsBot/ttlcache v1.6.1-0.20200405150101-acc18e37b261/go.mod h1:2zPxDAN2TAPpxUPjxszjs3QFKreKrQh5al/R3cMXmYk=
|
||||
github.com/TicketsBot/worker v0.0.0-20220802140902-30ca73aea6b8 h1:/hxUoNMsAD1HeG66iPDn0G5zQ8RNltaiL2h50LNplaA=
|
||||
github.com/TicketsBot/worker v0.0.0-20220802140902-30ca73aea6b8/go.mod h1:E8y+9Xu8el7QzHALhR/IFvITcJJkDeAxfsBFIEEWJuo=
|
||||
github.com/TicketsBot/worker v0.0.0-20220830131837-12d85aca5c71 h1:9cXKmN0wDrafXpLhbaOgFCBZlP903nFDm6sPo9UPHwA=
|
||||
github.com/TicketsBot/worker v0.0.0-20220830131837-12d85aca5c71/go.mod h1:1lgdQCRso/tfis5E5bb2CyKPMbSDJpigM/LfmubgKHE=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
@ -196,8 +196,8 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
@ -405,8 +405,10 @@ github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6po
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
github.com/rxdn/gdl v0.0.0-20220726141522-788c9ce67ad0 h1:i2WqGZFCpow9d9ZfdVbEExeCkAnw969CIMyOtebqGVY=
|
||||
github.com/rxdn/gdl v0.0.0-20220726141522-788c9ce67ad0/go.mod h1:HtxfLp4OaoPoDJHQ4JOx/QeLH2d40VgT3wNOf7ETsRE=
|
||||
github.com/rxdn/gdl v0.0.0-20220816151714-b119c7b939a9 h1:X4kT2+HgTHIfBFWdDbk4nzqxhfeq/mdkr/WUPs2R5LE=
|
||||
github.com/rxdn/gdl v0.0.0-20220816151714-b119c7b939a9/go.mod h1:HtxfLp4OaoPoDJHQ4JOx/QeLH2d40VgT3wNOf7ETsRE=
|
||||
github.com/rxdn/gdl v0.0.0-20220830131333-09a2e5819976 h1:8txEQWvEVqHZfrD5WFIj4NMC+waEPYBf9abZjOP+rkQ=
|
||||
github.com/rxdn/gdl v0.0.0-20220830131333-09a2e5819976/go.mod h1:HtxfLp4OaoPoDJHQ4JOx/QeLH2d40VgT3wNOf7ETsRE=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/schollz/progressbar/v3 v3.8.2 h1:2kZJwZCpb+E/V79kGO7daeq+hUwUJW0A5QD1Wv455dA=
|
||||
github.com/schollz/progressbar/v3 v3.8.2/go.mod h1:9KHLdyuXczIsyStQwzvW8xiELskmX7fQMaZdN23nAv8=
|
||||
@ -493,6 +495,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@ -681,8 +685,8 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY
|
||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e h1:4nW4NLDYnU28ojHaHO8OVxFHk/aQ33U01a9cjED+pzE=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"encoding/base64"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
@ -22,7 +23,8 @@ func IsInt(str string) bool {
|
||||
}
|
||||
|
||||
func Base64Decode(s string) string {
|
||||
b, err := base64.StdEncoding.DecodeString(s); if err != nil {
|
||||
b, err := base64.StdEncoding.DecodeString(s)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(b)
|
||||
@ -32,6 +34,10 @@ func Base64Encode(s string) string {
|
||||
return base64.StdEncoding.EncodeToString([]byte(s))
|
||||
}
|
||||
|
||||
func StrPtr(s string) *string {
|
||||
return &s
|
||||
func StringMax(str string, max int, suffix ...string) string {
|
||||
if len(str) > max {
|
||||
return str[:max] + strings.Join(suffix, "")
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user