/
upload_images.go
132 lines (110 loc) · 3.81 KB
/
upload_images.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2023 E99p1ant. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package db
import (
"context"
"encoding/json"
"github.com/pkg/errors"
"github.com/samber/lo"
"gorm.io/datatypes"
"gorm.io/gorm"
)
var UploadImgaes UploadImagesStore
var _ UploadImagesStore = (*uploadImages)(nil)
type UploadImagesStore interface {
Create(ctx context.Context, opts CreateUploadImageOptions) (*UploadImage, error)
GetByQuestionID(ctx context.Context, questionID uint) ([]*UploadImage, error)
GetByTypeQuestionID(ctx context.Context, typ UploadImageQuestionType, questionID uint) ([]*UploadImage, error)
}
func NewUploadImagesStore(db *gorm.DB) UploadImagesStore {
return &uploadImages{db}
}
type uploadImages struct {
*gorm.DB
}
type UploadImage struct {
gorm.Model
UploaderUserID uint
Name string
FileSize int64
Md5 string
Key string
PublicURLs datatypes.JSON
}
type UploadImageQuestionType string
const (
UploadImageQuestionTypeAsk UploadImageQuestionType = "ask"
UploadImageQuestionTypeAnswer UploadImageQuestionType = "answer"
)
type UploadImageQuestion struct {
Type UploadImageQuestionType
UploadImageID uint
QuestionID uint
}
type CreateUploadImageOptions struct {
Type UploadImageQuestionType
QuestionID uint
UploaderUserID uint
Name string
FileSize int64
Md5 string
Key string
PublicURLs map[string]string
IsDeletingPrevious bool
}
func (db *uploadImages) Create(ctx context.Context, opts CreateUploadImageOptions) (*UploadImage, error) {
publicURLsJson, err := json.Marshal(opts.PublicURLs)
if err != nil {
return nil, errors.Wrap(err, "marshal public urls")
}
image := &UploadImage{
UploaderUserID: opts.UploaderUserID,
Name: opts.Name,
FileSize: opts.FileSize,
Md5: opts.Md5,
Key: opts.Key,
PublicURLs: datatypes.JSON(publicURLsJson),
}
if err := db.Transaction(func(tx *gorm.DB) error {
if err := tx.WithContext(ctx).Create(image).Error; err != nil {
return errors.Wrap(err, "create image")
}
if opts.IsDeletingPrevious {
if err := tx.WithContext(ctx).Where("type = ? AND question_id = ?", opts.Type, opts.QuestionID).Delete(&UploadImageQuestion{}).Error; err != nil {
return errors.Wrap(err, "delete previous image question link")
}
}
if err := tx.WithContext(ctx).Create(&UploadImageQuestion{
Type: opts.Type,
UploadImageID: image.ID,
QuestionID: opts.QuestionID,
}).Error; err != nil {
return errors.Wrap(err, "create image question link")
}
return nil
}); err != nil {
return nil, err
}
return image, nil
}
func (db *uploadImages) getBy(ctx context.Context, where string, args ...interface{}) ([]*UploadImage, error) {
var uploadImageQuestions []*UploadImageQuestion
if err := db.WithContext(ctx).Model(&UploadImageQuestion{}).Where(where, args...).Find(&uploadImageQuestions).Error; err != nil {
return nil, errors.Wrap(err, "get image questions")
}
uploadImageIDs := lo.Map(uploadImageQuestions, func(item *UploadImageQuestion, _ int) uint {
return item.UploadImageID
})
var uploadImages []*UploadImage
if err := db.WithContext(ctx).Model(&UploadImage{}).Where("id IN ?", uploadImageIDs).Order("id ASC").Find(&uploadImages).Error; err != nil {
return nil, errors.Wrap(err, "get images")
}
return uploadImages, nil
}
func (db *uploadImages) GetByQuestionID(ctx context.Context, questionID uint) ([]*UploadImage, error) {
return db.getBy(ctx, "question_id = ?", questionID)
}
func (db *uploadImages) GetByTypeQuestionID(ctx context.Context, typ UploadImageQuestionType, questionID uint) ([]*UploadImage, error) {
return db.getBy(ctx, "type = ? AND question_id = ?", typ, questionID)
}