Skip to content

Commit

Permalink
Adds object storage
Browse files Browse the repository at this point in the history
  • Loading branch information
Snakeyesz committed Jun 20, 2019
1 parent 53ec88e commit c67cf35
Show file tree
Hide file tree
Showing 6 changed files with 258 additions and 7 deletions.
10 changes: 4 additions & 6 deletions events/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@ import (
"net/http"
"time"

"gitlab.com/Cacophony/go-kit/discord"

"github.com/bwmarrin/discordgo"
"github.com/go-redis/redis"
"github.com/jinzhu/gorm"

"gitlab.com/Cacophony/go-kit/paginator"

"github.com/bwmarrin/discordgo"
"gitlab.com/Cacophony/go-kit/discord"
"gitlab.com/Cacophony/go-kit/interfaces"
"gitlab.com/Cacophony/go-kit/paginator"
"gitlab.com/Cacophony/go-kit/state"
"go.uber.org/zap"
)
Expand Down Expand Up @@ -84,6 +81,7 @@ type Event struct {
db *gorm.DB
httpClient *http.Client
questionnaire *Questionnaire
storage *Storage
}

// BucketType specifies the scope of a bucket
Expand Down
9 changes: 9 additions & 0 deletions events/event_values.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ func (e *Event) Logger() *zap.Logger {
return e.logger
}

// WithStorage stores the storage bucket in the event
func (e *Event) WithStorage(storage *Storage) {
e.storage = storage
}

func (e *Event) Storage() *Storage {
return e.storage
}

// WithLocalizations stores the localizations in the event
func (e *Event) WithLocalizations(localizations []interfaces.Localization) {
e.localizations = localizations
Expand Down
25 changes: 25 additions & 0 deletions events/storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package events

import (
"github.com/jinzhu/gorm"
"go.uber.org/zap"
"gocloud.dev/blob"
)

type Storage struct {
logger *zap.Logger
db *gorm.DB
bucket *blob.Bucket
}

func NewStorage(
logger *zap.Logger,
db *gorm.DB,
bucket *blob.Bucket,
) *Storage {
return &Storage{
logger: logger,
db: db,
bucket: bucket,
}
}
193 changes: 193 additions & 0 deletions events/storage_file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
package events

import (
"errors"
"io/ioutil"
"math/rand"
"net/http"
"time"

"github.com/bwmarrin/discordgo"
"github.com/jinzhu/gorm"
)

const (
noStorageError string = "Event storage is Nil"
noFileData string = "No file data."
noFileInfo string = "No file info found."

fileIdCharacters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
fileIdLength = 8
)

var (
objectStorageFQDN = ""
objectStorageBucketName = ""
)

type FileInfo struct {
gorm.Model

Filename string
UserID string
ChannelID string
GuildID string
FileID string
Source string
MimeType string
UploadDate time.Time
Filesize int
RetrievedCount int
Public bool
CustomCommandID uint
}

func (f *FileInfo) TableName() string {
return "object_storage"
}

func (f *FileInfo) GetLink() string {
if objectStorageFQDN != "" {
return "https://" + objectStorageFQDN + "/" + f.bucketKey()
}

if objectStorageBucketName != "" {
return "https://storage.googleapis.com/" + objectStorageBucketName + "/" + f.bucketKey()
}

return ""
}

func (f *FileInfo) bucketKey() string {
return f.FileID + "/" + f.Filename
}

func InitObjectStorage(db *gorm.DB, fqdn string, bucketName string) error {

// objectStorageFQDN = fqdn
objectStorageBucketName = bucketName

rand.Seed(time.Now().UTC().UnixNano())
return db.AutoMigrate(FileInfo{}).Error
}

func (e *Event) AddFile(data []byte, file *FileInfo) (*FileInfo, error) {
if e.storage == nil {
return nil, errors.New(noStorageError)
}

if len(data) == 0 {
return nil, errors.New(noFileData)
}

if file.FileID == "" {
newFileID, err := getUniqueFileId(e.DB())
if err != nil {
return nil, err
}
file.FileID = newFileID
}

err := saveFileToDB(e.DB(), file)
if err != nil {
return nil, err
}

err = e.storage.bucket.WriteAll(e.Context(), file.bucketKey(), data, nil)
if err != nil {
return nil, err
}

return file, nil
}

func (e *Event) DeleteFile(file *FileInfo) error {
if e.storage == nil {
return errors.New(noStorageError)
}

if file.Filename == "" {
return errors.New(noFileInfo)
}

err := deleteFileFromDB(e.DB(), file)
if err != nil {
return err
}

return e.storage.bucket.Delete(e.Context(), file.bucketKey())
}

func (e *Event) AddAttachement(attachement *discordgo.MessageAttachment) (*FileInfo, error) {

resp, err := e.HTTPClient().Get(attachement.URL)
if resp != nil && resp.Body != nil {
defer resp.Body.Close()
}

bytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}

uniqueId, err := getUniqueFileId(e.DB())
if err != nil {
return nil, err
}

return e.AddFile(bytes, &FileInfo{
Filename: attachement.Filename,
UserID: e.UserID,
ChannelID: e.ChannelID,
GuildID: e.GuildID,
FileID: uniqueId,
MimeType: http.DetectContentType(bytes),
UploadDate: time.Now(),
Source: attachement.URL,
Filesize: len(bytes),
Public: true,
})

}

func (e *Event) UpdateFileInfo(file FileInfo) error {
return e.DB().Update(file).Error
}

func getUniqueFileId(db *gorm.DB) (string, error) {

output := make([]byte, fileIdLength)
for i := range output {
output[i] = fileIdCharacters[rand.Intn(len(fileIdCharacters))]
}

var count int
err := db.
Model(FileInfo{}).
Where(FileInfo{FileID: string(output)}).
Count(&count).
Error
if count != 0 {
return getUniqueFileId(db)
}

return string(output), err
}

func saveFileToDB(db *gorm.DB, f *FileInfo) error {
if f.FileID == "" {
return errors.New(noFileInfo)
}

if db.NewRecord(f) {
return db.Create(f).Error
}
return db.Update(f).Error
}

func deleteFileFromDB(db *gorm.DB, f *FileInfo) error {
if f.FileID == "" {
return errors.New(noFileInfo)
}
return db.Delete(f).Error
}
2 changes: 1 addition & 1 deletion permissions/cacophony.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

const (
// DiscordCacophonyServerGuildID is the Guild ID of the Cacophony Guild
DiscordCacophonyServerGuildID = "435420687906111498"
DiscordCacophonyServerGuildID = "403003926720413699"
// DiscordCacophonyPatronRoleID is the Role ID of the Patron role on the Cacophony Guild
DiscordCacophonyPatronRoleID = "578650002361155626"
)
Expand Down
26 changes: 26 additions & 0 deletions storage/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package storage

import (
"context"

"gocloud.dev/blob"
"gocloud.dev/blob/gcsblob"
"gocloud.dev/gcp"
)

func NewStorageBucket(ctx context.Context, bucketName string) (*blob.Bucket, error) {
creds, err := gcp.DefaultCredentials(ctx)
if err != nil {
return nil, err
}

client, err := gcp.NewHTTPClient(
gcp.DefaultTransport(),
gcp.CredentialsTokenSource(creds),
)
if err != nil {
return nil, err
}

return gcsblob.OpenBucket(ctx, client, bucketName, nil)
}

0 comments on commit c67cf35

Please sign in to comment.