Segregate configuration management into config package
This commit is contained in:
parent
6683322bb1
commit
44f006bb0f
9 changed files with 109 additions and 105 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -7,61 +7,7 @@ import (
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
const name = "discordo"
|
const Name = "discordo"
|
||||||
|
|
||||||
type (
|
|
||||||
MessagesTextKeysConfig struct {
|
|
||||||
CopyContent string `yaml:"copy_content"`
|
|
||||||
|
|
||||||
Reply string `yaml:"reply"`
|
|
||||||
ReplyMention string `yaml:"reply_mention"`
|
|
||||||
SelectReply string `yaml:"select_reply"`
|
|
||||||
|
|
||||||
SelectPrevious string `yaml:"select_previous"`
|
|
||||||
SelectNext string `yaml:"select_next"`
|
|
||||||
SelectFirst string `yaml:"select_first"`
|
|
||||||
SelectLast string `yaml:"select_last"`
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageInputKeysConfig struct {
|
|
||||||
Send string `yaml:"send"`
|
|
||||||
Paste string `yaml:"paste"`
|
|
||||||
|
|
||||||
LaunchEditor string `yaml:"launch_editor"`
|
|
||||||
}
|
|
||||||
|
|
||||||
KeysConfig struct {
|
|
||||||
Cancel string `yaml:"cancel"`
|
|
||||||
|
|
||||||
MessagesText MessagesTextKeysConfig `yaml:"messages_text"`
|
|
||||||
MessageInput MessageInputKeysConfig `yaml:"message_input"`
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
GuildsTreeThemeConfig struct {
|
|
||||||
Graphics bool `yaml:"graphics"`
|
|
||||||
}
|
|
||||||
|
|
||||||
MessagesTextThemeConfig struct {
|
|
||||||
AuthorColor string `yaml:"author_color"`
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageInputThemeConfig struct{}
|
|
||||||
|
|
||||||
ThemeConfig struct {
|
|
||||||
Border bool `yaml:"border"`
|
|
||||||
BorderColor string `yaml:"border_color"`
|
|
||||||
BorderPadding [4]int `yaml:"border_padding,flow"`
|
|
||||||
|
|
||||||
TitleColor string `yaml:"title_color"`
|
|
||||||
BackgroundColor string `yaml:"background_color"`
|
|
||||||
|
|
||||||
GuildsTree GuildsTreeThemeConfig `yaml:"guilds_tree"`
|
|
||||||
MessagesText MessagesTextThemeConfig `yaml:"messages_text"`
|
|
||||||
MessageInput MessageInputThemeConfig `yaml:"message_input"`
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Mouse bool `yaml:"mouse"`
|
Mouse bool `yaml:"mouse"`
|
||||||
|
|
@ -73,13 +19,13 @@ type Config struct {
|
||||||
Theme ThemeConfig `yaml:"theme"`
|
Theme ThemeConfig `yaml:"theme"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func newConfig() (*Config, error) {
|
func New() (*Config, error) {
|
||||||
path, err := os.UserConfigDir()
|
path, err := os.UserConfigDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
path = filepath.Join(path, name)
|
path = filepath.Join(path, Name)
|
||||||
err = os.MkdirAll(path, os.ModePerm)
|
err = os.MkdirAll(path, os.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
30
config/keys.go
Normal file
30
config/keys.go
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
type (
|
||||||
|
MessagesTextKeysConfig struct {
|
||||||
|
CopyContent string `yaml:"copy_content"`
|
||||||
|
|
||||||
|
Reply string `yaml:"reply"`
|
||||||
|
ReplyMention string `yaml:"reply_mention"`
|
||||||
|
SelectReply string `yaml:"select_reply"`
|
||||||
|
|
||||||
|
SelectPrevious string `yaml:"select_previous"`
|
||||||
|
SelectNext string `yaml:"select_next"`
|
||||||
|
SelectFirst string `yaml:"select_first"`
|
||||||
|
SelectLast string `yaml:"select_last"`
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageInputKeysConfig struct {
|
||||||
|
Send string `yaml:"send"`
|
||||||
|
Paste string `yaml:"paste"`
|
||||||
|
|
||||||
|
LaunchEditor string `yaml:"launch_editor"`
|
||||||
|
}
|
||||||
|
|
||||||
|
KeysConfig struct {
|
||||||
|
Cancel string `yaml:"cancel"`
|
||||||
|
|
||||||
|
MessagesText MessagesTextKeysConfig `yaml:"messages_text"`
|
||||||
|
MessageInput MessageInputKeysConfig `yaml:"message_input"`
|
||||||
|
}
|
||||||
|
)
|
||||||
26
config/theme.go
Normal file
26
config/theme.go
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
type (
|
||||||
|
GuildsTreeThemeConfig struct {
|
||||||
|
Graphics bool `yaml:"graphics"`
|
||||||
|
}
|
||||||
|
|
||||||
|
MessagesTextThemeConfig struct {
|
||||||
|
AuthorColor string `yaml:"author_color"`
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageInputThemeConfig struct{}
|
||||||
|
|
||||||
|
ThemeConfig struct {
|
||||||
|
Border bool `yaml:"border"`
|
||||||
|
BorderColor string `yaml:"border_color"`
|
||||||
|
BorderPadding [4]int `yaml:"border_padding,flow"`
|
||||||
|
|
||||||
|
TitleColor string `yaml:"title_color"`
|
||||||
|
BackgroundColor string `yaml:"background_color"`
|
||||||
|
|
||||||
|
GuildsTree GuildsTreeThemeConfig `yaml:"guilds_tree"`
|
||||||
|
MessagesText MessagesTextThemeConfig `yaml:"messages_text"`
|
||||||
|
MessageInput MessageInputThemeConfig `yaml:"message_input"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
@ -24,20 +24,20 @@ func newGuildsTree() *GuildsTree {
|
||||||
root: tview.NewTreeNode(""),
|
root: tview.NewTreeNode(""),
|
||||||
}
|
}
|
||||||
|
|
||||||
gt.SetGraphics(config.Theme.GuildsTree.Graphics)
|
gt.SetGraphics(cfg.Theme.GuildsTree.Graphics)
|
||||||
gt.SetRoot(gt.root)
|
gt.SetRoot(gt.root)
|
||||||
gt.SetTopLevel(1)
|
gt.SetTopLevel(1)
|
||||||
gt.SetSelectedFunc(gt.onSelected)
|
gt.SetSelectedFunc(gt.onSelected)
|
||||||
|
|
||||||
gt.SetBackgroundColor(tcell.GetColor(config.Theme.BackgroundColor))
|
gt.SetBackgroundColor(tcell.GetColor(cfg.Theme.BackgroundColor))
|
||||||
|
|
||||||
gt.SetTitle("Guilds")
|
gt.SetTitle("Guilds")
|
||||||
gt.SetTitleColor(tcell.GetColor(config.Theme.TitleColor))
|
gt.SetTitleColor(tcell.GetColor(cfg.Theme.TitleColor))
|
||||||
gt.SetTitleAlign(tview.AlignLeft)
|
gt.SetTitleAlign(tview.AlignLeft)
|
||||||
|
|
||||||
p := config.Theme.BorderPadding
|
p := cfg.Theme.BorderPadding
|
||||||
gt.SetBorder(config.Theme.Border)
|
gt.SetBorder(cfg.Theme.Border)
|
||||||
gt.SetBorderColor(tcell.GetColor(config.Theme.BorderColor))
|
gt.SetBorderColor(tcell.GetColor(cfg.Theme.BorderColor))
|
||||||
gt.SetBorderPadding(p[0], p[1], p[2], p[3])
|
gt.SetBorderPadding(p[0], p[1], p[2], p[3])
|
||||||
|
|
||||||
return gt
|
return gt
|
||||||
|
|
@ -150,7 +150,7 @@ func (gt *GuildsTree) onSelected(n *tview.TreeNode) {
|
||||||
gt.selectedChannel = c
|
gt.selectedChannel = c
|
||||||
messagesText.SetTitle(gt.channelToString(*c))
|
messagesText.SetTitle(gt.channelToString(*c))
|
||||||
|
|
||||||
ms, err := discordState.Messages(ref, config.MessagesLimit)
|
ms, err := discordState.Messages(ref, cfg.MessagesLimit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,11 @@ func newLoginForm() *LoginForm {
|
||||||
lf.AddButton("Login", lf.onLoginButtonSelected)
|
lf.AddButton("Login", lf.onLoginButtonSelected)
|
||||||
|
|
||||||
lf.SetTitle("Login")
|
lf.SetTitle("Login")
|
||||||
lf.SetTitleColor(tcell.GetColor(config.Theme.TitleColor))
|
lf.SetTitleColor(tcell.GetColor(cfg.Theme.TitleColor))
|
||||||
|
|
||||||
p := config.Theme.BorderPadding
|
p := cfg.Theme.BorderPadding
|
||||||
lf.SetBorder(config.Theme.Border)
|
lf.SetBorder(cfg.Theme.Border)
|
||||||
lf.SetBorderColor(tcell.GetColor(config.Theme.BorderColor))
|
lf.SetBorderColor(tcell.GetColor(cfg.Theme.BorderColor))
|
||||||
lf.SetBorderPadding(p[0], p[1], p[2], p[3])
|
lf.SetBorderPadding(p[0], p[1], p[2], p[3])
|
||||||
|
|
||||||
return lf
|
return lf
|
||||||
|
|
|
||||||
13
main.go
13
main.go
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/ayn2op/discordo/config"
|
||||||
"github.com/rivo/tview"
|
"github.com/rivo/tview"
|
||||||
"github.com/zalando/go-keyring"
|
"github.com/zalando/go-keyring"
|
||||||
)
|
)
|
||||||
|
|
@ -14,7 +15,7 @@ import (
|
||||||
var (
|
var (
|
||||||
token string
|
token string
|
||||||
|
|
||||||
config *Config
|
cfg *config.Config
|
||||||
discordState *State
|
discordState *State
|
||||||
|
|
||||||
app = tview.NewApplication()
|
app = tview.NewApplication()
|
||||||
|
|
@ -33,7 +34,7 @@ func init() {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
path = filepath.Join(path, name)
|
path = filepath.Join(path, config.Name)
|
||||||
err = os.MkdirAll(path, os.ModePerm)
|
err = os.MkdirAll(path, os.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|
@ -55,16 +56,16 @@ func main() {
|
||||||
var err error
|
var err error
|
||||||
// If the token is passed via the flag, set it in the keyring.
|
// If the token is passed via the flag, set it in the keyring.
|
||||||
if token != "" {
|
if token != "" {
|
||||||
go keyring.Set(name, "token", token)
|
go keyring.Set(config.Name, "token", token)
|
||||||
} else {
|
} else {
|
||||||
token, err = keyring.Get(name, "token")
|
token, err = keyring.Get(config.Name, "token")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err = newConfig()
|
cfg, err = config.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -95,7 +96,7 @@ func main() {
|
||||||
app.SetRoot(flex, true)
|
app.SetRoot(flex, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
app.EnableMouse(config.Mouse)
|
app.EnableMouse(cfg.Mouse)
|
||||||
err = app.Run()
|
err = app.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|
|
||||||
|
|
@ -24,15 +24,15 @@ func newMessageInput() *MessageInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
mi.SetInputCapture(mi.onInputCapture)
|
mi.SetInputCapture(mi.onInputCapture)
|
||||||
mi.SetBackgroundColor(tcell.GetColor(config.Theme.BackgroundColor))
|
mi.SetBackgroundColor(tcell.GetColor(cfg.Theme.BackgroundColor))
|
||||||
mi.SetFieldBackgroundColor(tcell.GetColor(config.Theme.BackgroundColor))
|
mi.SetFieldBackgroundColor(tcell.GetColor(cfg.Theme.BackgroundColor))
|
||||||
|
|
||||||
mi.SetTitleColor(tcell.GetColor(config.Theme.TitleColor))
|
mi.SetTitleColor(tcell.GetColor(cfg.Theme.TitleColor))
|
||||||
mi.SetTitleAlign(tview.AlignLeft)
|
mi.SetTitleAlign(tview.AlignLeft)
|
||||||
|
|
||||||
p := config.Theme.BorderPadding
|
p := cfg.Theme.BorderPadding
|
||||||
mi.SetBorder(config.Theme.Border)
|
mi.SetBorder(cfg.Theme.Border)
|
||||||
mi.SetBorderColor(tcell.GetColor(config.Theme.BorderColor))
|
mi.SetBorderColor(tcell.GetColor(cfg.Theme.BorderColor))
|
||||||
mi.SetBorderPadding(p[0], p[1], p[2], p[3])
|
mi.SetBorderPadding(p[0], p[1], p[2], p[3])
|
||||||
|
|
||||||
return mi
|
return mi
|
||||||
|
|
@ -45,16 +45,16 @@ func (mi *MessageInput) reset() {
|
||||||
|
|
||||||
func (mi *MessageInput) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
|
func (mi *MessageInput) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
|
||||||
switch event.Name() {
|
switch event.Name() {
|
||||||
case config.Keys.MessageInput.Send:
|
case cfg.Keys.MessageInput.Send:
|
||||||
mi.sendAction()
|
mi.sendAction()
|
||||||
return nil
|
return nil
|
||||||
case config.Keys.MessageInput.Paste:
|
case cfg.Keys.MessageInput.Paste:
|
||||||
mi.pasteAction()
|
mi.pasteAction()
|
||||||
return nil
|
return nil
|
||||||
case config.Keys.MessageInput.LaunchEditor:
|
case cfg.Keys.MessageInput.LaunchEditor:
|
||||||
messageInput.launchEditorAction()
|
messageInput.launchEditorAction()
|
||||||
return nil
|
return nil
|
||||||
case config.Keys.Cancel:
|
case cfg.Keys.Cancel:
|
||||||
mi.reset()
|
mi.reset()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -116,7 +116,7 @@ func (mi *MessageInput) pasteAction() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mi *MessageInput) launchEditorAction() {
|
func (mi *MessageInput) launchEditorAction() {
|
||||||
e := config.Editor
|
e := cfg.Editor
|
||||||
if e == "default" {
|
if e == "default" {
|
||||||
e = os.Getenv("EDITOR")
|
e = os.Getenv("EDITOR")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,15 +37,15 @@ func newMessagesText() *MessagesText {
|
||||||
app.Draw()
|
app.Draw()
|
||||||
})
|
})
|
||||||
|
|
||||||
mt.SetBackgroundColor(tcell.GetColor(config.Theme.BackgroundColor))
|
mt.SetBackgroundColor(tcell.GetColor(cfg.Theme.BackgroundColor))
|
||||||
|
|
||||||
mt.SetTitle("Messages")
|
mt.SetTitle("Messages")
|
||||||
mt.SetTitleColor(tcell.GetColor(config.Theme.TitleColor))
|
mt.SetTitleColor(tcell.GetColor(cfg.Theme.TitleColor))
|
||||||
mt.SetTitleAlign(tview.AlignLeft)
|
mt.SetTitleAlign(tview.AlignLeft)
|
||||||
|
|
||||||
p := config.Theme.BorderPadding
|
p := cfg.Theme.BorderPadding
|
||||||
mt.SetBorder(config.Theme.Border)
|
mt.SetBorder(cfg.Theme.Border)
|
||||||
mt.SetBorderColor(tcell.GetColor(config.Theme.BorderColor))
|
mt.SetBorderColor(tcell.GetColor(cfg.Theme.BorderColor))
|
||||||
mt.SetBorderPadding(p[0], p[1], p[2], p[3])
|
mt.SetBorderPadding(p[0], p[1], p[2], p[3])
|
||||||
|
|
||||||
return mt
|
return mt
|
||||||
|
|
@ -74,7 +74,7 @@ func (mt *MessagesText) createMessage(m *discord.Message) error {
|
||||||
mt.buf.WriteByte(' ')
|
mt.buf.WriteByte(' ')
|
||||||
|
|
||||||
mt.buf.WriteByte('[')
|
mt.buf.WriteByte('[')
|
||||||
mt.buf.WriteString(config.Theme.MessagesText.AuthorColor)
|
mt.buf.WriteString(cfg.Theme.MessagesText.AuthorColor)
|
||||||
mt.buf.WriteByte(']')
|
mt.buf.WriteByte(']')
|
||||||
mt.buf.WriteString(m.ReferencedMessage.Author.Username)
|
mt.buf.WriteString(m.ReferencedMessage.Author.Username)
|
||||||
mt.buf.WriteString("[-] ")
|
mt.buf.WriteString("[-] ")
|
||||||
|
|
@ -98,12 +98,12 @@ func (mt *MessagesText) createMessage(m *discord.Message) error {
|
||||||
|
|
||||||
func (mt *MessagesText) createHeader(m *discord.Message) {
|
func (mt *MessagesText) createHeader(m *discord.Message) {
|
||||||
mt.buf.WriteByte('[')
|
mt.buf.WriteByte('[')
|
||||||
mt.buf.WriteString(config.Theme.MessagesText.AuthorColor)
|
mt.buf.WriteString(cfg.Theme.MessagesText.AuthorColor)
|
||||||
mt.buf.WriteByte(']')
|
mt.buf.WriteByte(']')
|
||||||
mt.buf.WriteString(m.Author.Username)
|
mt.buf.WriteString(m.Author.Username)
|
||||||
mt.buf.WriteString("[-] ")
|
mt.buf.WriteString("[-] ")
|
||||||
|
|
||||||
if config.Timestamps {
|
if cfg.Timestamps {
|
||||||
mt.buf.WriteString("[::d]")
|
mt.buf.WriteString("[::d]")
|
||||||
mt.buf.WriteString(m.Timestamp.Format(time.Kitchen))
|
mt.buf.WriteString(m.Timestamp.Format(time.Kitchen))
|
||||||
mt.buf.WriteString("[::-] ")
|
mt.buf.WriteString("[::-] ")
|
||||||
|
|
@ -127,31 +127,31 @@ func (mt *MessagesText) createFooter(m *discord.Message) {
|
||||||
|
|
||||||
func (mt *MessagesText) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
|
func (mt *MessagesText) onInputCapture(event *tcell.EventKey) *tcell.EventKey {
|
||||||
switch event.Name() {
|
switch event.Name() {
|
||||||
case config.Keys.MessagesText.CopyContent:
|
case cfg.Keys.MessagesText.CopyContent:
|
||||||
mt.copyContentAction()
|
mt.copyContentAction()
|
||||||
return nil
|
return nil
|
||||||
case config.Keys.MessagesText.Reply:
|
case cfg.Keys.MessagesText.Reply:
|
||||||
mt.replyAction(false)
|
mt.replyAction(false)
|
||||||
return nil
|
return nil
|
||||||
case config.Keys.MessagesText.ReplyMention:
|
case cfg.Keys.MessagesText.ReplyMention:
|
||||||
mt.replyAction(true)
|
mt.replyAction(true)
|
||||||
return nil
|
return nil
|
||||||
case config.Keys.MessagesText.SelectPrevious:
|
case cfg.Keys.MessagesText.SelectPrevious:
|
||||||
mt.selectPreviousAction()
|
mt.selectPreviousAction()
|
||||||
return nil
|
return nil
|
||||||
case config.Keys.MessagesText.SelectNext:
|
case cfg.Keys.MessagesText.SelectNext:
|
||||||
mt.selectNextAction()
|
mt.selectNextAction()
|
||||||
return nil
|
return nil
|
||||||
case config.Keys.MessagesText.SelectFirst:
|
case cfg.Keys.MessagesText.SelectFirst:
|
||||||
mt.selectFirstAction()
|
mt.selectFirstAction()
|
||||||
return nil
|
return nil
|
||||||
case config.Keys.MessagesText.SelectLast:
|
case cfg.Keys.MessagesText.SelectLast:
|
||||||
mt.selectLastAction()
|
mt.selectLastAction()
|
||||||
return nil
|
return nil
|
||||||
case config.Keys.MessagesText.SelectReply:
|
case cfg.Keys.MessagesText.SelectReply:
|
||||||
mt.selectReplyAction()
|
mt.selectReplyAction()
|
||||||
return nil
|
return nil
|
||||||
case config.Keys.Cancel:
|
case cfg.Keys.Cancel:
|
||||||
guildsTree.selectedChannel = nil
|
guildsTree.selectedChannel = nil
|
||||||
|
|
||||||
messagesText.reset()
|
messagesText.reset()
|
||||||
|
|
|
||||||
5
state.go
5
state.go
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/ayn2op/discordo/config"
|
||||||
"github.com/diamondburned/arikawa/v3/api"
|
"github.com/diamondburned/arikawa/v3/api"
|
||||||
"github.com/diamondburned/arikawa/v3/gateway"
|
"github.com/diamondburned/arikawa/v3/gateway"
|
||||||
"github.com/diamondburned/arikawa/v3/state"
|
"github.com/diamondburned/arikawa/v3/state"
|
||||||
|
|
@ -12,10 +13,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
api.UserAgent = fmt.Sprintf("%s/%s %s/%s", name, "0.1", "arikawa", "v3")
|
api.UserAgent = fmt.Sprintf("%s/%s %s/%s", config.Name, "0.1", "arikawa", "v3")
|
||||||
gateway.DefaultIdentity = gateway.IdentifyProperties{
|
gateway.DefaultIdentity = gateway.IdentifyProperties{
|
||||||
OS: runtime.GOOS,
|
OS: runtime.GOOS,
|
||||||
Browser: name,
|
Browser: config.Name,
|
||||||
Device: "",
|
Device: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue