From 3e9bed827319f5831923bdbd5cbe7dbf7ff9eb67 Mon Sep 17 00:00:00 2001 From: diamondburned Date: Sat, 13 Mar 2021 00:21:12 -0800 Subject: [PATCH] WIP lables repo --- .build.yml | 7 + cmd/plugin/main.go | 5 + discord.go | 18 +- go.mod | 6 +- go.sum | 212 +----------------- internal/discord/state/labels/container.go | 47 ++++ internal/discord/state/labels/format.go | 73 ++++++ internal/discord/state/labels/labels.go | 178 +++++++++++++++ internal/discord/state/labels/labels_wip.go | 52 +++++ internal/discord/state/state.go | 29 ++- .../authenticate/authenticator.go | 0 .../authenticate/discordlogin.go | 0 .../authenticate/login.go | 0 .../authenticate/token.go | 0 .../authenticate/totp.go | 0 .../category/category.go | 0 .../channel/channel.go | 0 .../channel/commander.go | 0 .../channel/commands/arguments.go | 0 .../channel/commands/command.go | 0 .../channel/commands/commands.go | 0 .../channel/message/action/actioner.go | 0 .../channel/message/backlog/backlogger.go | 0 .../channel/message/edit/editor.go | 0 .../channel/message/indicate/typing.go | 0 .../channel/message/indicate/unread.go | 10 + .../channel/message/memberlist/member.go | 14 +- .../channel/message/memberlist/memberlist.go | 0 .../channel/message/memberlist/section.go | 9 +- .../channel/message/message.go | 0 .../channel/message/nickname/nicknamer.go | 0 .../channel/message/send/complete/channel.go | 0 .../message/send/complete/completer.go | 0 .../channel/message/send/complete/emoji.go | 0 .../channel/message/send/complete/mention.go | 0 .../channel/message/send/sender.go | 0 .../channel/shared/channel.go | 45 ---- .../channel/typer/typer.go | 0 .../{discord => discord_old}/config/config.go | 0 .../{discord => discord_old}/folder/folder.go | 0 .../{discord => discord_old}/guild/guild.go | 8 +- .../message/author.go | 2 +- .../message/message.go | 0 .../private/hub/messages.go | 0 .../private/hub/sender.go | 0 .../private/hub/server.go | 0 .../private/private.go | 0 .../session/restorer.go | 0 .../session/session.go | 38 ++-- internal/discord_old/state/nonce/nonce.go | 90 ++++++++ internal/discord_old/state/state.go | 116 ++++++++++ internal/segments/avatar/avatar.go | 37 +++ internal/segments/mention/activity.go | 2 +- internal/segments/mention/channel.go | 46 ++++ internal/urlutils/urlutils.go | 5 +- logo.go | 20 -- 56 files changed, 746 insertions(+), 323 deletions(-) create mode 100644 .build.yml create mode 100644 cmd/plugin/main.go create mode 100644 internal/discord/state/labels/container.go create mode 100644 internal/discord/state/labels/format.go create mode 100644 internal/discord/state/labels/labels.go create mode 100644 internal/discord/state/labels/labels_wip.go rename internal/{discord => discord_old}/authenticate/authenticator.go (100%) rename internal/{discord => discord_old}/authenticate/discordlogin.go (100%) rename internal/{discord => discord_old}/authenticate/login.go (100%) rename internal/{discord => discord_old}/authenticate/token.go (100%) rename internal/{discord => discord_old}/authenticate/totp.go (100%) rename internal/{discord => discord_old}/category/category.go (100%) rename internal/{discord => discord_old}/channel/channel.go (100%) rename internal/{discord => discord_old}/channel/commander.go (100%) rename internal/{discord => discord_old}/channel/commands/arguments.go (100%) rename internal/{discord => discord_old}/channel/commands/command.go (100%) rename internal/{discord => discord_old}/channel/commands/commands.go (100%) rename internal/{discord => discord_old}/channel/message/action/actioner.go (100%) rename internal/{discord => discord_old}/channel/message/backlog/backlogger.go (100%) rename internal/{discord => discord_old}/channel/message/edit/editor.go (100%) rename internal/{discord => discord_old}/channel/message/indicate/typing.go (100%) rename internal/{discord => discord_old}/channel/message/indicate/unread.go (83%) rename internal/{discord => discord_old}/channel/message/memberlist/member.go (91%) rename internal/{discord => discord_old}/channel/message/memberlist/memberlist.go (100%) rename internal/{discord => discord_old}/channel/message/memberlist/section.go (93%) rename internal/{discord => discord_old}/channel/message/message.go (100%) rename internal/{discord => discord_old}/channel/message/nickname/nicknamer.go (100%) rename internal/{discord => discord_old}/channel/message/send/complete/channel.go (100%) rename internal/{discord => discord_old}/channel/message/send/complete/completer.go (100%) rename internal/{discord => discord_old}/channel/message/send/complete/emoji.go (100%) rename internal/{discord => discord_old}/channel/message/send/complete/mention.go (100%) rename internal/{discord => discord_old}/channel/message/send/sender.go (100%) rename internal/{discord => discord_old}/channel/shared/channel.go (52%) rename internal/{discord => discord_old}/channel/typer/typer.go (100%) rename internal/{discord => discord_old}/config/config.go (100%) rename internal/{discord => discord_old}/folder/folder.go (100%) rename internal/{discord => discord_old}/guild/guild.go (94%) rename internal/{discord => discord_old}/message/author.go (98%) rename internal/{discord => discord_old}/message/message.go (100%) rename internal/{discord => discord_old}/private/hub/messages.go (100%) rename internal/{discord => discord_old}/private/hub/sender.go (100%) rename internal/{discord => discord_old}/private/hub/server.go (100%) rename internal/{discord => discord_old}/private/private.go (100%) rename internal/{discord => discord_old}/session/restorer.go (100%) rename internal/{discord => discord_old}/session/session.go (91%) create mode 100644 internal/discord_old/state/nonce/nonce.go create mode 100644 internal/discord_old/state/state.go create mode 100644 internal/segments/avatar/avatar.go delete mode 100644 logo.go diff --git a/.build.yml b/.build.yml new file mode 100644 index 0000000..ab4febe --- /dev/null +++ b/.build.yml @@ -0,0 +1,7 @@ +image: alpine/edge +sources: + - https://github.com/diamondburned/cchat-discord +tasks: + - plugin: | + cd cchat-discord + go build -buildmode=plugin ./cmd/plugin diff --git a/cmd/plugin/main.go b/cmd/plugin/main.go new file mode 100644 index 0000000..68fa7e5 --- /dev/null +++ b/cmd/plugin/main.go @@ -0,0 +1,5 @@ +package main + +import _ "github.com/diamondburned/cchat-discord" + +func main() {} diff --git a/discord.go b/discord.go index 57fa102..b959be8 100644 --- a/discord.go +++ b/discord.go @@ -5,6 +5,7 @@ import ( "github.com/diamondburned/cchat-discord/internal/discord/authenticate" "github.com/diamondburned/cchat-discord/internal/discord/config" "github.com/diamondburned/cchat-discord/internal/discord/session" + "github.com/diamondburned/cchat-discord/internal/segments/avatar" "github.com/diamondburned/cchat/services" "github.com/diamondburned/cchat/text" "github.com/diamondburned/cchat/utils/empty" @@ -16,22 +17,29 @@ func init() { services.RegisterService(service) } +// Logo implements cchat.Iconer for the Discord logo. +var Logo = avatar.Segment{ + URL: "https://raw.githubusercontent.com/" + + "diamondburned/cchat-discord/himearikawa/discord_logo.png", + Size: 169, + Text: "Discord", +} + type Service struct { empty.Service } func (Service) Name() text.Rich { - return text.Rich{Content: "Discord"} + return text.Rich{ + Content: "Discord", + Segments: []text.Segment{Logo}, + } } func (Service) Authenticate() []cchat.Authenticator { return authenticate.FirstStageAuthenticators() } -func (Service) AsIconer() cchat.Iconer { - return Logo -} - func (Service) AsSessionRestorer() cchat.SessionRestorer { return session.Restorer } diff --git a/go.mod b/go.mod index e160729..7f23b31 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,13 @@ module github.com/diamondburned/cchat-discord go 1.14 require ( - github.com/diamondburned/arikawa/v2 v2.0.0-20210106050916-771591e5eb65 - github.com/diamondburned/cchat v0.3.17 + github.com/diamondburned/arikawa/v2 v2.0.5 + github.com/diamondburned/cchat v0.5.1 github.com/diamondburned/ningen/v2 v2.0.0-20210106052055-9da2a0102d49 github.com/dustin/go-humanize v1.0.0 github.com/go-test/deep v1.0.7 github.com/lithammer/fuzzysearch v1.1.1 github.com/pkg/errors v0.9.1 github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 - github.com/yuin/goldmark v1.1.30 + github.com/yuin/goldmark v1.3.2 ) diff --git a/go.sum b/go.sum index 3de0317..6b2a4af 100644 --- a/go.sum +++ b/go.sum @@ -24,200 +24,13 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/dave/jennifer v1.4.1/go.mod h1:7jEdnm+qBcxl8PC0zyp7vxcpSRnzXSt9r39tpTVGlwA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/diamondburned/arikawa v0.9.5 h1:P1ffsp+NHT22wWKYFVC8CdlGRLzPuUV9FcCBKOCJpCI= -github.com/diamondburned/arikawa v0.9.5/go.mod h1:nIhVIatzTQhPUa7NB8w4koG1RF9gYbpAr8Fj8sKq660= -github.com/diamondburned/arikawa v0.9.6 h1:6TpfTKa2btoVQGxojNqv8g2YC0tIc/tX5w/OCVZPF5Q= -github.com/diamondburned/arikawa v0.9.6/go.mod h1:nIhVIatzTQhPUa7NB8w4koG1RF9gYbpAr8Fj8sKq660= -github.com/diamondburned/arikawa v0.10.2 h1:xTsFWlWwGzFr8HD7tyv2jMRyserOR4yV5dhq/PZMPAA= -github.com/diamondburned/arikawa v0.10.2/go.mod h1:nIhVIatzTQhPUa7NB8w4koG1RF9gYbpAr8Fj8sKq660= -github.com/diamondburned/arikawa v0.10.5 h1:o5lBopooA+8cXlKZdct5qF0xztuZZ35phvQrwGS5vYM= -github.com/diamondburned/arikawa v0.10.5/go.mod h1:nIhVIatzTQhPUa7NB8w4koG1RF9gYbpAr8Fj8sKq660= -github.com/diamondburned/arikawa v0.12.4 h1:lhWJqcGkIIMiOYWdsoEuGlri2UbMkzMeh+VfuJPkXt4= -github.com/diamondburned/arikawa v0.12.4/go.mod h1:nIhVIatzTQhPUa7NB8w4koG1RF9gYbpAr8Fj8sKq660= -github.com/diamondburned/arikawa v1.1.4 h1:+fctDxzPCF84DFL+POBQgG4CuSpSepE09mdR3Y4vNRQ= -github.com/diamondburned/arikawa v1.1.4/go.mod h1:nIhVIatzTQhPUa7NB8w4koG1RF9gYbpAr8Fj8sKq660= -github.com/diamondburned/arikawa v1.1.6 h1:Y/ioTYipS2v/NXfcAEhCnMTzrpxDjWlkjLKKcX29n6o= -github.com/diamondburned/arikawa v1.1.6/go.mod h1:nIhVIatzTQhPUa7NB8w4koG1RF9gYbpAr8Fj8sKq660= -github.com/diamondburned/arikawa v1.2.0 h1:3dFmpk/G4UwO+Kto0tXd5AbaCKC9KH2ZfnA8UOdzQ1k= -github.com/diamondburned/arikawa v1.2.0/go.mod h1:nIhVIatzTQhPUa7NB8w4koG1RF9gYbpAr8Fj8sKq660= -github.com/diamondburned/arikawa v1.3.0 h1:up5q5Ya/QbiFqhMejvl+c03YdsgzkzspsJOWW30A2lk= -github.com/diamondburned/arikawa v1.3.0/go.mod h1:nIhVIatzTQhPUa7NB8w4koG1RF9gYbpAr8Fj8sKq660= -github.com/diamondburned/arikawa v1.3.2 h1:ftWgP95IJGXNvCvtO5x0QBYsnFSnIBY0SvDdGoC3ILA= -github.com/diamondburned/arikawa v1.3.2/go.mod h1:nIhVIatzTQhPUa7NB8w4koG1RF9gYbpAr8Fj8sKq660= -github.com/diamondburned/arikawa v1.3.6 h1:DhxWDO4fyXAZ4VFrWdJOqiiJKJRpkrehGJwPtZ2eos0= -github.com/diamondburned/arikawa v1.3.6/go.mod h1:nIhVIatzTQhPUa7NB8w4koG1RF9gYbpAr8Fj8sKq660= -github.com/diamondburned/arikawa/v2 v2.0.0-20201208195035-9911a3d6627a/go.mod h1:e+lhS20ni2luFEU06Pc8paCxgZL99/RZb77dOC82CF0= -github.com/diamondburned/arikawa/v2 v2.0.0-20201218230021-9df396bb7f14 h1:2+j49uXPC44gEFstt0hlY17Wz88HU7DXgOmQmgIf28E= -github.com/diamondburned/arikawa/v2 v2.0.0-20201218230021-9df396bb7f14/go.mod h1:e+lhS20ni2luFEU06Pc8paCxgZL99/RZb77dOC82CF0= -github.com/diamondburned/arikawa/v2 v2.0.0-20201219061804-88911a7d1117 h1:n769tNSjYU2EDCkM3PBLTaB0LQwN9Sr3Rab9KXVxhoc= -github.com/diamondburned/arikawa/v2 v2.0.0-20201219061804-88911a7d1117/go.mod h1:e+lhS20ni2luFEU06Pc8paCxgZL99/RZb77dOC82CF0= -github.com/diamondburned/arikawa/v2 v2.0.0-20201219063311-c9dd51aeb654 h1:z4/LcUUQ/B7l3+G1fh16/ByW206/oueKLANdygetEyA= -github.com/diamondburned/arikawa/v2 v2.0.0-20201219063311-c9dd51aeb654/go.mod h1:e+lhS20ni2luFEU06Pc8paCxgZL99/RZb77dOC82CF0= -github.com/diamondburned/arikawa/v2 v2.0.0-20201219065126-f11edb7260b2 h1:73ukkYNYZztR3wUXzeyza6AG4zBZjA8ER6qO0QGZPPA= -github.com/diamondburned/arikawa/v2 v2.0.0-20201219065126-f11edb7260b2/go.mod h1:e+lhS20ni2luFEU06Pc8paCxgZL99/RZb77dOC82CF0= -github.com/diamondburned/arikawa/v2 v2.0.0-20201219075756-36c2f166becd h1:HCaw0YrlQWKTao7QE6s8tjYImZEpH7Lad85bnYel1V0= -github.com/diamondburned/arikawa/v2 v2.0.0-20201219075756-36c2f166becd/go.mod h1:/vapSS3yfYRAt5hhgI6JiPkca+wKhgi0MdanT1dBBQY= -github.com/diamondburned/arikawa/v2 v2.0.0-20201220000828-3e2814748f9a h1:aA8K3+JfXdJPcK9Ms4WmHLGp+qnKT0VuNWOUZUP9YpY= -github.com/diamondburned/arikawa/v2 v2.0.0-20201220000828-3e2814748f9a/go.mod h1:e+lhS20ni2luFEU06Pc8paCxgZL99/RZb77dOC82CF0= -github.com/diamondburned/arikawa/v2 v2.0.0-20201220032235-088b30430377 h1:71BLnECSl0/Ns7iZmEm7MpE5+qSuWw/BQBQY2XCUmVc= -github.com/diamondburned/arikawa/v2 v2.0.0-20201220032235-088b30430377/go.mod h1:e+lhS20ni2luFEU06Pc8paCxgZL99/RZb77dOC82CF0= -github.com/diamondburned/arikawa/v2 v2.0.0-20201227001310-f3f075b27f44 h1:i6Jec7bvVY8NhwW3L0SlpfWM6r2p2i67XuhiOEzkfwI= -github.com/diamondburned/arikawa/v2 v2.0.0-20201227001310-f3f075b27f44/go.mod h1:e+lhS20ni2luFEU06Pc8paCxgZL99/RZb77dOC82CF0= -github.com/diamondburned/arikawa/v2 v2.0.0-20210101074829-c6d8c741e883/go.mod h1:e+lhS20ni2luFEU06Pc8paCxgZL99/RZb77dOC82CF0= -github.com/diamondburned/arikawa/v2 v2.0.0-20210101083335-169b36126239 h1:ogL6/TJJecNYkvREJa+nHZ326b+QjHN/eLXMUtiyz/A= github.com/diamondburned/arikawa/v2 v2.0.0-20210101083335-169b36126239/go.mod h1:e+lhS20ni2luFEU06Pc8paCxgZL99/RZb77dOC82CF0= -github.com/diamondburned/arikawa/v2 v2.0.0-20210105213913-8a213759164c h1:6n1EqFEPZbtm0pj8vtS7VzZuWvg7v04UL9hAcpK3lNk= -github.com/diamondburned/arikawa/v2 v2.0.0-20210105213913-8a213759164c/go.mod h1:e+lhS20ni2luFEU06Pc8paCxgZL99/RZb77dOC82CF0= -github.com/diamondburned/arikawa/v2 v2.0.0-20210106050916-771591e5eb65 h1:foJMpT+BAoASVzDj9WDxNp6/OxnWnQ/uUHk2DXARP/Y= -github.com/diamondburned/arikawa/v2 v2.0.0-20210106050916-771591e5eb65/go.mod h1:e+lhS20ni2luFEU06Pc8paCxgZL99/RZb77dOC82CF0= -github.com/diamondburned/cchat v0.0.34 h1:BGiVxMRA9dmW3rLilIldBvjVan7eTTpaWCCfX9IKBYU= -github.com/diamondburned/cchat v0.0.34/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.0.35 h1:WiMGl8BQJgbP9E4xRxgLGlqUsHpTcJgDKDt8/6a7lBk= -github.com/diamondburned/cchat v0.0.35/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.0.36 h1:fOD84RV7EUCjoOSogX/Hu5pe4tzHk3Qh7taKaojIAGc= -github.com/diamondburned/cchat v0.0.36/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.0.37 h1:yGz9yls5Lb/vLkU/DU53GjC80WOqoRe229DXsu5mtaY= -github.com/diamondburned/cchat v0.0.37/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.0.39 h1:Hxd7swmAIECm0MBd5wb1IFvreChwDFwnAshqgAstWGA= -github.com/diamondburned/cchat v0.0.39/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.0.40 h1:38gPyJnnDoNDHrXcV8Qchfv3y6jlS3Fzz/6FY0BPH6I= -github.com/diamondburned/cchat v0.0.40/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.0.41 h1:6y32s2wWTiDw4hWN/Gna6ay3uUrRAW5V8Cj0/xLKovw= -github.com/diamondburned/cchat v0.0.41/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.0.42 h1:FVMLy9hOTxKju8OWDBIStrekbgTHCaH8+GVnV4LOByg= -github.com/diamondburned/cchat v0.0.42/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.0.43 h1:HetAujSaUSdnQgAUZgprNLARjf/MSWXpCfWdvX2wOCU= -github.com/diamondburned/cchat v0.0.43/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.0.44 h1:NmXw4bU3nCPxxKYK6K5LjRjNMp15uXfcKVEt1KTA+SI= -github.com/diamondburned/cchat v0.0.44/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.0.45 h1:HMVSKx1h6lh2OenWaBTvMSK531hWaXAW7I0tKZepYug= -github.com/diamondburned/cchat v0.0.45/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.0.46 h1:fzm2XA9uGasX0uaic1AFfUMGA53PlO+GGmkYbx49A5k= -github.com/diamondburned/cchat v0.0.46/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.0.47 h1:qU2TNeXlqru8za4qAgMPWTw6k8HGGOyic08GPPZJ6r8= -github.com/diamondburned/cchat v0.0.47/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.0.48 h1:MAzGzKY20JBh/LnirOZVPwbMq07xfqu4Lb4XsV9/sXQ= -github.com/diamondburned/cchat v0.0.48/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.0.49 h1:zP6QvjdRU3UqDZt3rEqjkR/5M68XRVms7htHfE9tLOc= -github.com/diamondburned/cchat v0.0.49/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.1.0 h1:TJiMdKFd1mijQOO1KSp35PJMvW+jiif5Go4QmoIhH9I= -github.com/diamondburned/cchat v0.1.0/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.1.1 h1:tx130Vx0bvLQvQxyOJbhvPJ85qoOOs5ZhJVXDDIh7eU= -github.com/diamondburned/cchat v0.1.1/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.1.2 h1:/9/xtHeifirMHiHsf/acL23UPZuS2YdzqWMMR5+sUPU= -github.com/diamondburned/cchat v0.1.2/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.1.3 h1:4xq8Tc+U0OUf2Vr6s8Igb5iADmeJ9oM1Db+M6zF/PDQ= -github.com/diamondburned/cchat v0.1.3/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= -github.com/diamondburned/cchat v0.2.11 h1:w4c/6t02htGtVj6yIjznecOGMlkcj0TmmLy+K48gHeM= -github.com/diamondburned/cchat v0.2.11/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= -github.com/diamondburned/cchat v0.2.12 h1:R4wrBdhELMfhv2Kn3xL/H3ci8UcLXzFRPq1IrY4+js4= -github.com/diamondburned/cchat v0.2.12/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= -github.com/diamondburned/cchat v0.3.0 h1:xC8Y+/nwsVhc4a7i7R+4n0JczOnFSA2Gmj6Bz/pZ5zo= -github.com/diamondburned/cchat v0.3.0/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= -github.com/diamondburned/cchat v0.3.1 h1:7NbVjT50dmLxcHPm+eDFF5jcaZw3t/9IdSEkZ/md1Rg= -github.com/diamondburned/cchat v0.3.1/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= -github.com/diamondburned/cchat v0.3.4 h1:9JvcIrmy00cZMc2acfTSARTEzdtrSOqeIz/iYjHOgl4= -github.com/diamondburned/cchat v0.3.4/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= -github.com/diamondburned/cchat v0.3.5 h1:6rweOEmFLJUlrC98sLFwUUp9H+GWhVgtEqW5suF+J/o= -github.com/diamondburned/cchat v0.3.5/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= -github.com/diamondburned/cchat v0.3.6 h1:at9bnxlABa3TGscra/cRq/ASsmJh6GCdQ0vnCD91tDk= -github.com/diamondburned/cchat v0.3.6/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= -github.com/diamondburned/cchat v0.3.7 h1:0t3FkbzC/pBRAR3w0uYznJ+7dYqcR1M48a9wgz4JkIg= -github.com/diamondburned/cchat v0.3.7/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= -github.com/diamondburned/cchat v0.3.8 h1:vgFe8giVfwsAO+WpTYsTDIXvRUN48osVPNu0pZNvPEk= -github.com/diamondburned/cchat v0.3.8/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= -github.com/diamondburned/cchat v0.3.11 h1:C1f9Tp7Kz3t+T1SlepL1RS7b/kACAKWAIZXAgJEpCHg= -github.com/diamondburned/cchat v0.3.11/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= -github.com/diamondburned/cchat v0.3.12 h1:mew54lsDrwrJs4U2FtdbNFl/wAZcueIgZCsImHQzVL4= -github.com/diamondburned/cchat v0.3.12/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= -github.com/diamondburned/cchat v0.3.13 h1:qSAo8FJDvEi9o8kLQJ5Mbo4jrfb+sd1Muo1sx8ruBo8= -github.com/diamondburned/cchat v0.3.13/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= -github.com/diamondburned/cchat v0.3.14 h1:nDr9DJ1EW3kab4gieE+DLhpvHRws+umWpw5XrOmlNyc= -github.com/diamondburned/cchat v0.3.14/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= -github.com/diamondburned/cchat v0.3.15 h1:BJf8ZiRtDWTGMtQ3QqjNU0H+784WSrkJEpFGkKY5gEw= -github.com/diamondburned/cchat v0.3.15/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= -github.com/diamondburned/cchat v0.3.16 h1:vRF8BeypyQ6yr0wK/odGStrmrbB+1WkNcjIwP+SMZeo= -github.com/diamondburned/cchat v0.3.16/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= -github.com/diamondburned/cchat v0.3.17 h1:pGwas8Y0SBU7yg4EQ/MvrbqZhrnRhPBYm1AiRsL147s= -github.com/diamondburned/cchat v0.3.17/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= -github.com/diamondburned/ningen v0.1.1-0.20200621014632-6babb812b249 h1:yP7kJ+xCGpDz6XbcfACJcju4SH1XDPwlrvbofz3lP8I= -github.com/diamondburned/ningen v0.1.1-0.20200621014632-6babb812b249/go.mod h1:xW9hpBZsGi8KpAh10TyP+YQlYBo+Xc+2w4TR6N0951A= -github.com/diamondburned/ningen v0.1.1-0.20200708085949-b64e350f3b8c h1:3h/kyk6HplYZF3zLi106itjYJWjbuMK/twijeGLEy2M= -github.com/diamondburned/ningen v0.1.1-0.20200708085949-b64e350f3b8c/go.mod h1:FNezDLQIhoDS+RkXLSQ7dJNrt6BW/nVl1krzDgWMQwg= -github.com/diamondburned/ningen v0.1.1-0.20200708090333-227e90d19851 h1:xf1aLPnwK/Yn2z7dBIgQROSVOEc2wtivgnnwBItdEVM= -github.com/diamondburned/ningen v0.1.1-0.20200708090333-227e90d19851/go.mod h1:FNezDLQIhoDS+RkXLSQ7dJNrt6BW/nVl1krzDgWMQwg= -github.com/diamondburned/ningen v0.1.1-0.20200708211706-57c712372ede h1:qRmfQCOS+ZnH4G0+8O09PUx3HQTdQwzsDoo1ucTgm2E= -github.com/diamondburned/ningen v0.1.1-0.20200708211706-57c712372ede/go.mod h1:FNezDLQIhoDS+RkXLSQ7dJNrt6BW/nVl1krzDgWMQwg= -github.com/diamondburned/ningen v0.1.1-0.20200711215126-d4b8a17e818d h1:XgG/KRbAwu8v2/YZWimjXo0dgdD69E38ollCfbFtU7s= -github.com/diamondburned/ningen v0.1.1-0.20200711215126-d4b8a17e818d/go.mod h1:NVneOJDUDEIC3cnyeh2vpeAPVtBdC2Kcy+uwDy4o2qk= -github.com/diamondburned/ningen v0.1.1-0.20200712031630-349ee2c3f01c h1:CpYhIGiRzee7Jm0H4c0fLvRe/08QitDNo8KHYtrOmFE= -github.com/diamondburned/ningen v0.1.1-0.20200712031630-349ee2c3f01c/go.mod h1:NVneOJDUDEIC3cnyeh2vpeAPVtBdC2Kcy+uwDy4o2qk= -github.com/diamondburned/ningen v0.1.1-0.20200715015332-cb3c7378b3c8 h1:0IxrMc4bh/sp2e0dnagKgM72i9CfCoo1FygyglJcXao= -github.com/diamondburned/ningen v0.1.1-0.20200715015332-cb3c7378b3c8/go.mod h1:SKPY3387RHCbMrnefex9D+zlrA2yB+LCtaaQAgatAuc= -github.com/diamondburned/ningen v0.1.1-0.20200715034121-61de7138eb56 h1:DAk3bEwJZycjfZu4OXDYrR/nmpy3ZS/dfUF0rskfVj0= -github.com/diamondburned/ningen v0.1.1-0.20200715034121-61de7138eb56/go.mod h1:SKPY3387RHCbMrnefex9D+zlrA2yB+LCtaaQAgatAuc= -github.com/diamondburned/ningen v0.1.1-0.20200715040340-2395a0dbd0fa h1:ntHcz6GNzxn3TovtYZVwOBvL3xn7Iq1luaV/KEIEXrk= -github.com/diamondburned/ningen v0.1.1-0.20200715040340-2395a0dbd0fa/go.mod h1:SKPY3387RHCbMrnefex9D+zlrA2yB+LCtaaQAgatAuc= -github.com/diamondburned/ningen v0.1.1-0.20200716061206-b8f3ae446253 h1:Jpdv9ZnViZct1aSYhE1NZRIkmIodey1OeeqdCSoAu40= -github.com/diamondburned/ningen v0.1.1-0.20200716061206-b8f3ae446253/go.mod h1:Sunqp1b9Tc0+DtWKslhf83Zepgj/TELB6h8J9HZCPqQ= -github.com/diamondburned/ningen v0.1.1-0.20200717013108-297a3bdf84dc h1:YZ84Kdlv91tdcyLfGfQ+LG9kWZN8dTKIic0KlEtGV0U= -github.com/diamondburned/ningen v0.1.1-0.20200717013108-297a3bdf84dc/go.mod h1:Sunqp1b9Tc0+DtWKslhf83Zepgj/TELB6h8J9HZCPqQ= -github.com/diamondburned/ningen v0.1.1-0.20200717070406-6dc482b394c0 h1:DkzeHISwAeEYIBiynYkxOz4eNuT2DfTjF93DZjyMLmc= -github.com/diamondburned/ningen v0.1.1-0.20200717070406-6dc482b394c0/go.mod h1:Sunqp1b9Tc0+DtWKslhf83Zepgj/TELB6h8J9HZCPqQ= -github.com/diamondburned/ningen v0.1.1-0.20200717072304-e483f86c08e6 h1:YN0cj0aOCa+tKmx0aD5qsbSYaIJnyrA0/+eygMKP+/w= -github.com/diamondburned/ningen v0.1.1-0.20200717072304-e483f86c08e6/go.mod h1:Sunqp1b9Tc0+DtWKslhf83Zepgj/TELB6h8J9HZCPqQ= -github.com/diamondburned/ningen v0.1.1-0.20200814175234-6d546fac7724 h1:889IwdXZdIJlwlARBHZ2xxZ05Qfjd0yrVnpivyjfxTo= -github.com/diamondburned/ningen v0.1.1-0.20200814175234-6d546fac7724/go.mod h1:Lcgkgu/QfaTqnBQqYb2LlnhM9aR509uEt07y61UQNGg= -github.com/diamondburned/ningen v0.1.1-0.20200814183847-6722b606d3e1 h1:t3UPOrtdabeRqlHN+KIIht9MI6BdyCil7r5A8kz9hq4= -github.com/diamondburned/ningen v0.1.1-0.20200814183847-6722b606d3e1/go.mod h1:Lcgkgu/QfaTqnBQqYb2LlnhM9aR509uEt07y61UQNGg= -github.com/diamondburned/ningen v0.1.1-0.20200815001935-477d5b58b555 h1:NGxGSTnUWlNL8rUlU6hKxaOCbpM8Jrgwh/51pBu28UQ= -github.com/diamondburned/ningen v0.1.1-0.20200815001935-477d5b58b555/go.mod h1:Lcgkgu/QfaTqnBQqYb2LlnhM9aR509uEt07y61UQNGg= -github.com/diamondburned/ningen v0.1.1-0.20200815192814-e630cb3debe2 h1:9GZLZhVlqqTSwKX9CTf+fmj+/kpF8B1p+uYLdaUAHVI= -github.com/diamondburned/ningen v0.1.1-0.20200815192814-e630cb3debe2/go.mod h1:PIsJWdDhjgN9OiR+qrDPD8KGQ8UyFuRVrgs3Ewu6a3c= -github.com/diamondburned/ningen v0.1.1-0.20200815214034-638820c48066 h1:TOLTl0zLJ+idYB7i6C4oGfmVF1Y0AFoNfVQWU3hmc4A= -github.com/diamondburned/ningen v0.1.1-0.20200815214034-638820c48066/go.mod h1:PIsJWdDhjgN9OiR+qrDPD8KGQ8UyFuRVrgs3Ewu6a3c= -github.com/diamondburned/ningen v0.1.1-0.20200816035718-70361fb41b6f h1:Wzns8I0VjMrcsH7N5lqHKTRkgBt2aCwx+7wAxvSFGjU= -github.com/diamondburned/ningen v0.1.1-0.20200816035718-70361fb41b6f/go.mod h1:PIsJWdDhjgN9OiR+qrDPD8KGQ8UyFuRVrgs3Ewu6a3c= -github.com/diamondburned/ningen v0.1.1-0.20200816040753-9595e584e6bc h1:pxFVcg7J7D9hYVVReXLdJurgv4uAo1a6jNHcYpdeZsE= -github.com/diamondburned/ningen v0.1.1-0.20200816040753-9595e584e6bc/go.mod h1:PIsJWdDhjgN9OiR+qrDPD8KGQ8UyFuRVrgs3Ewu6a3c= -github.com/diamondburned/ningen v0.1.1-0.20200816040956-857988325ce0 h1:c3G8NjcS7JZvQvY549r993C0P1ltEf7sFpfRD21HFhk= -github.com/diamondburned/ningen v0.1.1-0.20200816040956-857988325ce0/go.mod h1:PIsJWdDhjgN9OiR+qrDPD8KGQ8UyFuRVrgs3Ewu6a3c= -github.com/diamondburned/ningen v0.1.1-0.20200816192443-0b6a02d498d2 h1:PodX8lfv7ZffUHUsaQUdIjZ50ONY8uCCXXUL7yzoSMQ= -github.com/diamondburned/ningen v0.1.1-0.20200816192443-0b6a02d498d2/go.mod h1:PIsJWdDhjgN9OiR+qrDPD8KGQ8UyFuRVrgs3Ewu6a3c= -github.com/diamondburned/ningen v0.1.1-0.20200818185419-0d3e89f25ee1 h1:ahr5xvEzrBIpRc3mrdihCd0iCUEawPixulbJk6MVAao= -github.com/diamondburned/ningen v0.1.1-0.20200818185419-0d3e89f25ee1/go.mod h1:vglus/9ENunGHSAZxzilq1ApNQMDtYBSG8V4r/vDY1o= -github.com/diamondburned/ningen v0.1.1-0.20200820222120-e86664f3f084 h1:nZiBsM/9Dw9Uxw8iBu3GO5m+BlYmqa3kVIP6LcKJPKQ= -github.com/diamondburned/ningen v0.1.1-0.20200820222120-e86664f3f084/go.mod h1:aXm69MB+Qu04OjBiixQw28zRijDc49vruMJMaHZ2c0Q= -github.com/diamondburned/ningen v0.1.1-0.20200820222640-35796f938a58 h1:sQvq5DgmX8hSyiP4HVZfOhlFY/PgvQWu6USAy04i1Yc= -github.com/diamondburned/ningen v0.1.1-0.20200820222640-35796f938a58/go.mod h1:aXm69MB+Qu04OjBiixQw28zRijDc49vruMJMaHZ2c0Q= -github.com/diamondburned/ningen v0.2.1-0.20201023061015-ce64ffb0bb12 h1:hcabAq2jPmEhrfSRrl2hHkpQXtPTIh7L58fvCxBO/C4= -github.com/diamondburned/ningen v0.2.1-0.20201023061015-ce64ffb0bb12/go.mod h1:TcvJV0bK4bp7t+7m29/Tz9dCqgA0sJBKM/Igt0WkvT4= -github.com/diamondburned/ningen v1.0.0 h1:fr+7oDWA0Db73CuVeLY8SScWdW6ft/aWwkULXD0flKw= -github.com/diamondburned/ningen v1.0.0/go.mod h1:TcvJV0bK4bp7t+7m29/Tz9dCqgA0sJBKM/Igt0WkvT4= -github.com/diamondburned/ningen/v2 v2.0.0-20201210080809-a14408097980 h1:g/ndgdW9sdL2KEIORhbRafnwreDksZVTPQtRF3SgriU= -github.com/diamondburned/ningen/v2 v2.0.0-20201210080809-a14408097980/go.mod h1:ub/rJpU3cD1Izpa1g+JDuzmtbfP/grV2ZSK5GzL94nc= -github.com/diamondburned/ningen/v2 v2.0.0-20201219070301-15610044db9a h1:w8CWPYiwH9p2XGlHHeTqRWx7e8CJJLN8i4orAkOa27Y= -github.com/diamondburned/ningen/v2 v2.0.0-20201219070301-15610044db9a/go.mod h1:Pw4ZPQmZUonCytlKhHgan98CZeCQ4AWh0DWqvnhsuNE= -github.com/diamondburned/ningen/v2 v2.0.0-20201219225720-58beeea47f6d h1:2DWG8srhOrOJDffCk37L66p5yLJssY5wGdt7OPd7Y68= -github.com/diamondburned/ningen/v2 v2.0.0-20201219225720-58beeea47f6d/go.mod h1:9ZWVTlDzwR0/tGFrBF6iiQV8qPXlJSKsIqRIRyXtDDU= -github.com/diamondburned/ningen/v2 v2.0.0-20201219233304-7023c9c95229 h1:Or3Qy+gwKeIECMv2S9rWsF3xRy90kpHKgCgmixG7ybE= -github.com/diamondburned/ningen/v2 v2.0.0-20201219233304-7023c9c95229/go.mod h1:9ZWVTlDzwR0/tGFrBF6iiQV8qPXlJSKsIqRIRyXtDDU= -github.com/diamondburned/ningen/v2 v2.0.0-20201219234158-543154247f29 h1:rwyTYHlPHSO8dAAqgeSIaXLQLPlX1NC8Ebd1py1JTVg= -github.com/diamondburned/ningen/v2 v2.0.0-20201219234158-543154247f29/go.mod h1:9ZWVTlDzwR0/tGFrBF6iiQV8qPXlJSKsIqRIRyXtDDU= -github.com/diamondburned/ningen/v2 v2.0.0-20201219235002-2c75ebf8f5fc h1:cV3WgIGTNeh8MFqRRgcxjgjTLBrU/1h24jVEeA2qySg= -github.com/diamondburned/ningen/v2 v2.0.0-20201219235002-2c75ebf8f5fc/go.mod h1:9ZWVTlDzwR0/tGFrBF6iiQV8qPXlJSKsIqRIRyXtDDU= -github.com/diamondburned/ningen/v2 v2.0.0-20201220032656-1096439b9379 h1:gcmMWHBtgJD+HVDQqSoy1C5L4g1CVSYadwrdeYgVL30= -github.com/diamondburned/ningen/v2 v2.0.0-20201220032656-1096439b9379/go.mod h1:2ZjyeHqO9jCdlfmJhhVhk8eCumx418n39uVaC/LgEgY= -github.com/diamondburned/ningen/v2 v2.0.0-20201220054153-c69c4f7057b4 h1:qzh5ghfgvUllilOhkrGP29IGQT6DGfcc3lhk9uSA6nU= -github.com/diamondburned/ningen/v2 v2.0.0-20201220054153-c69c4f7057b4/go.mod h1:2ZjyeHqO9jCdlfmJhhVhk8eCumx418n39uVaC/LgEgY= -github.com/diamondburned/ningen/v2 v2.0.0-20201227020621-a4e33db11d3c h1:IWn/N54JkJz7PVgmAt7cWXLky9wY0UjXzznNoWLIFgA= -github.com/diamondburned/ningen/v2 v2.0.0-20201227020621-a4e33db11d3c/go.mod h1:zQkAo1RT4ru4HW6B5T4IRO2pee8ITzTUA2Y7XNpgjqo= -github.com/diamondburned/ningen/v2 v2.0.0-20201227034843-dc1d22fc28e4 h1:ptIpcyB/FIBM5viKLVXuBiE1utqBcH4S3l5kUQrsL9Q= -github.com/diamondburned/ningen/v2 v2.0.0-20201227034843-dc1d22fc28e4/go.mod h1:zQkAo1RT4ru4HW6B5T4IRO2pee8ITzTUA2Y7XNpgjqo= -github.com/diamondburned/ningen/v2 v2.0.0-20210101084041-d9a5058b63b5 h1:GKqBXunV2AC/owpkiaFng1wPxgxE76sQ8HEPAHGj29o= -github.com/diamondburned/ningen/v2 v2.0.0-20210101084041-d9a5058b63b5/go.mod h1:WRQCUX/dTH4OPEy3JANLA5D6fbumzp5zk03uSUAZppA= -github.com/diamondburned/ningen/v2 v2.0.0-20210106043942-5e3332344ab6 h1:YTvBovyUXatZbU/+gdLJPmBvisLbJkLQe6pq4BFvcUQ= -github.com/diamondburned/ningen/v2 v2.0.0-20210106043942-5e3332344ab6/go.mod h1:WRQCUX/dTH4OPEy3JANLA5D6fbumzp5zk03uSUAZppA= +github.com/diamondburned/arikawa/v2 v2.0.5 h1:X/jPfeEFj/Hzk26kudNJqtVkQb3vnh3tAjEF1mY7GK8= +github.com/diamondburned/arikawa/v2 v2.0.5/go.mod h1:e+lhS20ni2luFEU06Pc8paCxgZL99/RZb77dOC82CF0= +github.com/diamondburned/cchat v0.5.0 h1:+3+Rc0GnumLUJ9+GyJPRt6SVuH9vVp7B6hrHf8HsDKI= +github.com/diamondburned/cchat v0.5.0/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= +github.com/diamondburned/cchat v0.5.1 h1:Ju34nv0tbLaWfm+LtyUA4TPlX7206eXo6LM+3JzosQo= +github.com/diamondburned/cchat v0.5.1/go.mod h1:IlMtF+XIvAJh0GL/2yFdf0/34w+Hdy5A1GgvSwAXtQI= github.com/diamondburned/ningen/v2 v2.0.0-20210106052055-9da2a0102d49 h1:wfj+fvDJLUC+xkRmVA/ZE9nmeSqFy4fbyIi3hBHgn/U= github.com/diamondburned/ningen/v2 v2.0.0-20210106052055-9da2a0102d49/go.mod h1:WRQCUX/dTH4OPEy3JANLA5D6fbumzp5zk03uSUAZppA= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= @@ -226,8 +39,7 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-test/deep v1.0.6 h1:UHSEyLZUwX9Qoi99vVwvewiMC8mM2bf7XEM2nqvzEn8= -github.com/go-test/deep v1.0.6/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= +github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -254,8 +66,6 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY= -github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc= github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= @@ -265,8 +75,6 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/kawasin73/umutex v0.2.1 h1:Onkzz3LKs1HThskVwdhhBocqdRQqwCZ03quDJzuPzPo= -github.com/kawasin73/umutex v0.2.1/go.mod h1:A02N2muKVFMvFlp5c+hBycgdH964YtieGs+7mYB16NU= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -285,8 +93,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/twmb/murmur3 v1.1.3 h1:D83U0XYKcHRYwYIpBKf3Pks91Z0Byda/9SJ8B6EMRcA= github.com/twmb/murmur3 v1.1.3/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= -github.com/yuin/goldmark v1.1.30 h1:j4d4Lw3zqZelDhBksEo3BnWg9xhXRQGJPPSL6OApZjI= github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.2 h1:YjHC5TgyMmHpicTgEqDN0Q96Xo8K6tLXPnmNOHXCgs0= +github.com/yuin/goldmark v1.3.2/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -297,7 +106,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -370,8 +178,6 @@ golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/internal/discord/state/labels/container.go b/internal/discord/state/labels/container.go new file mode 100644 index 0000000..17843b8 --- /dev/null +++ b/internal/discord/state/labels/container.go @@ -0,0 +1,47 @@ +package labels + +import ( + "github.com/diamondburned/arikawa/v2/discord" + "github.com/diamondburned/cchat" +) + +type labelContainers struct { + guilds map[discord.GuildID]guildContainer + channels map[discord.ChannelID]labelerList + // presences map[discord.UserID]labelerList +} + +func newLabelContainers() labelContainers { + return labelContainers{ + guilds: map[discord.GuildID]guildContainer{}, + channels: map[discord.ChannelID]labelerList{}, + // presences: map[discord.UserID]labelerList{}, + } +} + +type guildContainer struct { + guild labelerList // optional + members map[discord.UserID]labelerList // optional +} + +// IsEmpty returns true if the container no longer holds any labeler. +func (gcont guildContainer) IsEmpty() bool { + return len(gcont.guild) == 0 && len(gcont.members) == 0 +} + +// labelerList is a list of labelers. +type labelerList map[cchat.LabelContainer]struct{} + +// Add adds the given labeler. If the map is nil, then a new one is created. +func (llist *labelerList) Add(l cchat.LabelContainer) { + if *llist == nil { + *llist = make(map[cchat.LabelContainer]struct{}, 1) + } + + (*llist)[l] = struct{}{} +} + +// Remove removes the given labeler. +func (llist labelerList) Remove(l cchat.LabelContainer) { + delete(llist, l) +} diff --git a/internal/discord/state/labels/format.go b/internal/discord/state/labels/format.go new file mode 100644 index 0000000..b5acd48 --- /dev/null +++ b/internal/discord/state/labels/format.go @@ -0,0 +1,73 @@ +package labels + +import ( + "github.com/diamondburned/arikawa/v2/discord" + "github.com/diamondburned/cchat-discord/internal/segments/avatar" + "github.com/diamondburned/cchat-discord/internal/segments/colored" + "github.com/diamondburned/cchat-discord/internal/segments/mention" + "github.com/diamondburned/cchat-discord/internal/segments/segutil" + "github.com/diamondburned/cchat-discord/internal/urlutils" + "github.com/diamondburned/cchat/text" + "github.com/diamondburned/ningen/v2" +) + +// TODO: these functions should probably be its own package. + +func labelGuild(s *ningen.State, guildID discord.GuildID) text.Rich { + g, err := s.Cabinet.Guild(guildID) + if err != nil { + return text.Plain(guildID.String()) + } + + return text.Rich{ + Content: g.Name, + Segments: []text.Segment{ + avatar.Segment{ + URL: urlutils.AvatarURL(g.IconURL()), + Size: urlutils.AvatarSize, + Text: g.Name, + }, + }, + } +} + +func labelMember(s *ningen.State, g discord.GuildID, u discord.UserID) text.Rich { + m, err := s.Cabinet.Member(g, u) + if err != nil { + s.MemberState.RequestMember(g, u) + return text.Plain(u.Mention()) + } + + user := mention.NewUser(m.User) + user.WithMember(*m) + user.WithGuildID(g) + user.WithState(s) + user.Prefetch() + + rich := text.Rich{Content: user.DisplayName()} + rich.Segments = []text.Segment{ + mention.NewSegment(0, len(rich.Content), user), + } + + if m.User.Bot { + rich.Content += " " + rich.Segments = append(rich.Segments, + colored.NewBlurple(segutil.Write(&rich, "[BOT]")), + ) + } + + return rich +} + +func labelChannel(s *ningen.State, chID discord.ChannelID) text.Rich { + var rich text.Rich + + ch, err := s.Cabinet.Channel(chID) + if err != nil { + rich = text.Plain(ch.Mention()) + } else { + rich = text.Plain(mention.ChannelName(*ch)) + } + + return rich +} diff --git a/internal/discord/state/labels/labels.go b/internal/discord/state/labels/labels.go new file mode 100644 index 0000000..ed1c77f --- /dev/null +++ b/internal/discord/state/labels/labels.go @@ -0,0 +1,178 @@ +package labels + +import ( + "sync" + + "github.com/diamondburned/arikawa/v2/discord" + "github.com/diamondburned/arikawa/v2/gateway" + "github.com/diamondburned/cchat" + "github.com/diamondburned/ningen/v2" +) + +// Repository is a repository containing LabelContainers. It watches for update +// events from the gateway. +// +// If a labeler that is already registered were to be added again, then the +// adder function will do nothing and will return a callback that does nothing. +type Repository struct { + state *ningen.State + detachs []func() + stopped bool + + mutex sync.Mutex + stores labelContainers +} + +// NewRepository creates a new repository. +func NewRepository(state *ningen.State) *Repository { + r := Repository{ + state: state, + stores: newLabelContainers(), + } + + r.detachs = []func(){ + state.AddHandler(r.onGuildUpdate), + state.AddHandler(r.onMemberUpdate), + state.AddHandler(r.onMemberRemove), + state.AddHandler(r.onChannelUpdate), + state.AddHandler(r.onChannelDelete), + } + + return &r +} + +func (r *Repository) onGuildUpdate(ev *gateway.GuildUpdateEvent) { + r.mutex.Lock() + defer r.mutex.Unlock() + + if r.stopped { + return + } + + guild, ok := r.stores.guilds[ev.ID] + if !ok { + return + } + + rich := labelGuild(r.state, ev.ID) + + for labeler := range guild.guild { + labeler.SetLabel(rich) + } +} + +// AddGuildLabel adds a label to display the given guild ID. Refer to Repository +// for more documentation. +func (r *Repository) AddGuildLabel(guildID discord.GuildID, l cchat.LabelContainer) func() { + l.SetLabel(labelGuild(r.state, guildID)) + + r.mutex.Lock() + defer r.mutex.Unlock() + + guild, _ := r.stores.guilds[guildID] + guild.guild.Add(l) + r.stores.guilds[guildID] = guild + + return func() { + r.mutex.Lock() + defer r.mutex.Unlock() + + guild, _ := r.stores.guilds[guildID] + guild.guild.Remove(l) + + if guild.IsEmpty() { + delete(r.stores.guilds, guildID) + return + } + + r.stores.guilds[guildID] = guild + } +} + +func (r *Repository) onMemberRemove(ev *gateway.GuildMemberRemoveEvent) {} + +func (r *Repository) onMemberUpdate(ev *gateway.GuildMemberUpdateEvent) {} + +// AddMemberLabel adds a label to display the given member live. Refer to +// Repository for more documentation. +func (r *Repository) AddMemberLabel( + guildID discord.GuildID, userID discord.UserID, l cchat.LabelContainer) func() { + + l.SetLabel(labelMember(r.state, guildID, userID)) + + r.mutex.Lock() + defer r.mutex.Unlock() + + guild, _ := r.stores.guilds[guildID] + + llist := guild.members[userID] + llist.Add(l) + + if guild.members == nil { + guild.members = make(map[discord.UserID]labelerList, 1) + } + + guild.members[userID] = llist + r.stores.guilds[guildID] = guild + + return func() { + r.mutex.Lock() + defer r.mutex.Unlock() + + guild, _ := r.stores.guilds[guildID] + + llist := guild.members[userID] + llist.Remove(l) + + if guild.IsEmpty() { + delete(r.stores.guilds, guildID) + return + } + + guild.members[userID] = llist + r.stores.guilds[guildID] = guild + } +} + +func (r *Repository) onChannelUpdate(ev *gateway.ChannelUpdateEvent) {} +func (r *Repository) onChannelDelete(ev *gateway.ChannelDeleteEvent) {} + +// AddChannelLabel adds a label to display the given channel live. Refer to +// Repository for more documentation. +func (r *Repository) AddChannelLabel(chID discord.ChannelID, l cchat.LabelContainer) func() { + l.SetLabel(labelChannel(r.state, chID)) + + r.mutex.Lock() + defer r.mutex.Unlock() + + llist := r.stores.channels[chID] + llist.Add(l) + r.stores.channels[chID] = llist + + return func() { + r.mutex.Lock() + defer r.mutex.Unlock() + + llist := r.stores.channels[chID] + llist.Remove(l) + + if len(llist) == 0 { + delete(r.stores.channels, chID) + return + } + + r.stores.channels[chID] = llist + } +} + +// Stop detaches all handlers. +func (r *Repository) Stop() { + r.mutex.Lock() + defer r.mutex.Unlock() + + r.stopped = true + + for _, detach := range r.detachs { + detach() + } +} diff --git a/internal/discord/state/labels/labels_wip.go b/internal/discord/state/labels/labels_wip.go new file mode 100644 index 0000000..d164010 --- /dev/null +++ b/internal/discord/state/labels/labels_wip.go @@ -0,0 +1,52 @@ +package labels + +// Unused things. + +// // AddPresenceLabel adds a label to display the giveen presence live. Refer to +// // Repository for more information. +// func (r *Repository) AddPresenceLabel(uID discord.UserID, l cchat.LabelContainer) (func(), error) { +// presence, err := r.state.Presence(0, uID) +// if err != nil { +// // We can accept lazy presences. +// l.SetLabel(text.Plain(uID.Mention())) +// } else { +// l.SetLabel() +// } + +// r.mutex.Lock() + +// llist := r.stores.presences[uID] +// llist.Add(l) +// r.stores.presences[uID] = llist + +// r.mutex.Unlock() + +// return func() { +// r.mutex.Lock() +// defer r.mutex.Unlock() + +// llist := r.stores.presences[uID] +// llist.Remove(l) + +// if len(llist) == 0 { +// delete(r.stores.presences, uID) +// return +// } + +// r.stores.presences[uID] = llist +// } +// } + +// func newPresenceSegment(s *ningen.State, uID discord.UserID) (*mention.User, error) { +// p, err := s.Presence(0, uID) +// if err != nil { +// return nil, err +// } + +// user := mention.NewUser(p.User) +// user.WithState(s) +// user.WithMember(opItem.Member.Member) +// user.WithGuildID(ch.GuildID) +// user.WithPresence(opItem.Member.Presence) +// user.Prefetch() +// } diff --git a/internal/discord/state/state.go b/internal/discord/state/state.go index 42681bf..1395cd6 100644 --- a/internal/discord/state/state.go +++ b/internal/discord/state/state.go @@ -3,14 +3,13 @@ package state import ( "context" - "log" "github.com/diamondburned/arikawa/v2/discord" "github.com/diamondburned/arikawa/v2/session" "github.com/diamondburned/arikawa/v2/state" "github.com/diamondburned/arikawa/v2/state/store/defaultstore" - "github.com/diamondburned/arikawa/v2/utils/httputil/httpdriver" "github.com/diamondburned/cchat" + "github.com/diamondburned/cchat-discord/internal/discord/state/labels" "github.com/diamondburned/cchat-discord/internal/discord/state/nonce" "github.com/diamondburned/ningen/v2" "github.com/pkg/errors" @@ -19,6 +18,7 @@ import ( type Instance struct { *ningen.State Nonces *nonce.Map + Labels *labels.Repository // UserID is a constant user ID of the current user. It is guaranteed to be // valid. @@ -66,10 +66,12 @@ func New(s *state.State) (*Instance, error) { return nil, errors.Wrap(err, "failed to create a state wrapper") } - n.Client.OnRequest = append(n.Client.OnRequest, func(r httpdriver.Request) error { - log.Println("[Discord] Request", r.GetPath()) - return nil - }) + // n.Client.OnRequest = append(n.Client.OnRequest, + // func(r httpdriver.Request) error { + // log.Println("[Discord] Request", r.GetPath()) + // return nil + // }, + // ) if err := n.Open(); err != nil { return nil, err @@ -85,6 +87,7 @@ func New(s *state.State) (*Instance, error) { UserID: u.ID, State: n, Nonces: new(nonce.Map), + Labels: labels.NewRepository(n), }, nil } @@ -95,12 +98,11 @@ func (s *Instance) Permissions( return s.StateOnly().Permissions(chID, uID) } +var deadCtx = expiredContext() + // StateOnly returns a shallow copy of *State with an already-expired context. func (s *Instance) StateOnly() *state.State { - ctx, cancel := context.WithCancel(context.Background()) - cancel() - - return s.WithContext(ctx) + return s.WithContext(deadCtx) } func (s *Instance) SaveSession() map[string]string { @@ -108,3 +110,10 @@ func (s *Instance) SaveSession() map[string]string { "token": s.Token, } } + +func expiredContext() context.Context { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + + return ctx +} diff --git a/internal/discord/authenticate/authenticator.go b/internal/discord_old/authenticate/authenticator.go similarity index 100% rename from internal/discord/authenticate/authenticator.go rename to internal/discord_old/authenticate/authenticator.go diff --git a/internal/discord/authenticate/discordlogin.go b/internal/discord_old/authenticate/discordlogin.go similarity index 100% rename from internal/discord/authenticate/discordlogin.go rename to internal/discord_old/authenticate/discordlogin.go diff --git a/internal/discord/authenticate/login.go b/internal/discord_old/authenticate/login.go similarity index 100% rename from internal/discord/authenticate/login.go rename to internal/discord_old/authenticate/login.go diff --git a/internal/discord/authenticate/token.go b/internal/discord_old/authenticate/token.go similarity index 100% rename from internal/discord/authenticate/token.go rename to internal/discord_old/authenticate/token.go diff --git a/internal/discord/authenticate/totp.go b/internal/discord_old/authenticate/totp.go similarity index 100% rename from internal/discord/authenticate/totp.go rename to internal/discord_old/authenticate/totp.go diff --git a/internal/discord/category/category.go b/internal/discord_old/category/category.go similarity index 100% rename from internal/discord/category/category.go rename to internal/discord_old/category/category.go diff --git a/internal/discord/channel/channel.go b/internal/discord_old/channel/channel.go similarity index 100% rename from internal/discord/channel/channel.go rename to internal/discord_old/channel/channel.go diff --git a/internal/discord/channel/commander.go b/internal/discord_old/channel/commander.go similarity index 100% rename from internal/discord/channel/commander.go rename to internal/discord_old/channel/commander.go diff --git a/internal/discord/channel/commands/arguments.go b/internal/discord_old/channel/commands/arguments.go similarity index 100% rename from internal/discord/channel/commands/arguments.go rename to internal/discord_old/channel/commands/arguments.go diff --git a/internal/discord/channel/commands/command.go b/internal/discord_old/channel/commands/command.go similarity index 100% rename from internal/discord/channel/commands/command.go rename to internal/discord_old/channel/commands/command.go diff --git a/internal/discord/channel/commands/commands.go b/internal/discord_old/channel/commands/commands.go similarity index 100% rename from internal/discord/channel/commands/commands.go rename to internal/discord_old/channel/commands/commands.go diff --git a/internal/discord/channel/message/action/actioner.go b/internal/discord_old/channel/message/action/actioner.go similarity index 100% rename from internal/discord/channel/message/action/actioner.go rename to internal/discord_old/channel/message/action/actioner.go diff --git a/internal/discord/channel/message/backlog/backlogger.go b/internal/discord_old/channel/message/backlog/backlogger.go similarity index 100% rename from internal/discord/channel/message/backlog/backlogger.go rename to internal/discord_old/channel/message/backlog/backlogger.go diff --git a/internal/discord/channel/message/edit/editor.go b/internal/discord_old/channel/message/edit/editor.go similarity index 100% rename from internal/discord/channel/message/edit/editor.go rename to internal/discord_old/channel/message/edit/editor.go diff --git a/internal/discord/channel/message/indicate/typing.go b/internal/discord_old/channel/message/indicate/typing.go similarity index 100% rename from internal/discord/channel/message/indicate/typing.go rename to internal/discord_old/channel/message/indicate/typing.go diff --git a/internal/discord/channel/message/indicate/unread.go b/internal/discord_old/channel/message/indicate/unread.go similarity index 83% rename from internal/discord/channel/message/indicate/unread.go rename to internal/discord_old/channel/message/indicate/unread.go index 11baa32..13c61f7 100644 --- a/internal/discord/channel/message/indicate/unread.go +++ b/internal/discord_old/channel/message/indicate/unread.go @@ -1,6 +1,7 @@ package indicate import ( + "github.com/diamondburned/arikawa/v2/discord" "github.com/diamondburned/cchat" "github.com/diamondburned/cchat-discord/internal/discord/channel/shared" "github.com/diamondburned/ningen/v2/states/read" @@ -41,3 +42,12 @@ func (ui UnreadIndicator) UnreadIndicate(indicator cchat.UnreadContainer) (func( } }), nil } + +func (ui UnreadIndicator) MarkRead(msgID cchat.ID) { + d, err := discord.ParseSnowflake(msgID) + if err != nil { + return + } + + ui.State.ReadState.MarkRead(ui.ID, discord.MessageID(d)) +} diff --git a/internal/discord/channel/message/memberlist/member.go b/internal/discord_old/channel/message/memberlist/member.go similarity index 91% rename from internal/discord/channel/message/memberlist/member.go rename to internal/discord_old/channel/message/memberlist/member.go index 72756ef..98d9010 100644 --- a/internal/discord/channel/message/memberlist/member.go +++ b/internal/discord_old/channel/message/memberlist/member.go @@ -40,22 +40,18 @@ func (l *Member) ID() cchat.ID { return l.mention.UserID().String() } -func (l *Member) Name() text.Rich { +func (l *Member) Name(ctx context.Context, labeler cchat.LabelContainer) error { + l.mention.Prefetch() content := l.mention.DisplayName() - return text.Rich{ + labeler.SetLabel(text.Rich{ Content: content, Segments: []text.Segment{ mention.NewSegment(0, len(content), &l.mention), }, - } -} + }) -func (l *Member) AsIconer() cchat.Iconer { return l } - -func (l *Member) Icon(ctx context.Context, c cchat.IconContainer) (func(), error) { - c.SetIcon(l.mention.Avatar()) - return func() {}, nil + return nil } func (l *Member) Status() cchat.Status { diff --git a/internal/discord/channel/message/memberlist/memberlist.go b/internal/discord_old/channel/message/memberlist/memberlist.go similarity index 100% rename from internal/discord/channel/message/memberlist/memberlist.go rename to internal/discord_old/channel/message/memberlist/memberlist.go diff --git a/internal/discord/channel/message/memberlist/section.go b/internal/discord_old/channel/message/memberlist/section.go similarity index 93% rename from internal/discord/channel/message/memberlist/section.go rename to internal/discord_old/channel/message/memberlist/section.go index cd8473a..b383b4b 100644 --- a/internal/discord/channel/message/memberlist/section.go +++ b/internal/discord_old/channel/message/memberlist/section.go @@ -1,6 +1,7 @@ package memberlist import ( + "context" "fmt" "github.com/diamondburned/arikawa/v2/discord" @@ -8,12 +9,9 @@ import ( "github.com/diamondburned/cchat" "github.com/diamondburned/cchat-discord/internal/discord/channel/shared" "github.com/diamondburned/cchat/text" - "github.com/diamondburned/cchat/utils/empty" ) type Section struct { - empty.Namer - // constant states listID string id string // roleID or online or offline @@ -63,8 +61,9 @@ func (s Section) ID() cchat.ID { return s.id } -func (s Section) Name() text.Rich { - return text.Rich{Content: s.name} +func (s Section) Name(ctx context.Context, labeler cchat.LabelContainer) (err error) { + labeler.SetLabel(text.Plain(s.name)) + return nil } func (s Section) Total() int { diff --git a/internal/discord/channel/message/message.go b/internal/discord_old/channel/message/message.go similarity index 100% rename from internal/discord/channel/message/message.go rename to internal/discord_old/channel/message/message.go diff --git a/internal/discord/channel/message/nickname/nicknamer.go b/internal/discord_old/channel/message/nickname/nicknamer.go similarity index 100% rename from internal/discord/channel/message/nickname/nicknamer.go rename to internal/discord_old/channel/message/nickname/nicknamer.go diff --git a/internal/discord/channel/message/send/complete/channel.go b/internal/discord_old/channel/message/send/complete/channel.go similarity index 100% rename from internal/discord/channel/message/send/complete/channel.go rename to internal/discord_old/channel/message/send/complete/channel.go diff --git a/internal/discord/channel/message/send/complete/completer.go b/internal/discord_old/channel/message/send/complete/completer.go similarity index 100% rename from internal/discord/channel/message/send/complete/completer.go rename to internal/discord_old/channel/message/send/complete/completer.go diff --git a/internal/discord/channel/message/send/complete/emoji.go b/internal/discord_old/channel/message/send/complete/emoji.go similarity index 100% rename from internal/discord/channel/message/send/complete/emoji.go rename to internal/discord_old/channel/message/send/complete/emoji.go diff --git a/internal/discord/channel/message/send/complete/mention.go b/internal/discord_old/channel/message/send/complete/mention.go similarity index 100% rename from internal/discord/channel/message/send/complete/mention.go rename to internal/discord_old/channel/message/send/complete/mention.go diff --git a/internal/discord/channel/message/send/sender.go b/internal/discord_old/channel/message/send/sender.go similarity index 100% rename from internal/discord/channel/message/send/sender.go rename to internal/discord_old/channel/message/send/sender.go diff --git a/internal/discord/channel/shared/channel.go b/internal/discord_old/channel/shared/channel.go similarity index 52% rename from internal/discord/channel/shared/channel.go rename to internal/discord_old/channel/shared/channel.go index d30f963..fd1db82 100644 --- a/internal/discord/channel/shared/channel.go +++ b/internal/discord_old/channel/shared/channel.go @@ -3,56 +3,11 @@ package shared import ( "errors" - "strings" "github.com/diamondburned/arikawa/v2/discord" "github.com/diamondburned/cchat-discord/internal/discord/state" ) -// ChannelName returns the channel name if any, otherwise it formats its own -// name into a list of recipients. -func ChannelName(ch discord.Channel) string { - switch ch.Type { - case discord.DirectMessage, discord.GroupDM: - if len(ch.DMRecipients) > 0 { - return FormatRecipients(ch.DMRecipients) - } - - default: - if ch.Name == "" { - break - } - - if ch.NSFW { - return "#" + ch.Name + " (nsfw)" - } else { - return "#" + ch.Name - } - } - - return ch.ID.String() -} - -// FormatRecipients joins the given list of users into a string listing all -// recipients with English punctuation rules. -func FormatRecipients(users []discord.User) string { - switch len(users) { - case 0: - return "" - case 1: - return users[0].Username - case 2: - return users[0].Username + " and " + users[1].Username - } - - var usernames = make([]string, len(users)-1) - for i, user := range users[:len(users)-1] { - usernames[i] = user.Username - } - - return strings.Join(usernames, ", ") + " and " + users[len(users)-1].Username -} - type Channel struct { ID discord.ChannelID GuildID discord.GuildID diff --git a/internal/discord/channel/typer/typer.go b/internal/discord_old/channel/typer/typer.go similarity index 100% rename from internal/discord/channel/typer/typer.go rename to internal/discord_old/channel/typer/typer.go diff --git a/internal/discord/config/config.go b/internal/discord_old/config/config.go similarity index 100% rename from internal/discord/config/config.go rename to internal/discord_old/config/config.go diff --git a/internal/discord/folder/folder.go b/internal/discord_old/folder/folder.go similarity index 100% rename from internal/discord/folder/folder.go rename to internal/discord_old/folder/folder.go diff --git a/internal/discord/guild/guild.go b/internal/discord_old/guild/guild.go similarity index 94% rename from internal/discord/guild/guild.go rename to internal/discord_old/guild/guild.go index e8733be..ded70d5 100644 --- a/internal/discord/guild/guild.go +++ b/internal/discord_old/guild/guild.go @@ -98,7 +98,8 @@ func (g *Guild) Servers(container cchat.ServersContainer) error { return toplevels[i].Type != discord.GuildCategory }) - var chs = make([]cchat.Server, 0, len(toplevels)) + chs := make([]cchat.Server, 0, len(toplevels)) + ids := make(map[discord.ChannelID]struct{}, len(toplevels)) for _, ch := range toplevels { switch ch.Type { @@ -110,9 +111,14 @@ func (g *Guild) Servers(container cchat.ServersContainer) error { return errors.Wrapf(err, "Failed to make channel %q: %v", ch.Name, err) } chs = append(chs, c) + default: + continue } } container.SetServers(chs) + + // TODO: account for insertion/deletion. + return nil } diff --git a/internal/discord/message/author.go b/internal/discord_old/message/author.go similarity index 98% rename from internal/discord/message/author.go rename to internal/discord_old/message/author.go index 5960cd1..1ce0ef2 100644 --- a/internal/discord/message/author.go +++ b/internal/discord_old/message/author.go @@ -17,7 +17,7 @@ type Author struct { user *mention.User // same pointer as in name } -var _ cchat.Author = (*Author)(nil) +var _ cchat.User = (*Author)(nil) // NewAuthor creates a new message author. func NewAuthor(user *mention.User) Author { diff --git a/internal/discord/message/message.go b/internal/discord_old/message/message.go similarity index 100% rename from internal/discord/message/message.go rename to internal/discord_old/message/message.go diff --git a/internal/discord/private/hub/messages.go b/internal/discord_old/private/hub/messages.go similarity index 100% rename from internal/discord/private/hub/messages.go rename to internal/discord_old/private/hub/messages.go diff --git a/internal/discord/private/hub/sender.go b/internal/discord_old/private/hub/sender.go similarity index 100% rename from internal/discord/private/hub/sender.go rename to internal/discord_old/private/hub/sender.go diff --git a/internal/discord/private/hub/server.go b/internal/discord_old/private/hub/server.go similarity index 100% rename from internal/discord/private/hub/server.go rename to internal/discord_old/private/hub/server.go diff --git a/internal/discord/private/private.go b/internal/discord_old/private/private.go similarity index 100% rename from internal/discord/private/private.go rename to internal/discord_old/private/private.go diff --git a/internal/discord/session/restorer.go b/internal/discord_old/session/restorer.go similarity index 100% rename from internal/discord/session/restorer.go rename to internal/discord_old/session/restorer.go diff --git a/internal/discord/session/session.go b/internal/discord_old/session/session.go similarity index 91% rename from internal/discord/session/session.go rename to internal/discord_old/session/session.go index ccd1183..00100ab 100644 --- a/internal/discord/session/session.go +++ b/internal/discord_old/session/session.go @@ -93,9 +93,8 @@ func (s *Session) Servers(container cchat.ServersContainer) error { func (s *Session) servers(container cchat.ServersContainer) error { ready := s.state.Ready() - switch { // If the user has guild folders: - case len(ready.UserSettings.GuildFolders) > 0: + if len(ready.UserSettings.GuildFolders) > 0 { // TODO: account for missing guilds. toplevels := make([]cchat.Server, 1, len(ready.UserSettings.GuildFolders)+1) toplevels[0] = s.private @@ -118,10 +117,12 @@ func (s *Session) servers(container cchat.ServersContainer) error { } container.SetServers(toplevels) + return nil + } // If the user doesn't have guild folders but has sorted their guilds // before: - case len(ready.UserSettings.GuildPositions) > 0: + if len(ready.UserSettings.GuildPositions) > 0 { guilds := make([]cchat.Server, 1, len(ready.UserSettings.GuildPositions)+1) guilds[0] = s.private @@ -134,23 +135,22 @@ func (s *Session) servers(container cchat.ServersContainer) error { } container.SetServers(guilds) - - // None of the above: - default: - g, err := s.state.Guilds() - if err != nil { - return err - } - - servers := make([]cchat.Server, len(g)+1) - servers[0] = s.private - - for i := range g { - servers[i+1] = guild.New(s.state, &g[i]) - } - - container.SetServers(servers) + return nil } + // None of the above: + g, err := s.state.Guilds() + if err != nil { + return err + } + + servers := make([]cchat.Server, len(g)+1) + servers[0] = s.private + + for i := range g { + servers[i+1] = guild.New(s.state, &g[i]) + } + + container.SetServers(servers) return nil } diff --git a/internal/discord_old/state/nonce/nonce.go b/internal/discord_old/state/nonce/nonce.go new file mode 100644 index 0000000..898c496 --- /dev/null +++ b/internal/discord_old/state/nonce/nonce.go @@ -0,0 +1,90 @@ +package nonce + +import ( + "encoding/base64" + "encoding/binary" + "fmt" + "strconv" + "sync" + "sync/atomic" + "time" + + cryptorand "crypto/rand" + mathrand "math/rand" +) + +func init() { + mathrand.Seed(time.Now().UnixNano()) +} + +var nonceCounter uint64 + +// generateNonce generates a unique nonce ID. +func generateNonce() string { + return fmt.Sprintf( + "%s-%s-%s", + strconv.FormatInt(time.Now().Unix(), 36), + randomBits(), + strconv.FormatUint(atomic.AddUint64(&nonceCounter, 1), 36), + ) +} + +// randomBits returns a string 6 bytes long with random characters that are safe +// to print. It falls back to math/rand's pseudorandom number generator if it +// cannot read from the system entropy pool. +func randomBits() string { + randBits := make([]byte, 2) + + _, err := cryptorand.Read(randBits) + if err != nil { + binary.LittleEndian.PutUint32(randBits, mathrand.Uint32()) + } + + return base64.RawStdEncoding.EncodeToString(randBits) +} + +// Map is a nonce state that keeps track of known nonces and generates a +// Discord-compatible nonce string. +type Map sync.Map + +// Generate generates a new internal nonce, add a bind from the new nonce to the +// original nonce, then return the new nonce. If the given original nonce is +// empty, then an empty string is returned. +func (nmap *Map) Generate(original string) string { + // Ignore empty nonces. + if original == "" { + return "" + } + + newNonce := generateNonce() + (*sync.Map)(nmap).Store(newNonce, original) + return newNonce +} + +// Load grabs the nonce and permanently deleting it if the given nonce is found. +func (nmap *Map) Load(newNonce string) string { + v, ok := (*sync.Map)(nmap).LoadAndDelete(newNonce) + if ok { + return v.(string) + } + return "" +} + +// Set is a unique set of nonces. +type Set sync.Map + +var nonceSentinel = struct{}{} + +func (nset *Set) Store(nonce string) { + (*sync.Map)(nset).Store(nonce, nonceSentinel) +} + +func (nset *Set) Has(nonce string) bool { + _, ok := (*sync.Map)(nset).Load(nonce) + return ok +} + +func (nset *Set) HasAndDelete(nonce string) bool { + _, ok := (*sync.Map)(nset).LoadAndDelete(nonce) + return ok +} diff --git a/internal/discord_old/state/state.go b/internal/discord_old/state/state.go new file mode 100644 index 0000000..c3a9bc7 --- /dev/null +++ b/internal/discord_old/state/state.go @@ -0,0 +1,116 @@ +// Package state provides a shared state instance for other packages to use. +package state + +import ( + "context" + + "github.com/diamondburned/arikawa/v2/discord" + "github.com/diamondburned/arikawa/v2/session" + "github.com/diamondburned/arikawa/v2/state" + "github.com/diamondburned/arikawa/v2/state/store/defaultstore" + "github.com/diamondburned/cchat" + "github.com/diamondburned/cchat-discord/internal/discord/state/nonce" + "github.com/diamondburned/ningen/v2" + "github.com/pkg/errors" +) + +type Instance struct { + *ningen.State + Nonces *nonce.Map + + // UserID is a constant user ID of the current user. It is guaranteed to be + // valid. + UserID discord.UserID +} + +var _ cchat.SessionSaver = (*Instance)(nil) + +// ErrInvalidSession is returned if SessionRestore is given a bad session. +var ErrInvalidSession = errors.New("invalid session") + +func NewFromData(data map[string]string) (*Instance, error) { + tk, ok := data["token"] + if !ok { + return nil, ErrInvalidSession + } + + return NewFromToken(tk) +} + +func NewFromToken(token string) (*Instance, error) { + s, err := state.New(token) + if err != nil { + return nil, err + } + + return New(s) +} + +func Login(email, password, mfa string) (*Instance, error) { + session, err := session.Login(email, password, mfa) + if err != nil { + return nil, err + } + + cabinet := defaultstore.New() + cabinet.MessageStore = defaultstore.NewMessage(50) + + return New(state.NewFromSession(session, cabinet)) +} + +func New(s *state.State) (*Instance, error) { + n, err := ningen.FromState(s) + if err != nil { + return nil, errors.Wrap(err, "failed to create a state wrapper") + } + + // n.Client.OnRequest = append(n.Client.OnRequest, + // func(r httpdriver.Request) error { + // log.Println("[Discord] Request", r.GetPath()) + // return nil + // }, + // ) + + if err := n.Open(); err != nil { + return nil, err + } + + // Prefetch user. + u, err := s.Me() + if err != nil { + return nil, errors.Wrap(err, "failed to get current user") + } + + return &Instance{ + UserID: u.ID, + State: n, + Nonces: new(nonce.Map), + }, nil +} + +// Permissions queries for the permission without hitting the REST API. +func (s *Instance) Permissions( + chID discord.ChannelID, uID discord.UserID) (discord.Permissions, error) { + + return s.StateOnly().Permissions(chID, uID) +} + +var deadCtx = expiredContext() + +// StateOnly returns a shallow copy of *State with an already-expired context. +func (s *Instance) StateOnly() *state.State { + return s.WithContext(deadCtx) +} + +func (s *Instance) SaveSession() map[string]string { + return map[string]string{ + "token": s.Token, + } +} + +func expiredContext() context.Context { + ctx, cancel := context.WithCancel(context.Background()) + cancel() + + return ctx +} diff --git a/internal/segments/avatar/avatar.go b/internal/segments/avatar/avatar.go new file mode 100644 index 0000000..87fa0d0 --- /dev/null +++ b/internal/segments/avatar/avatar.go @@ -0,0 +1,37 @@ +package avatar + +import ( + "github.com/diamondburned/cchat/text" + "github.com/diamondburned/cchat/utils/empty" +) + +// Segment describes an avatar segment. +type Segment struct { + empty.TextSegment + Position int + + URL string + Size int // optional + Text string // optional +} + +func (s Segment) Bounds() (int, int) { return s.Position, s.Position } +func (s Segment) AsAvatarer() text.Avatarer { return avatarURL{s} } + +type avatarURL struct { + seg Segment +} + +var _ text.Avatarer = avatarURL{} + +func (aurl avatarURL) AvatarText() string { + return aurl.seg.Text +} + +func (aurl avatarURL) AvatarSize() int { + return aurl.seg.Size +} + +func (aurl avatarURL) Avatar() string { + return aurl.seg.URL +} diff --git a/internal/segments/mention/activity.go b/internal/segments/mention/activity.go index c374a6a..21240bb 100644 --- a/internal/segments/mention/activity.go +++ b/internal/segments/mention/activity.go @@ -34,7 +34,7 @@ func NewLargeActivityImage(start int, ac discord.Activity) LargeActivityImage { return LargeActivityImage{ start: start, - url: urlutils.AssetURL(ac.ApplicationID, ac.Assets.LargeImage), + url: urlutils.AssetURL(ac.AppID, ac.Assets.LargeImage), text: ac.Assets.LargeText, } } diff --git a/internal/segments/mention/channel.go b/internal/segments/mention/channel.go index 051c48d..11c3c12 100644 --- a/internal/segments/mention/channel.go +++ b/internal/segments/mention/channel.go @@ -1,6 +1,8 @@ package mention import ( + "strings" + "github.com/diamondburned/arikawa/v2/discord" "github.com/diamondburned/cchat-discord/internal/segments/renderer" "github.com/diamondburned/cchat/text" @@ -8,6 +10,50 @@ import ( "github.com/diamondburned/ningen/v2/md" ) +// ChannelName returns the channel name if any, otherwise it formats its own +// name into a list of recipients. +func ChannelName(ch discord.Channel) string { + switch ch.Type { + case discord.DirectMessage, discord.GroupDM: + if len(ch.DMRecipients) > 0 { + return FormatRecipients(ch.DMRecipients) + } + + default: + if ch.Name == "" { + break + } + + if ch.NSFW { + return "#" + ch.Name + " (nsfw)" + } else { + return "#" + ch.Name + } + } + + return ch.ID.String() +} + +// FormatRecipients joins the given list of users into a string listing all +// recipients with English punctuation rules. +func FormatRecipients(users []discord.User) string { + switch len(users) { + case 0: + return "" + case 1: + return users[0].Username + case 2: + return users[0].Username + " and " + users[1].Username + } + + var usernames = make([]string, len(users)-1) + for i, user := range users[:len(users)-1] { + usernames[i] = user.Username + } + + return strings.Join(usernames, ", ") + " and " + users[len(users)-1].Username +} + type Channel struct { discord.Channel } diff --git a/internal/urlutils/urlutils.go b/internal/urlutils/urlutils.go index 22aced6..3fb4749 100644 --- a/internal/urlutils/urlutils.go +++ b/internal/urlutils/urlutils.go @@ -9,9 +9,12 @@ import ( "github.com/diamondburned/arikawa/v2/discord" ) +// AvatarSize is the size of the source image. +const AvatarSize = 128 + // AvatarURL wraps the URL with URL queries for the avatar. func AvatarURL(URL string) string { - return Sized(URL, 128) + return Sized(URL, AvatarSize) } // Sized wraps the URL with the size query. diff --git a/logo.go b/logo.go deleted file mode 100644 index d813318..0000000 --- a/logo.go +++ /dev/null @@ -1,20 +0,0 @@ -package discord - -import ( - "context" - - "github.com/diamondburned/cchat" -) - -const LogoURL = "https://raw.githubusercontent.com/" + - "diamondburned/cchat-discord/himearikawa/discord_logo.png" - -// Logo implements cchat.Iconer for the Discord logo. -var Logo cchat.Iconer = logo{} - -type logo struct{} - -func (logo) Icon(ctx context.Context, iconer cchat.IconContainer) (func(), error) { - iconer.SetIcon(LogoURL) - return func() {}, nil -}