From 780613d7b9525cebd344d5d82fd0b78287423aaa Mon Sep 17 00:00:00 2001 From: Dustin Pianalto Date: Sat, 23 Jan 2021 01:25:06 -0900 Subject: [PATCH] initial database crud --- channel.go | 10 +- go.sum | 1 + guild.go | 20 +- internal/database/channel.go | 68 ++++++ internal/database/database.go | 9 +- internal/database/guild.go | 100 ++++++++ internal/database/message.go | 94 ++++++++ .../000002_add_guild_to_request.down.sql | 1 + .../000002_add_guild_to_request.up.sql | 2 + internal/database/patreon.go | 178 ++++++++++++++ internal/database/request.go | 226 ++++++++++++++++++ internal/database/server.go | 138 +++++++++++ internal/database/user.go | 37 +++ message.go | 18 +- patreon.go | 29 +-- request.go | 36 +-- server.go | 22 +- user.go | 8 +- 18 files changed, 924 insertions(+), 73 deletions(-) create mode 100644 internal/database/channel.go create mode 100644 internal/database/guild.go create mode 100644 internal/database/message.go create mode 100644 internal/database/migrations/000002_add_guild_to_request.down.sql create mode 100644 internal/database/migrations/000002_add_guild_to_request.up.sql create mode 100644 internal/database/patreon.go create mode 100644 internal/database/request.go create mode 100644 internal/database/server.go create mode 100644 internal/database/user.go diff --git a/channel.go b/channel.go index db4a182..827d20d 100644 --- a/channel.go +++ b/channel.go @@ -9,9 +9,9 @@ type Channel struct { } type ChannelService interface { - Channel(id string) (*Channel, error) - CreateChannel(c *Channel) (*Channel, error) - DeleteChannel(c *Channel) error - GuildChannels(g *Guild) ([]*Channel, error) - UpdateChannel(c *Channel) (*Channel, error) + Channel(id string) (Channel, error) + CreateChannel(c Channel) (Channel, error) + DeleteChannel(c Channel) error + GuildChannels(g Guild) ([]Channel, error) + UpdateChannel(c Channel) (Channel, error) } diff --git a/go.sum b/go.sum index 0f7ccd0..5a69020 100644 --- a/go.sum +++ b/go.sum @@ -294,6 +294,7 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg= golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/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= diff --git a/guild.go b/guild.go index e98a95d..b4771c5 100644 --- a/guild.go +++ b/guild.go @@ -8,18 +8,18 @@ type Guild struct { type Role struct { ID string - RoleType int + RoleType string Guild Guild } type GuildService interface { - Guild(id string) (*Guild, error) - CreateGuild(g *Guild) (*Guild, error) - DeleteGuild(g *Guild) error - UpdateGuild(g *Guild) (*Guild, error) - GuildRoles(g *Guild) ([]*Role, error) - CreateRole(r *Role) (*Role, error) - Role(id string) (*Role, error) - UpdateRole(r *Role) (*Role, error) - DeleteRole(r *Role) error + Guild(id string) (Guild, error) + CreateGuild(g Guild) (Guild, error) + DeleteGuild(g Guild) error + UpdateGuild(g Guild) (Guild, error) + GuildRoles(g Guild) ([]Role, error) + CreateRole(r Role) (Role, error) + Role(id string) (Role, error) + UpdateRole(r Role) (Role, error) + DeleteRole(r Role) error } diff --git a/internal/database/channel.go b/internal/database/channel.go new file mode 100644 index 0000000..196898d --- /dev/null +++ b/internal/database/channel.go @@ -0,0 +1,68 @@ +package database + +import ( + "database/sql" + "log" + + "github.com/dustinpianalto/geeksbot" +) + +type channelService struct { + db *sql.DB +} + +func (s channelService) Channel(id string) (geeksbot.Channel, error) { + var channel geeksbot.Channel + var guild_id string + queryString := "SELECT id, guild_id, admin, default_channel, new_patron FROM channels WHERE id = $1" + row := s.db.QueryRow(queryString, id) + err := row.Scan(&channel.ID, &guild_id, &channel.Admin, &channel.Default, &channel.NewPatron) + if err != nil { + return geeksbot.Channel{}, err + } + guild, err := GuildService.Guild(guild_id) + if err != nil { + return geeksbot.Channel{}, err + } + channel.Guild = guild + return channel, nil +} + +func (s channelService) CreateChannel(c geeksbot.Channel) (geeksbot.Channel, error) { + queryString := "INSERT INTO channels (id, guild_id, admin, default_channel, new_patron VALUES ($1, $2, $3, $4, $5))" + _, err := s.db.Exec(queryString, c.ID, c.Guild.ID, c.Admin, c.Default, c.NewPatron) + return c, err +} + +func (s channelService) DeleteChannel(c geeksbot.Channel) error { + queryString := "DELETE FROM channels WHERE id = $1" + _, err := s.db.Exec(queryString, c.ID) + return err +} + +func (s channelService) UpdateChannel(c geeksbot.Channel) (geeksbot.Channel, error) { + queryString := "UPDATE channels SET admin = $2, default_channel = $3, new_patron = $4 WHERE id = $1" + _, err := s.db.Exec(queryString, c.ID, c.Admin, c.Default, c.NewPatron) + return c, err +} + +func (s channelService) GuildChannels(g geeksbot.Guild) ([]geeksbot.Channel, error) { + var channels []geeksbot.Channel + queryString := "SELECT id FROM channels WHERE guild_id = $1" + rows, err := s.db.Query(queryString, g.ID) + for rows.Next() { + var id string + err = rows.Scan(&id) + if err != nil { + log.Println(err) + continue + } + channel, err := s.Channel(id) + if err != nil { + log.Println(err) + continue + } + channels = append(channels, channel) + } + return channels, nil +} diff --git a/internal/database/database.go b/internal/database/database.go index 0f074ac..b04964a 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -12,7 +12,14 @@ import ( ) var ( - db *sql.DB + db *sql.DB + GuildService guildService + UserService userService + ChannelService channelService + MessageService messageService + PatreonService patreonService + RequestService requestService + ServerService serverService ) func ConnectDatabase(dbConnString string) { diff --git a/internal/database/guild.go b/internal/database/guild.go new file mode 100644 index 0000000..b0e2524 --- /dev/null +++ b/internal/database/guild.go @@ -0,0 +1,100 @@ +package database + +import ( + "database/sql" + "log" + + "github.com/dustinpianalto/geeksbot" +) + +type guildService struct { + db *sql.DB +} + +func (s guildService) Guild(id string) (geeksbot.Guild, error) { + var g geeksbot.Guild + queryString := "SELECT id, new_patron_message, prefixes FROM guilds WHERE id = $1" + row := s.db.QueryRow(queryString, id) + err := row.Scan(&g.ID, &g.NewPatronMessage, &g.Prefixes) + if err != nil { + return geeksbot.Guild{}, err + } + return g, nil +} + +func (s guildService) CreateGuild(g geeksbot.Guild) (geeksbot.Guild, error) { + queryString := "INSERT INTO guilds (id, new_patron_message, prefixes) VALUES ($1, $2, $3)" + _, err := s.db.Exec(queryString, g.ID, g.NewPatronMessage, g.Prefixes) + return g, err +} + +func (s guildService) DeleteGuild(g geeksbot.Guild) error { + queryString := "DELETE FROM guilds WHERE id = $1" + _, err := s.db.Exec(queryString, g.ID) + return err +} + +func (s guildService) UpdateGuild(g geeksbot.Guild) (geeksbot.Guild, error) { + queryString := "UPDATE guilds SET new_patron_message = $2, prefixes = $3 WHERE id = $1" + _, err := s.db.Exec(queryString, g.ID, g.NewPatronMessage, g.Prefixes) + return g, err +} + +func (s guildService) GuildRoles(g geeksbot.Guild) ([]geeksbot.Role, error) { + var roles []geeksbot.Role + queryString := "SELECT id FROM roles WHERE guild_id = $1" + rows, err := s.db.Query(queryString, g.ID) + if err != nil { + return nil, err + } + for rows.Next() { + var id string + err = rows.Scan(&id) + if err != nil { + log.Println(err) + continue + } + role, err := s.Role(id) + if err != nil { + log.Println(err) + continue + } + roles = append(roles, role) + } + return roles, nil +} + +func (s guildService) CreateRole(r geeksbot.Role) (geeksbot.Role, error) { + queryString := "INSERT INTO roles (id, role_type, guild_id) VALUES ($1, $2, $3)" + _, err := s.db.Exec(queryString, r.ID, r.RoleType, r.Guild.ID) + return r, err +} + +func (s guildService) Role(id string) (geeksbot.Role, error) { + var role geeksbot.Role + var guild_id string + queryString := "SELECT id, role_type, guild_id FROM roles WHERE id = $1" + row := s.db.QueryRow(queryString, id) + err := row.Scan(&role.ID, &role.RoleType, &guild_id) + if err != nil { + return geeksbot.Role{}, err + } + guild, err := s.Guild(guild_id) + if err != nil { + return geeksbot.Role{}, err + } + role.Guild = guild + return role, nil +} + +func (s guildService) UpdateRole(r geeksbot.Role) (geeksbot.Role, error) { + queryString := "UPDATE roles SET role_type = $2 WHERE id = $1" + _, err := s.db.Exec(queryString, r.ID, r.RoleType) + return r, err +} + +func (s guildService) DeleteRole(r geeksbot.Role) error { + queryString := "DELETE FROM roles WHERE id = $1" + _, err := s.db.Exec(queryString, r.ID) + return err +} diff --git a/internal/database/message.go b/internal/database/message.go new file mode 100644 index 0000000..414a5ec --- /dev/null +++ b/internal/database/message.go @@ -0,0 +1,94 @@ +package database + +import ( + "database/sql" + "log" + + "github.com/dustinpianalto/geeksbot" +) + +type messageService struct { + db *sql.DB +} + +func (s messageService) Message(id string) (geeksbot.Message, error) { + var m geeksbot.Message + var channel_id string + var author_id string + queryString := `SELECT m.id, m.created_at, m.modified_at, m.content, + m.previous_content, m.channel_id, m.author_id + FROM messages as m + WHERE m.id = $1` + row := s.db.QueryRow(queryString, id) + err := row.Scan(&m.ID, &m.CreatedAt, &m.ModifiedAt, &m.Content, + &m.PreviousContent, &channel_id, &author_id) + if err != nil { + return geeksbot.Message{}, err + } + author, err := UserService.User(author_id) + if err != nil { + return geeksbot.Message{}, err + } + m.Author = author + channel, err := ChannelService.Channel(channel_id) + if err != nil { + return geeksbot.Message{}, err + } + m.Channel = channel + return m, nil +} + +func (s messageService) CreateMessage(m geeksbot.Message) (geeksbot.Message, error) { + queryString := `INSERT INTO messages (id, created_at, content, channel_id, author_id) + VALUES ($1, $2, $3, $4, $5)` + _, err := s.db.Exec(queryString, m.ID, m.CreatedAt, m.Content, m.Channel.ID, m.Author.ID) + return m, err +} + +func (s messageService) UpdateMessage(m geeksbot.Message) (geeksbot.Message, error) { + var content string + var previousContent []string + queryString := "SELECT content, previous_content FROM messages WHERE id = $1" + row := s.db.QueryRow(queryString, m.ID) + err := row.Scan(&content, &previousContent) + if err != nil { + return geeksbot.Message{}, err + } + if m.Content != content { + previousContent = append(previousContent, content) + } + queryString = "UPDATE messages SET modified_at = $2, content = $3, previous_content = $4 WHERE id = $1" + _, err = s.db.Exec(queryString, m.ID, m.ModifiedAt, m.Content, previousContent) + m.PreviousContent = previousContent + return m, nil +} + +func (s messageService) DeleteMessage(m geeksbot.Message) error { + queryString := "DELETE FROM messages WHERE id = $1" + _, err := s.db.Exec(queryString, m.ID) + return err +} + +func (s messageService) ChannelMessages(c geeksbot.Channel) ([]geeksbot.Message, error) { + var messages []geeksbot.Message + queryString := `SELECT id FROM messages WHERE channel_id = $1` + rows, err := s.db.Query(queryString, c.ID) + if err != nil { + return nil, err + } + for rows.Next() { + var id string + err = rows.Scan(&id) + if err != nil { + log.Println(err) + continue + } + m, err := s.Message(id) + if err != nil { + log.Println(err) + continue + } + messages = append(messages, m) + } + return messages, nil +} diff --git a/internal/database/migrations/000002_add_guild_to_request.down.sql b/internal/database/migrations/000002_add_guild_to_request.down.sql new file mode 100644 index 0000000..8d02a48 --- /dev/null +++ b/internal/database/migrations/000002_add_guild_to_request.down.sql @@ -0,0 +1 @@ +ALTER TABLE requests DROP COLUMN guild_id; diff --git a/internal/database/migrations/000002_add_guild_to_request.up.sql b/internal/database/migrations/000002_add_guild_to_request.up.sql new file mode 100644 index 0000000..1afb502 --- /dev/null +++ b/internal/database/migrations/000002_add_guild_to_request.up.sql @@ -0,0 +1,2 @@ +ALTER TABLE requests + ADD COLUMN guild_id varchar(30) REFERENCES guilds(id) ON DELETE CASCADSE; diff --git a/internal/database/patreon.go b/internal/database/patreon.go new file mode 100644 index 0000000..6195ca2 --- /dev/null +++ b/internal/database/patreon.go @@ -0,0 +1,178 @@ +package database + +import ( + "database/sql" + "log" + + "github.com/dustinpianalto/geeksbot" +) + +type patreonService struct { + db *sql.DB +} + +func (s patreonService) PatreonCreatorByID(id int) (geeksbot.PatreonCreator, error) { + var creator geeksbot.PatreonCreator + var gID string + queryString := "SELECT id, creator, link, guild_id FROM patreon_creator WHERE id = $1" + row := s.db.QueryRow(queryString, id) + err := row.Scan(&creator.ID, &creator.Creator, &creator.Link, &gID) + if err != nil { + return geeksbot.PatreonCreator{}, err + } + guild, err := GuildService.Guild(gID) + if err != nil { + return geeksbot.PatreonCreator{}, err + } + creator.Guild = guild + return creator, nil +} + +func (s patreonService) PatreonCreatorByName(name string, g geeksbot.Guild) (geeksbot.PatreonCreator, error) { + var id int + queryString := "SELECT id FROM patreon_creator WHERE creator = $1 AND guild_id = $2" + err := s.db.QueryRow(queryString, name, g.ID).Scan(&id) + if err != nil { + return geeksbot.PatreonCreator{}, nil + } + creator, err := s.PatreonCreatorByID(id) + return creator, err +} + +func (s patreonService) CreatePatreonCreator(c geeksbot.PatreonCreator) (geeksbot.PatreonCreator, error) { + var id int + queryString := `INSERT INTO patreon_creator (creator, link, guild_id) VALUES ($1, $2, $3) RETURNING id` + err := s.db.QueryRow(queryString, c.Creator, c.Link, c.Guild.ID).Scan(&id) + if err != nil { + return geeksbot.PatreonCreator{}, err + } + c.ID = id + return c, nil +} + +func (s patreonService) UpdatePatreonCreator(c geeksbot.PatreonCreator) (geeksbot.PatreonCreator, error) { + queryString := `UPDATE patreon_creator SET creator = $2, link = $3 WHERE id = $1` + _, err := s.db.Exec(queryString, c.ID, c.Creator, c.Link) + return c, err +} + +func (s patreonService) DeletePatreonCreator(c geeksbot.PatreonCreator) error { + queryString := `DELETE FROM patreon_creator WHERE id = $1` + _, err := s.db.Exec(queryString, c.ID) + return err +} + +func (s patreonService) PatreonTierByID(id int) (geeksbot.PatreonTier, error) { + var tier geeksbot.PatreonTier + var cID int + var rID string + var next int + queryString := `SELECT id, name, description, creator, role, next_tier FROM patreon_tier WHERE id = id` + err := s.db.QueryRow(queryString, id).Scan(&tier.ID, &tier.Name, &tier.Description, &cID, &rID, &next) + if err != nil { + return geeksbot.PatreonTier{}, err + } + creator, err := s.PatreonCreatorByID(cID) + if err != nil { + return geeksbot.PatreonTier{}, err + } + tier.Creator = creator + role, err := GuildService.Role(rID) + if err != nil { + return geeksbot.PatreonTier{}, err + } + tier.Role = role + if next == -1 { + tier.NextTier = nil + return tier, nil + } + nextTier, err := s.PatreonTierByID(next) + if err != nil { + return geeksbot.PatreonTier{}, err + } + tier.NextTier = &nextTier + return tier, nil +} + +func (s patreonService) PatreonTierByName(name string, creator string) (geeksbot.PatreonTier, error) { + var id int + queryString := `SELECT id FROM patreon_tier WHERE name = $1 AND creator = $2` + err := s.db.QueryRow(queryString, name, creator).Scan(&id) + if err != nil { + return geeksbot.PatreonTier{}, err + } + tier, err := s.PatreonTierByID(id) + return tier, err +} + +func (s patreonService) CreatePatreonTier(t geeksbot.PatreonTier) (geeksbot.PatreonTier, error) { + var id int + queryString := `INSERT INTO patreon_tier (name, description, creator, role, next_tier) + VALUES ($1, $2, $3, $4, $5) RETURNING id` + err := s.db.QueryRow(queryString, t.Name, t.Description, t.Creator.ID, t.Role.ID, t.NextTier.ID).Scan(&id) + if err != nil { + return geeksbot.PatreonTier{}, err + } + t.ID = id + return t, nil +} + +func (s patreonService) UpdatePatreonTier(t geeksbot.PatreonTier) (geeksbot.PatreonTier, error) { + queryString := `UPDATE patreon_tier SET name = $2, description = $3, role = $4, next_tier = $5 WHERE id = $1` + _, err := s.db.Exec(queryString, t.ID, t.Name, t.Description, t.Role.ID, t.NextTier.ID) + return t, err +} + +func (s patreonService) DeletePatreonTier(t geeksbot.PatreonTier) error { + queryString := `DELETE FROM patreon_tier WHERE id = $1` + _, err := s.db.Exec(queryString, t.ID) + return err +} + +func (s patreonService) GuildPatreonCreators(g geeksbot.Guild) ([]geeksbot.PatreonCreator, error) { + var creators []geeksbot.PatreonCreator + queryString := `SELECT id FROM patreon_creator WHERE guild_id = $1` + rows, err := s.db.Query(queryString, g.ID) + if err != nil { + return nil, err + } + for rows.Next() { + var id int + err := rows.Scan(&id) + if err != nil { + log.Println(err) + continue + } + creator, err := s.PatreonCreatorByID(id) + if err != nil { + log.Println(err) + continue + } + creators = append(creators, creator) + } + return creators, nil +} + +func (s patreonService) CreatorPatreonTiers(c geeksbot.PatreonCreator) ([]geeksbot.PatreonTier, error) { + var tiers []geeksbot.PatreonTier + queryString := `SELECT id FROM patreon_tier WHERE creator = $1` + rows, err := s.db.Query(queryString, c.ID) + if err != nil { + return nil, err + } + for rows.Next() { + var id int + err := rows.Scan(&id) + if err != nil { + log.Println(err) + continue + } + tier, err := s.PatreonTierByID(id) + if err != nil { + log.Println(err) + continue + } + tiers = append(tiers, tier) + } + return tiers, nil +} diff --git a/internal/database/request.go b/internal/database/request.go new file mode 100644 index 0000000..0f428f7 --- /dev/null +++ b/internal/database/request.go @@ -0,0 +1,226 @@ +package database + +import ( + "database/sql" + "log" + + "github.com/dustinpianalto/geeksbot" +) + +type requestService struct { + db *sql.DB +} + +func (s requestService) Request(id int64) (geeksbot.Request, error) { + var r geeksbot.Request + var aID string + var cID string + var gID string + var uID string + var mID string + queryString := `SELECT id, author_id, channel_id, guild_id, content, requested_at, completed, + completed_at, completed_by, message_id, completed_message + WHERE id = $1` + row := s.db.QueryRow(queryString, id) + err := row.Scan(&r.ID, &aID, &cID, &gID, &r.Content, &r.RequestedAt, &r.Completed, + &r.CompletedAt, &uID, &mID, &r.CompletedMessage) + if err != nil { + return geeksbot.Request{}, err + } + author, err := UserService.User(aID) + if err != nil { + return geeksbot.Request{}, err + } + guild, err := GuildService.Guild(gID) + if err != nil { + return geeksbot.Request{}, err + } + channel, err := ChannelService.Channel(cID) + if err != nil { + return geeksbot.Request{}, err + } + completedBy, err := UserService.User(uID) + if err != nil { + return geeksbot.Request{}, err + } + message, err := MessageService.Message(mID) + if err != nil { + return geeksbot.Request{}, err + } + r.Author = author + r.Guild = guild + r.Channel = channel + r.CompletedBy = completedBy + r.Message = message + return r, nil +} + +func (s requestService) UserRequests(u geeksbot.User, completed bool) ([]geeksbot.Request, error) { + var requests []geeksbot.Request + var queryString string + if completed { + queryString = "SELECT id FROM requests WHERE author_id = $1" + } else { + queryString = "SELECT id FROM requests WHERE author_id = $1 AND completed = False" + } + rows, err := s.db.Query(queryString, u.ID) + if err != nil { + return nil, err + } + for rows.Next() { + var id int64 + err = rows.Scan(&id) + if err != nil { + log.Println(err) + continue + } + request, err := s.Request(id) + if err != nil { + log.Println(err) + continue + } + requests = append(requests, request) + } + return requests, nil +} + +func (s requestService) GuildRequests(g geeksbot.Guild, completed bool) ([]geeksbot.Request, error) { + var requests []geeksbot.Request + var queryString string + if completed { + queryString = "SELECT id FROM requests WHERE guild_id = $1" + } else { + queryString = "SELECT id FROM requests WHERE guild_id = $1 AND completed = False" + } + rows, err := s.db.Query(queryString, g.ID) + if err != nil { + return nil, err + } + for rows.Next() { + var id int64 + err = rows.Scan(&id) + if err != nil { + log.Println(err) + continue + } + request, err := s.Request(id) + if err != nil { + log.Println(err) + continue + } + requests = append(requests, request) + } + return requests, nil + +} + +func (s requestService) CreateRequest(r geeksbot.Request) (geeksbot.Request, error) { + queryString := `INSERT INTO requests + (author_id, channel_id, guild_id, content, requested_at, + completed, completed_at, completed_by, message_id, completed_message) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING id` + var id int64 + err := s.db.QueryRow(queryString, + r.Author.ID, + r.Channel.ID, + r.Guild.ID, + r.Content, + r.RequestedAt, + r.Completed, + r.CompletedAt, + r.CompletedBy.ID, + r.Message.ID, + r.CompletedMessage).Scan(&id) + if err != nil { + return geeksbot.Request{}, err + } + r.ID = id + return r, nil +} + +func (s requestService) UpdateRequest(r geeksbot.Request) (geeksbot.Request, error) { + queryString := `UPDATE requests SET + completed = $2, completed_at = $3, completed_by = $4, completed_message = $5 + WHERE id = $1` + _, err := s.db.Exec(queryString, r.ID, r.Completed, r.CompletedAt, r.CompletedBy, r.CompletedMessage) + return r, err +} + +func (s requestService) DeleteRequest(r geeksbot.Request) error { + queryString := "DELETE FROM requests WHERE id = $1" + _, err := s.db.Exec(queryString, r.ID) + return err +} + +func (s requestService) Comment(id int64) (geeksbot.Comment, error) { + var c geeksbot.Comment + var aID string + var rID int64 + queryString := "SELECT id, author_id, request_id, comment_at, content WHERE id = $1" + row := s.db.QueryRow(queryString, id) + err := row.Scan(&c.ID, &aID, &rID, &c.CommentAt, &c.Content) + if err != nil { + return geeksbot.Comment{}, err + } + author, err := UserService.User(aID) + if err != nil { + return geeksbot.Comment{}, err + } + c.Author = author + request, err := s.Request(rID) + if err != nil { + return geeksbot.Comment{}, err + } + c.Request = request + return c, nil +} + +func (s requestService) RequestComments(r geeksbot.Request) ([]geeksbot.Comment, error) { + var comments []geeksbot.Comment + queryString := "SELECT id FROM comments WHERE request_id = $1" + rows, err := s.db.Query(queryString, r.ID) + if err != nil { + return nil, err + } + for rows.Next() { + var id int64 + err := rows.Scan(&id) + if err != nil { + log.Println(err) + continue + } + comment, err := s.Comment(id) + if err != nil { + log.Println(err) + continue + } + comments = append(comments, comment) + } + return comments, nil +} + +func (s requestService) RequestCommentCount(r geeksbot.Request) (int, error) { + var count int + queryString := "SELECT COUNT(id) FROM comments WHERE request_id = $1" + row := s.db.QueryRow(queryString, r.ID) + err := row.Scan(&count) + return count, err +} + +func (s requestService) CreateComment(c geeksbot.Comment) (geeksbot.Comment, error) { + queryString := `INSERT INTO comments (author_id, request_id, comment_at, content) + VALUES ($1, $2, $3, $4) RETURNING id` + var id int64 + err := s.db.QueryRow(queryString, c.Author.ID, c.Request.ID, c.CommentAt, c.Content).Scan(&id) + if err != nil { + return geeksbot.Comment{}, err + } + c.ID = id + return c, nil +} + +func (s requestService) DeleteComment(c geeksbot.Comment) error { + queryString := "DELETE FROM comments WHERE id = $1" + _, err := s.db.Exec(queryString, c.ID) + return err +} diff --git a/internal/database/server.go b/internal/database/server.go new file mode 100644 index 0000000..8a9c3a8 --- /dev/null +++ b/internal/database/server.go @@ -0,0 +1,138 @@ +package database + +import ( + "database/sql" + "log" + + "github.com/dustinpianalto/geeksbot" +) + +type serverService struct { + db *sql.DB +} + +func (s serverService) ServerByID(id int) (geeksbot.Server, error) { + var server geeksbot.Server + var guildID string + var aChanID string + var iChanID string + var iMsgID string + var sMsgID string + queryString := `SELECT id, name, ip_address, port, password, alerts_channel_id, + guild_id, info_channel_id, info_message_id, settings_message_id + FROM servers WHERE id = $1` + row := s.db.QueryRow(queryString, id) + err := row.Scan(&server.ID, &server.Name, &server.IPAddr, &server.Port, &server.Password, + &aChanID, &guildID, &iChanID, &iMsgID, &sMsgID) + if err != nil { + return geeksbot.Server{}, err + } + guild, err := GuildService.Guild(guildID) + if err != nil { + return geeksbot.Server{}, err + } + alertChannel, err := ChannelService.Channel(aChanID) + if err != nil { + return geeksbot.Server{}, err + } + infoChannel, err := ChannelService.Channel(iChanID) + if err != nil { + return geeksbot.Server{}, err + } + infoMessage, err := MessageService.Message(iMsgID) + if err != nil { + return geeksbot.Server{}, err + } + settingsMessage, err := MessageService.Message(sMsgID) + if err != nil { + return geeksbot.Server{}, err + } + server.Guild = guild + server.AlertsChannel = alertChannel + server.InfoChannel = infoChannel + server.InfoMessage = infoMessage + server.SettingsMessage = settingsMessage + return server, nil +} + +func (s serverService) ServerByName(name string, guild geeksbot.Guild) (geeksbot.Server, error) { + var id int + queryString := "SELECT id FROM servers WHERE name = $1 AND guild_id = $2" + row := s.db.QueryRow(queryString, name, guild.ID) + err := row.Scan(&id) + if err != nil { + return geeksbot.Server{}, err + } + server, err := s.ServerByID(id) + return server, err +} + +func (s serverService) CreateServer(server geeksbot.Server) (geeksbot.Server, error) { + var id int + queryString := `INSERT INTO servers (name, ip_address, port, password, alerts_channel_id, + guild_id, info_channel_id, info_message_id, settings_message_id) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id` + err := s.db.QueryRow(queryString, + server.Name, + server.IPAddr, + server.Port, + server.Password, + server.AlertsChannel, + server.Guild, + server.InfoChannel, + server.InfoMessage, + server.SettingsMessage, + ).Scan(&id) + if err != nil { + return geeksbot.Server{}, err + } + server.ID = id + return server, nil +} + +func (s serverService) DeleteServer(server geeksbot.Server) error { + queryString := `DELETE FROM servers WHERE id = $1` + _, err := s.db.Exec(queryString, server.ID) + return err +} + +func (s serverService) UpdateServer(server geeksbot.Server) (geeksbot.Server, error) { + queryString := `UPDATE servers SET name = $2, ip_address = $3, port = $4, password = $5, + alerts_channel_id = $6, info_channel_id = $7, info_message_id = $8, + settings_message_id = $9 WHERE id = $1` + _, err := s.db.Exec(queryString, + server.Name, + server.IPAddr, + server.Port, + server.Password, + server.AlertsChannel.ID, + server.InfoChannel.ID, + server.InfoMessage.ID, + server.SettingsMessage.ID, + ) + return server, err +} + +func (s serverService) GuildServers(g geeksbot.Guild) ([]geeksbot.Server, error) { + var servers []geeksbot.Server + queryString := `SELECT id FROM servers WHERE guild_id = $1` + rows, err := s.db.Query(queryString, g.ID) + if err != nil { + return nil, err + } + for rows.Next() { + var id int + err = rows.Scan(&id) + if err != nil { + log.Println(err) + continue + } + server, err := s.ServerByID(id) + if err != nil { + log.Println(err) + continue + } + servers = append(servers, server) + } + return servers, nil +} diff --git a/internal/database/user.go b/internal/database/user.go new file mode 100644 index 0000000..ced3758 --- /dev/null +++ b/internal/database/user.go @@ -0,0 +1,37 @@ +package database + +import ( + "database/sql" + + "github.com/dustinpianalto/geeksbot" +) + +type userService struct { + db *sql.DB +} + +func (s userService) User(id string) (geeksbot.User, error) { + var user geeksbot.User + queryString := "SELECT id, steam_id, active, staff, admin WHERE id = $1" + row := s.db.QueryRow(queryString, id) + err := row.Scan(&user.ID, &user.SteamID, &user.IsActive, &user.IsStaff, &user.IsAdmin) + return user, err +} + +func (s userService) CreateUser(u geeksbot.User) (geeksbot.User, error) { + queryString := "INSERT INTO users (id, steam_id, active, staff, admin) VALUES ($1, $2, $3, $4, $5)" + _, err := s.db.Exec(queryString, u.ID, u.SteamID, u.IsActive, u.IsStaff, u.IsAdmin) + return u, err +} + +func (s userService) DeleteUser(u geeksbot.User) error { + queryString := "DELETE FROM users WHERE id = $1" + _, err := s.db.Exec(queryString, u.ID) + return err +} + +func (s userService) UpdateUser(u geeksbot.User) (geeksbot.User, error) { + queryString := "UPDATE users SET steam_id = $2, active = $3, staff = $4, admin = $5 WHERE id = $1" + _, err := s.db.Exec(queryString, u.ID, u.SteamID, u.IsActive, u.IsStaff, u.IsAdmin) + return u, err +} diff --git a/message.go b/message.go index 3a2fb19..7316e91 100644 --- a/message.go +++ b/message.go @@ -1,23 +1,19 @@ package geeksbot -import "github.com/bwmarrin/discordgo" - type Message struct { ID string CreatedAt int64 ModifiedAt int64 Content string PreviousContent []string - Channel *Channel - Author *User - Embed *discordgo.MessageEmbed - PreviousEmbeds []*discordgo.MessageEmbed + Channel Channel + Author User } type MessageService interface { - Message(id string) (*Message, error) - CreateMessage(m *Message) (*Message, error) - DeleteMessage(m *Message) error - ChannelMessages(c *Channel) ([]*Message, error) - UpdateMessage(m *Message) (*Message, error) + Message(id string) (Message, error) + CreateMessage(m Message) (Message, error) + DeleteMessage(m Message) error + ChannelMessages(c Channel) ([]Message, error) + UpdateMessage(m Message) (Message, error) } diff --git a/patreon.go b/patreon.go index eed2f00..e2baf85 100644 --- a/patreon.go +++ b/patreon.go @@ -4,28 +4,29 @@ type PatreonCreator struct { ID int Creator string Link string - Guild *Guild + Guild Guild } type PatreonTier struct { ID int Name string Description string - Creator *PatreonCreator - Role *Role + Creator PatreonCreator + Role Role NextTier *PatreonTier } type PatreonService interface { - PatreonCreatorByID(id int) (*PatreonCreator, error) - PatreonCreatorByName(name string) (*PatreonCreator, error) - CreatePatreonCreator(c *PatreonCreator) (*PatreonCreator, error) - UpdatePatreonCreator(c *PatreonCreator) (*PatreonCreator, error) - DeletePatreonCreator(c *PatreonCreator) error - PatreonTierByID(id int) (*PatreonTier, error) - PatreonTierByName(name string) (*PatreonTier, error) - CreatePatreonTier(t *PatreonTier) (*PatreonTier, error) - UpdatePatreonTier(t *PatreonTier) (*PatreonTier, error) - DeletePatreonTier(t *PatreonTier) error - GuildPatreonCreators(g *Guild) ([]*PatreonCreator, error) + PatreonCreatorByID(id int) (PatreonCreator, error) + PatreonCreatorByName(name string) (PatreonCreator, error) + CreatePatreonCreator(c PatreonCreator) (PatreonCreator, error) + UpdatePatreonCreator(c PatreonCreator) (PatreonCreator, error) + DeletePatreonCreator(c PatreonCreator) error + PatreonTierByID(id int) (PatreonTier, error) + PatreonTierByName(name string, creator string) (PatreonTier, error) + CreatePatreonTier(t PatreonTier) (PatreonTier, error) + UpdatePatreonTier(t PatreonTier) (PatreonTier, error) + DeletePatreonTier(t PatreonTier) error + GuildPatreonCreators(g Guild) ([]PatreonCreator, error) + CreatorPatreonTiers(c PatreonCreator) ([]PatreonTier, error) } diff --git a/request.go b/request.go index 28b092e..bd7fd8a 100644 --- a/request.go +++ b/request.go @@ -4,34 +4,36 @@ import "time" type Request struct { ID int64 - Author *User - Channel *Channel + Author User + Channel Channel + Guild Guild Content string RequestedAt time.Time + Completed bool CompletedAt time.Time - CompletedBy *User - Message *Message + CompletedBy User + Message Message CompletedMessage string } type Comment struct { ID int64 - Author *User - Request *Request + Author User + Request Request CommentAt time.Time Content string } type RequestService interface { - Request(id int64) (*Request, error) - UserRequests(u *User, completed bool) ([]*Request, error) - GuildRequests(g *Guild, completed bool) ([]*Request, error) - CreateRequest(r *Request) (*Request, error) - UpdateRequest(r *Request) (*Request, error) - DeleteRequest(r *Request) error - Comment(id int64) (*Comment, error) - RequestComments(r *Request) ([]*Comment, error) - RequestCommentCount(r *Request) (int, error) - CreateComment(c *Comment) (*Comment, error) - DeleteComment(c *Comment) error + Request(id int64) (Request, error) + UserRequests(u User, completed bool) ([]Request, error) + GuildRequests(g Guild, completed bool) ([]Request, error) + CreateRequest(r Request) (Request, error) + UpdateRequest(r Request) (Request, error) + DeleteRequest(r Request) error + Comment(id int64) (Comment, error) + RequestComments(r Request) ([]Comment, error) + RequestCommentCount(r Request) (int, error) + CreateComment(c Comment) (Comment, error) + DeleteComment(c Comment) error } diff --git a/server.go b/server.go index faf731d..2a3af61 100644 --- a/server.go +++ b/server.go @@ -6,18 +6,18 @@ type Server struct { IPAddr string Port int Password string - AlertsChannel *Channel - Guild *Guild - InfoChannel *Channel - InfoMessage *Message - SettingsMessage *Message + AlertsChannel Channel + Guild Guild + InfoChannel Channel + InfoMessage Message + SettingsMessage Message } type ServerService interface { - ServerByID(id int) (*Server, error) - ServerByName(name string) (*Server, error) - CreateServer(s *Server) (*Server, error) - DeleteServer(s *Server) error - UpdateServer(s *Server) (*Server, error) - GuildServers(g *Guild) ([]*Server, error) + ServerByID(id int) (Server, error) + ServerByName(name string) (Server, error) + CreateServer(s Server) (Server, error) + DeleteServer(s Server) error + UpdateServer(s Server) (Server, error) + GuildServers(g Guild) ([]Server, error) } diff --git a/user.go b/user.go index 31a1f57..dcba7c9 100644 --- a/user.go +++ b/user.go @@ -11,8 +11,8 @@ type User struct { } type UserService interface { - User(id string) (*User, error) - CreateUser(u *User) (*User, error) - DeleteUser(u *User) error - UpdateUser(u *User) (*User, error) + User(id string) (User, error) + CreateUser(u User) (User, error) + DeleteUser(u User) error + UpdateUser(u User) (User, error) }