1
0
Fork 0
mirror of https://github.com/diamondburned/cchat-discord.git synced 2024-12-22 20:36:45 +00:00

Added folders and categories, markup improvements, bug fixes

This commit is contained in:
diamondburned (Forefront) 2020-06-19 01:09:41 -07:00
parent 8b9b46317b
commit dac771656e
8 changed files with 289 additions and 33 deletions

67
category.go Normal file
View file

@ -0,0 +1,67 @@
package discord
import (
"sort"
"github.com/diamondburned/arikawa/discord"
"github.com/diamondburned/cchat"
"github.com/diamondburned/cchat/text"
"github.com/pkg/errors"
)
type Category struct {
id discord.Snowflake
guildID discord.Snowflake
session *Session
}
var (
_ cchat.Server = (*Category)(nil)
_ cchat.ServerList = (*Category)(nil)
)
func NewCategory(s *Session, ch discord.Channel) *Category {
return &Category{
id: ch.ID,
guildID: ch.GuildID,
session: s,
}
}
func (c *Category) ID() string {
return c.id.String()
}
func (c *Category) Name() text.Rich {
t, err := c.session.Channel(c.id)
if err != nil {
// This shouldn't happen.
return text.Rich{Content: c.id.String()}
}
return text.Rich{
Content: t.Name,
}
}
func (c *Category) Servers(container cchat.ServersContainer) error {
t, err := c.session.Channels(c.guildID)
if err != nil {
return errors.Wrap(err, "Failed to get channels")
}
// Filter out channels with this category ID.
var chs = filterAccessible(c.session, filterCategory(t, c.id))
sort.Slice(chs, func(i, j int) bool {
return chs[i].Position < chs[j].Position
})
var chv = make([]cchat.Server, len(chs))
for i := range chs {
chv[i] = NewChannel(c.session, chs[i])
}
container.SetServers(chv)
return nil
}

View file

