mirror of
https://github.com/diamondburned/cchat-discord.git
synced 2025-02-02 23:46:43 +00:00
Added Typing indicator support; bumped cchat to v0.0.37
This commit is contained in:
parent
0a66a65fcf
commit
53111f3186
98
channel.go
98
channel.go
|
@ -2,6 +2,7 @@ package discord
|
|||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/diamondburned/arikawa/api"
|
||||
"github.com/diamondburned/arikawa/discord"
|
||||
|
@ -63,13 +64,14 @@ type Channel struct {
|
|||
}
|
||||
|
||||
var (
|
||||
_ cchat.Server = (*Channel)(nil)
|
||||
_ cchat.ServerMessage = (*Channel)(nil)
|
||||
_ cchat.ServerMessageSender = (*Channel)(nil)
|
||||
_ cchat.ServerMessageSendCompleter = (*Channel)(nil)
|
||||
_ cchat.ServerNickname = (*Channel)(nil)
|
||||
_ cchat.ServerMessageEditor = (*Channel)(nil)
|
||||
_ cchat.ServerMessageActioner = (*Channel)(nil)
|
||||
_ cchat.Server = (*Channel)(nil)
|
||||
_ cchat.ServerMessage = (*Channel)(nil)
|
||||
_ cchat.ServerMessageSender = (*Channel)(nil)
|
||||
_ cchat.ServerMessageSendCompleter = (*Channel)(nil)
|
||||
_ cchat.ServerNickname = (*Channel)(nil)
|
||||
_ cchat.ServerMessageEditor = (*Channel)(nil)
|
||||
_ cchat.ServerMessageActioner = (*Channel)(nil)
|
||||
_ cchat.ServerMessageTypingIndicator = (*Channel)(nil)
|
||||
)
|
||||
|
||||
func NewChannel(s *Session, ch discord.Channel) *Channel {
|
||||
|
@ -114,10 +116,10 @@ func (ch *Channel) Name() text.Rich {
|
|||
}
|
||||
}
|
||||
|
||||
func (ch *Channel) Nickname(ctx context.Context, labeler cchat.LabelContainer) error {
|
||||
func (ch *Channel) Nickname(ctx context.Context, labeler cchat.LabelContainer) (func(), error) {
|
||||
// We don't have a nickname if we're not in a guild.
|
||||
if !ch.guildID.Valid() {
|
||||
return nil
|
||||
return func() {}, nil
|
||||
}
|
||||
|
||||
state := ch.session.WithContext(ctx)
|
||||
|
@ -125,12 +127,12 @@ func (ch *Channel) Nickname(ctx context.Context, labeler cchat.LabelContainer) e
|
|||
// MemberColor should fill up the state cache.
|
||||
c, err := state.MemberColor(ch.guildID, ch.session.userID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to get self member color")
|
||||
return nil, errors.Wrap(err, "Failed to get self member color")
|
||||
}
|
||||
|
||||
m, err := state.Member(ch.guildID, ch.session.userID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to get self member")
|
||||
return nil, errors.Wrap(err, "Failed to get self member")
|
||||
}
|
||||
|
||||
var rich = text.Rich{Content: m.User.Username}
|
||||
|
@ -144,7 +146,29 @@ func (ch *Channel) Nickname(ctx context.Context, labeler cchat.LabelContainer) e
|
|||
}
|
||||
|
||||
labeler.SetLabel(rich)
|
||||
return nil
|
||||
|
||||
// Copy the user ID to use.
|
||||
var selfID = m.User.ID
|
||||
|
||||
return ch.session.AddHandler(func(g *gateway.GuildMemberUpdateEvent) {
|
||||
if g.GuildID != ch.guildID || g.User.ID != selfID {
|
||||
return
|
||||
}
|
||||
|
||||
var rich = text.Rich{Content: m.User.Username}
|
||||
if m.Nick != "" {
|
||||
rich.Content = m.Nick
|
||||
}
|
||||
|
||||
c, err := ch.session.MemberColor(g.GuildID, selfID)
|
||||
if err == nil {
|
||||
rich.Segments = []text.Segment{
|
||||
segments.NewColored(len(rich.Content), c.Uint32()),
|
||||
}
|
||||
}
|
||||
|
||||
labeler.SetLabel(rich)
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (ch *Channel) JoinServer(ctx context.Context, ct cchat.MessagesContainer) (func(), error) {
|
||||
|
@ -370,6 +394,10 @@ func (ch *Channel) canManageMessages(userID discord.Snowflake) bool {
|
|||
return p.Has(discord.PermissionManageMessages)
|
||||
}
|
||||
|
||||
// CompleteMessage implements message input completion capability for Discord.
|
||||
// This method supports user mentions, channel mentions and emojis.
|
||||
//
|
||||
// For the individual implementations, refer to channel_completion.go.
|
||||
func (ch *Channel) CompleteMessage(words []string, i int) (entries []cchat.CompletionEntry) {
|
||||
var word = words[i]
|
||||
// Word should have at least a character for the char check.
|
||||
|
@ -389,6 +417,52 @@ func (ch *Channel) CompleteMessage(words []string, i int) (entries []cchat.Compl
|
|||
return
|
||||
}
|
||||
|
||||
func (ch *Channel) Typing() error {
|
||||
return ch.session.Typing(ch.id)
|
||||
}
|
||||
|
||||
// TypingTimeout returns 8 seconds.
|
||||
func (ch *Channel) TypingTimeout() time.Duration {
|
||||
return 8 * time.Second
|
||||
}
|
||||
|
||||
func (ch *Channel) TypingSubscribe(ti cchat.TypingIndicator) (func(), error) {
|
||||
return ch.session.AddHandler(func(t *gateway.TypingStartEvent) {
|
||||
if t.ChannelID != ch.id {
|
||||
return
|
||||
}
|
||||
|
||||
if ch.guildID.Valid() {
|
||||
g, err := ch.session.Store.Guild(t.GuildID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if t.Member == nil {
|
||||
t.Member, err = ch.session.Store.Member(t.GuildID, t.UserID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ti.AddTyper(NewGuildMember(*t.Member, *g))
|
||||
return
|
||||
}
|
||||
|
||||
c, err := ch.self()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, user := range c.DMRecipients {
|
||||
if user.ID == t.UserID {
|
||||
ti.AddTyper(NewUser(user))
|
||||
return
|
||||
}
|
||||
}
|
||||
}), nil
|
||||
}
|
||||
|
||||
func newCancels() func(...func()) []func() {
|
||||
var cancels []func()
|
||||
return func(appended ...func()) []func() {
|
||||
|
|
2
go.mod
2
go.mod
|
@ -4,7 +4,7 @@ go 1.14
|
|||
|
||||
require (
|
||||
github.com/diamondburned/arikawa v0.9.5
|
||||
github.com/diamondburned/cchat v0.0.35
|
||||
github.com/diamondburned/cchat v0.0.37
|
||||
github.com/diamondburned/ningen v0.1.1-0.20200621014632-6babb812b249
|
||||
github.com/go-test/deep v1.0.6
|
||||
github.com/pkg/errors v0.9.1
|
||||
|
|
4
go.sum
4
go.sum
|
@ -29,6 +29,10 @@ github.com/diamondburned/cchat v0.0.34 h1:BGiVxMRA9dmW3rLilIldBvjVan7eTTpaWCCfX9
|
|||
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/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/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
|
|
18
guild.go
18
guild.go
|
@ -128,17 +128,25 @@ func (g *Guild) Name() text.Rich {
|
|||
return text.Rich{Content: s.Name}
|
||||
}
|
||||
|
||||
func (g *Guild) Icon(ctx context.Context, iconer cchat.IconContainer) error {
|
||||
func (g *Guild) Icon(ctx context.Context, iconer cchat.IconContainer) (func(), error) {
|
||||
s, err := g.self(ctx)
|
||||
if err != nil {
|
||||
// This shouldn't happen.
|
||||
return errors.Wrap(err, "Failed to get guild")
|
||||
return nil, errors.Wrap(err, "Failed to get guild")
|
||||
}
|
||||
|
||||
if s.Icon != "" {
|
||||
iconer.SetIcon(s.IconURL() + "?size=64")
|
||||
// Used for comparison.
|
||||
var hash = s.Icon
|
||||
if hash != "" {
|
||||
iconer.SetIcon(AvatarURL(s.IconURL()))
|
||||
}
|
||||
return nil
|
||||
|
||||
return g.session.AddHandler(func(g *gateway.GuildUpdateEvent) {
|
||||
if g.Icon != hash {
|
||||
hash = g.Icon
|
||||
iconer.SetIcon(AvatarURL(s.IconURL()))
|
||||
}
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (g *Guild) Servers(container cchat.ServersContainer) error {
|
||||
|
|
19
message.go
19
message.go
|
@ -1,6 +1,7 @@
|
|||
package discord
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/diamondburned/arikawa/discord"
|
||||
|
@ -51,6 +52,20 @@ func (m messageHeader) Time() time.Time {
|
|||
return m.time.Time()
|
||||
}
|
||||
|
||||
// AvatarURL wraps the URL with URL queries for the avatar.
|
||||
func AvatarURL(URL string) string {
|
||||
u, err := url.Parse(URL)
|
||||
if err != nil {
|
||||
return URL
|
||||
}
|
||||
|
||||
q := u.Query()
|
||||
q.Set("size", "64")
|
||||
u.RawQuery = q.Encode()
|
||||
|
||||
return u.String()
|
||||
}
|
||||
|
||||
type Author struct {
|
||||
id discord.Snowflake
|
||||
name text.Rich
|
||||
|
@ -61,7 +76,7 @@ func NewUser(u discord.User) Author {
|
|||
return Author{
|
||||
id: u.ID,
|
||||
name: text.Rich{Content: u.Username},
|
||||
avatar: u.AvatarURL(),
|
||||
avatar: AvatarURL(u.AvatarURL()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +84,7 @@ func NewGuildMember(m discord.Member, g discord.Guild) Author {
|
|||
return Author{
|
||||
id: m.User.ID,
|
||||
name: RenderMemberName(m, g),
|
||||
avatar: m.User.AvatarURL(),
|
||||
avatar: AvatarURL(m.User.AvatarURL()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
16
service.go
16
service.go
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
|
||||
"github.com/diamondburned/arikawa/discord"
|
||||
"github.com/diamondburned/arikawa/gateway"
|
||||
"github.com/diamondburned/arikawa/state"
|
||||
"github.com/diamondburned/cchat"
|
||||
"github.com/diamondburned/cchat/services"
|
||||
|
@ -30,9 +31,9 @@ func (Service) Name() text.Rich {
|
|||
return text.Rich{Content: "Discord"}
|
||||
}
|
||||
|
||||
func (Service) Icon(ctx context.Context, iconer cchat.IconContainer) error {
|
||||
func (Service) Icon(ctx context.Context, iconer cchat.IconContainer) (func(), error) {
|
||||
iconer.SetIcon("https://discord.com/assets/2c21aeda16de354ba5334551a883b481.png")
|
||||
return nil
|
||||
return func() {}, nil
|
||||
}
|
||||
|
||||
func (Service) Authenticate() cchat.Authenticator {
|
||||
|
@ -122,15 +123,18 @@ func (s *Session) Name() text.Rich {
|
|||
return text.Rich{Content: u.Username + "#" + u.Discriminator}
|
||||
}
|
||||
|
||||
func (s *Session) Icon(ctx context.Context, iconer cchat.IconContainer) error {
|
||||
func (s *Session) Icon(ctx context.Context, iconer cchat.IconContainer) (func(), error) {
|
||||
u, err := s.Me()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to get the current user")
|
||||
return nil, errors.Wrap(err, "Failed to get the current user")
|
||||
}
|
||||
|
||||
// Thanks to arikawa, AvatarURL is never empty.
|
||||
iconer.SetIcon(u.AvatarURL())
|
||||
return nil
|
||||
iconer.SetIcon(AvatarURL(u.AvatarURL()))
|
||||
|
||||
return s.AddHandler(func(u *gateway.UserUpdateEvent) {
|
||||
iconer.SetIcon(AvatarURL(u.AvatarURL()))
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (s *Session) Disconnect() error {
|
||||
|
|
Loading…
Reference in a new issue