/
login.go
127 lines (106 loc) · 3.29 KB
/
login.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package slashcommands
import (
"fmt"
"time"
"github.com/bwmarrin/discordgo"
"github.com/zekroTJA/shinpuru/internal/services/config"
"github.com/zekroTJA/shinpuru/internal/services/database"
"github.com/zekroTJA/shinpuru/internal/services/permissions"
"github.com/zekroTJA/shinpuru/internal/util/static"
"github.com/zekroTJA/shinpuru/pkg/onetimeauth/v2"
"github.com/zekroTJA/shinpuru/pkg/timerstack"
"github.com/zekrotja/ken"
)
type Login struct {
ken.EphemeralCommand
}
var (
_ ken.SlashCommand = (*Login)(nil)
_ permissions.PermCommand = (*Login)(nil)
_ ken.DmCapable = (*Login)(nil)
)
func (c *Login) Name() string {
return "login"
}
func (c *Login) Description() string {
return "Log in to the web interface."
}
func (c *Login) Version() string {
return "1.1.0"
}
func (c *Login) Type() discordgo.ApplicationCommandType {
return discordgo.ChatApplicationCommand
}
func (c *Login) IsDmCapable() bool {
return true
}
func (c *Login) Options() []*discordgo.ApplicationCommandOption {
return []*discordgo.ApplicationCommandOption{}
}
func (c *Login) Domain() string {
return "sp.etc.login"
}
func (c *Login) SubDomains() []permissions.SubPermission {
return nil
}
func (c *Login) Run(ctx ken.Context) (err error) {
if err = ctx.Defer(); err != nil {
return
}
cfg := ctx.Get(static.DiConfig).(config.Provider)
ota := ctx.Get(static.DiOneTimeAuth).(onetimeauth.OneTimeAuth)
db := ctx.Get(static.DiDatabase).(database.Database)
enabled, err := db.GetUserOTAEnabled(ctx.User().ID)
if err != nil && !database.IsErrDatabaseNotFound(err) {
return
}
if !enabled {
enableLink := fmt.Sprintf("%s/usersettings", cfg.Config().WebServer.PublicAddr)
err = ctx.FollowUpError(
"One Time Authorization is disabled by default. If you want to use it, you need "+
"to enable it first in your [**user settings page**]("+enableLink+").", "").
Send().Error
return err
}
token, _, err := ota.GetKey(ctx.User().ID, "login-via-dm")
if err != nil {
return
}
link := fmt.Sprintf("%s/api/ota?token=%s", cfg.Config().WebServer.PublicAddr, token)
emb := &discordgo.MessageEmbed{
Color: static.ColorEmbedDefault,
Description: "Click this [**this link**](" + link + ") and you will be automatically logged " +
"in to the shinpuru web interface.\n\nThis link expires in one minute.",
}
fum := ctx.FollowUpEmbed(emb).AddComponents(func(cb *ken.ComponentBuilder) {
cb.AddActionsRow(func(b ken.ComponentAssembler) {
b.Add(discordgo.Button{
Label: "Login to the Web Interface",
Style: discordgo.LinkButton,
URL: link,
}, nil)
})
}).Send()
if fum.HasError() {
return fum.Error
}
timerstack.New().After(1*time.Minute, func() bool {
emb := &discordgo.MessageEmbed{
Color: static.ColorEmbedGray,
Description: "The login link has expired.",
}
fum.Edit(&discordgo.WebhookEdit{
Embeds: &[]*discordgo.MessageEmbed{emb},
Components: &[]discordgo.MessageComponent{discordgo.ActionsRow{
Components: []discordgo.MessageComponent{discordgo.Button{
Label: "Login to the Web Interface",
Style: discordgo.LinkButton,
Disabled: true,
URL: link,
}},
}},
})
return true
}).RunBlocking()
return
}