@ -12,6 +12,50 @@ import (
"github.com/pkg/errors"
)
func chGuildCheck(chType discord.ChannelType) bool {
switch chType {
case discord.GuildCategory, discord.GuildText:
return true
default:
return false
}
}
func filterAccessible(s *Session, chs []discord.Channel) []discord.Channel {
u, err := s.Me()
if err != nil {
// Shouldn't happen.
return chs
}
filtered := chs[:0]
for _, ch := range chs {
p, err := s.Permissions(ch.ID, u.ID)
if err != nil {
continue
}
if p.Has(discord.PermissionViewChannel) {
filtered = append(filtered, ch)
}
}
return filtered
}
func filterCategory(chs []discord.Channel, catID discord.Snowflake) []discord.Channel {
var filtered = chs[:0]
for _, ch := range chs {
if ch.CategoryID == catID && chGuildCheck(ch.Type) {
filtered = append(filtered, ch)
}
}
return filtered
}
type Channel struct {
id discord.Snowflake
guildID discord.Snowflake

6
go.mod
View file

@ -2,13 +2,11 @@ module github.com/diamondburned/cchat-discord
go 1.14
replace github.com/diamondburned/ningen => ../../ningen/
require (
github.com/davecgh/go-spew v1.1.1
github.com/diamondburned/arikawa v0.9.4
github.com/diamondburned/arikawa v0.9.5
github.com/diamondburned/cchat v0.0.31
github.com/diamondburned/ningen v0.0.0-20200618230530-16d4d7fbc521
github.com/diamondburned/ningen v0.1.0
github.com/go-test/deep v1.0.6
github.com/pkg/errors v0.9.1
github.com/yuin/goldmark v1.1.30

8
go.sum
View file

@ -3,6 +3,10 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/diamondburned/arikawa v0.8.7-0.20200522214036-530bff74a2c6/go.mod h1:nIhVIatzTQhPUa7NB8w4koG1RF9gYbpAr8Fj8sKq660=
github.com/diamondburned/arikawa v0.9.4 h1:Mrp0Vz9R2afbvhWS6m/oLIQy22/uxXb459LUv7qrZPA=
github.com/diamondburned/arikawa v0.9.4/go.mod h1:nIhVIatzTQhPUa7NB8w4koG1RF9gYbpAr8Fj8sKq660=
github.com/diamondburned/arikawa v0.9.5-0.20200619075944-01021f09025b h1:fTR1esGjH+rR3ssd2vlZoxYLtML29paO0JjRV2lB3s0=
github.com/diamondburned/arikawa v0.9.5-0.20200619075944-01021f09025b/go.mod h1:nIhVIatzTQhPUa7NB8w4koG1RF9gYbpAr8Fj8sKq660=
github.com/diamondburned/arikawa v0.9.5 h1:P1ffsp+NHT22wWKYFVC8CdlGRLzPuUV9FcCBKOCJpCI=
github.com/diamondburned/arikawa v0.9.5/go.mod h1:nIhVIatzTQhPUa7NB8w4koG1RF9gYbpAr8Fj8sKq660=
github.com/diamondburned/cchat v0.0.26 h1:QBt4d65uzUPJz3jF8b2pJ09Jz8LeBRyG2ol47FOy0g0=
github.com/diamondburned/cchat v0.0.26/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU=
github.com/diamondburned/cchat v0.0.28 h1:+1VnltW0rl8/NZTUP+x89jVhi3YTTR+e6iLprZ7HcwM=
@ -11,6 +15,10 @@ github.com/diamondburned/cchat v0.0.31 h1:yUgrh5xbGX0R55glyxYtVewIDL2eXLJ+okIEfV
github.com/diamondburned/cchat v0.0.31/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU=
github.com/diamondburned/ningen v0.0.0-20200610212436-159f7105a2be h1:mUw8X/YzJGFSdL8y3Q/XqyzqPyIMNVSDyZGOP3JXgJA=
github.com/diamondburned/ningen v0.0.0-20200610212436-159f7105a2be/go.mod h1:B2hq2B4va1MlnMmXuv9vXmyu9gscxJLmwrmcSB1Les8=
github.com/diamondburned/ningen v0.0.0-20200619080103-03201e09d2a9 h1:KmmKgOVCXiRufPhBWlGpSILM6ZAUvgATMelQfYNpZIw=
github.com/diamondburned/ningen v0.0.0-20200619080103-03201e09d2a9/go.mod h1:Oxl8JrIoyo/OTx2xq9DnvvkJ3V3fUeI6cftO4LmNX84=
github.com/diamondburned/ningen v0.1.0 h1:cTnRNrN0g2Wr/kgjLLpa3pqlbEd6JPNa1yGDer8uV4U=
github.com/diamondburned/ningen v0.1.0/go.mod h1:1vi8mlBlM2xjJy+IugU51q+IMgyNXggS4Xv3SPFd2Q4=
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/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY=

100
guild.go
View file

@ -2,13 +2,83 @@ package discord
import (
"context"
"sort"
"strings"
"github.com/diamondburned/arikawa/discord"
"github.com/diamondburned/arikawa/gateway"
"github.com/diamondburned/cchat"
"github.com/diamondburned/cchat-discord/segments"
"github.com/diamondburned/cchat/text"
"github.com/pkg/errors"
)
type GuildFolder struct {
gateway.GuildFolder
session *Session
}
var (
_ cchat.Server = (*Guild)(nil)
_ cchat.ServerList = (*Guild)(nil)
)
func NewGuildFolder(s *Session, gf gateway.GuildFolder) *GuildFolder {
// Name should never be empty.
if gf.Name == "" {
var names = make([]string, 0, len(gf.GuildIDs))
for _, id := range gf.GuildIDs {
if g, _ := s.Store.Guild(id); g != nil {
names = append(names, g.Name)
}
}
gf.Name = strings.Join(names, ", ")
}
return &GuildFolder{
GuildFolder: gf,
session: s,
}
}
func (gf *GuildFolder) ID() string {
return gf.GuildFolder.ID.String()
}
func (gf *GuildFolder) Name() text.Rich {
var name = text.Rich{
// 1en space for style.
Content: gf.GuildFolder.Name,
}
if gf.GuildFolder.Color > 0 {
name.Segments = []text.Segment{
// The length of this black box is actually 3. Mind == blown.
segments.NewColored(len(name.Content), gf.GuildFolder.Color.Uint32()),
}
}
return name
}
func (gf *GuildFolder) Servers(container cchat.ServersContainer) error {
var servers = make([]cchat.Server, len(gf.GuildIDs))
for i, id := range gf.GuildIDs {
g, err := gf.session.Guild(id)
if err != nil {
return errors.Wrap(err, "Failed to get guild ID "+id.String())
}
servers[i] = NewGuild(gf.session, g)
}
container.SetServers(servers)
return nil
}
type Guild struct {
id discord.Snowflake
session *Session
@ -27,6 +97,15 @@ func NewGuild(s *Session, g *discord.Guild) *Guild {
}
}
func NewGuildFromID(s *Session, gID discord.Snowflake) (*Guild, error) {
g, err := s.Guild(gID)
if err != nil {
return nil, err
}
return NewGuild(s, g), nil
}
func (g *Guild) self(ctx context.Context) (*discord.Guild, error) {
return g.session.WithContext(ctx).Guild(g.id)
}
@ -68,11 +147,24 @@ func (g *Guild) Servers(container cchat.ServersContainer) error {
return errors.Wrap(err, "Failed to get channels")
}
var channels = make([]cchat.Server, len(c))
for i := range c {
channels[i] = NewChannel(g.session, c[i])
// Only get top-level channels (those with category ID being null).
var toplevels = filterAccessible(g.session, filterCategory(c, discord.NullSnowflake))
sort.Slice(toplevels, func(i, j int) bool {
return toplevels[i].Position < toplevels[j].Position
})
var chs = make([]cchat.Server, 0, len(toplevels))
for _, ch := range toplevels {
switch ch.Type {
case discord.GuildCategory:
chs = append(chs, NewCategory(g.session, ch))
case discord.GuildText:
chs = append(chs, NewChannel(g.session, ch))
}
}
container.SetServers(channels)
container.SetServers(chs)
return nil
}

View file

@ -61,7 +61,7 @@ func NewUser(u discord.User) Author {
return Author{
id: u.ID,
name: text.Rich{Content: u.Username},
avatar: u.AvatarURL() + "?size=128",
avatar: u.AvatarURL(),
}
}
@ -85,7 +85,7 @@ func NewGuildMember(m discord.Member, g discord.Guild) Author {
return Author{
id: m.User.ID,
name: name,
avatar: m.User.AvatarURL() + "?size=128",
avatar: m.User.AvatarURL(),
}
}

View file

@ -45,7 +45,7 @@ func RenderNode(source []byte, n ast.Node) text.Rich {
ast.Walk(n, r.renderNode)
return text.Rich{
Content: string(bytes.TrimSpace(buf.Bytes())),
Content: buf.String(),
Segments: r.segs,
}
}
@ -57,14 +57,17 @@ func (r *TextRenderer) i() int {
// startBlock guarantees enough indentation to start a new block.
func (r *TextRenderer) startBlock() {
var maxNewlines = 2
var maxNewlines = 0
// Peek twice.
if r.peekLast(0) == '\n' {
maxNewlines--
}
if r.peekLast(1) == '\n' {
maxNewlines--
// Peek twice. If the last character is already a new line or we're only at
// the start of line (length 0), then don't pad.
if r.buf.Len() > 0 {
if r.peekLast(0) != '\n' {
maxNewlines++
}
if r.peekLast(1) != '\n' {
maxNewlines++
}
}
// Write the padding.

View file

@ -133,21 +133,6 @@ func (s *Session) Icon(ctx context.Context, iconer cchat.IconContainer) error {
return nil
}
func (s *Session) Servers(container cchat.ServersContainer) error {
g, err := s.Guilds()
if err != nil {
return err
}
var servers = make([]cchat.Server, len(g))
for i := range g {
servers[i] = NewGuild(s, &g[i])
}
container.SetServers(servers)
return nil
}
func (s *Session) Disconnect() error {
return s.Close()
}
@ -157,3 +142,62 @@ func (s *Session) Save() (map[string]string, error) {
"token": s.Token,
}, nil
}
func (s *Session) Servers(container cchat.ServersContainer) error {
switch {
// If the user has guild folders:
case len(s.Ready.Settings.GuildFolders) > 0:
// TODO: account for missing guilds.
var toplevels = make([]cchat.Server, 0, len(s.Ready.Settings.GuildFolders))
for _, folder := range s.Ready.Settings.GuildFolders {
// TODO: correct.
switch {
case folder.ID.Valid():
fallthrough
case len(folder.GuildIDs) > 1:
toplevels = append(toplevels, NewGuildFolder(s, folder))
case len(folder.GuildIDs) == 1:
g, err := NewGuildFromID(s, folder.GuildIDs[0])
if err != nil {
return errors.Wrap(err, "Failed to get guild in folder")
}
toplevels = append(toplevels, g)
}
}
container.SetServers(toplevels)
// If the user doesn't have guild folders but has sorted their guilds
// before:
case len(s.Ready.Settings.GuildPositions) > 0:
var guilds = make([]cchat.Server, 0, len(s.Ready.Settings.GuildPositions))
for _, id := range s.Ready.Settings.GuildPositions {
g, err := NewGuildFromID(s, id)
if err != nil {
return errors.Wrap(err, "Failed to get guild in position")
}
guilds = append(guilds, g)
}
container.SetServers(guilds)
// None of the above:
default:
g, err := s.Guilds()
if err != nil {
return err
}
var servers = make([]cchat.Server, len(g))
for i := range g {
servers[i] = NewGuild(s, &g[i])
}
container.SetServers(servers)
}
return nil
}