diff --git a/common/storage/drives/imgur.go b/common/storage/drives/imgur.go new file mode 100644 index 00000000..417980c9 --- /dev/null +++ b/common/storage/drives/imgur.go @@ -0,0 +1,77 @@ +package drives + +import ( + "bytes" + "fmt" + "net/http" + "one-api/common/requester" +) + +var imgurUploadURL = "https://api.imgur.com/3/image" + +type ImgurUpload struct { + ClientId string +} + +func NewImgurUpload(clientId string) *ImgurUpload { + return &ImgurUpload{ + ClientId: clientId, + } +} + +type ImgurResponse struct { + Status int `json:"status"` + Success bool `json:"success"` + Data ImgurData `json:"data,omitempty"` +} + +type ImgurData struct { + Link string `json:"link"` +} + +func (i *ImgurUpload) Name() string { + return "Imgur" +} + +func (i *ImgurUpload) Upload(data []byte, fileName string) (string, error) { + client := requester.NewHTTPRequester("", nil) + + var formBody bytes.Buffer + builder := client.CreateFormBuilder(&formBody) + + err := builder.CreateFormFileReader("image", bytes.NewReader(data), fileName) + if err != nil { + return "", fmt.Errorf("creating form file: %w", err) + } + builder.Close() + + headers := map[string]string{ + "Authorization": "Client-ID " + i.ClientId, + } + + req, err := client.NewRequest( + http.MethodPost, + imgurUploadURL, + client.WithBody(&formBody), + client.WithHeader(headers), + client.WithContentType(builder.FormDataContentType())) + req.ContentLength = int64(formBody.Len()) + + if err != nil { + return "", fmt.Errorf("new request failed: %w", err) + } + + defer req.Body.Close() + + imgurResponse := &ImgurResponse{} + _, errWithCode := client.SendRequest(req, imgurResponse, false) + if errWithCode != nil { + return "", fmt.Errorf("%s", errWithCode.Message) + } + + if !imgurResponse.Success { + return "", fmt.Errorf("upload failed Status: %d", imgurResponse.Status) + } + + return imgurResponse.Data.Link, nil +} diff --git a/common/storage/drives/sm.go b/common/storage/drives/sm.go index 163f7416..848de7f6 100644 --- a/common/storage/drives/sm.go +++ b/common/storage/drives/sm.go @@ -31,7 +31,7 @@ type SMResponse struct { Success bool `json:"success"` Code string `json:"code"` Message string `json:"message"` - Data SMData `json:"data"` + Data SMData `json:"data,omitempty"` RequestID string `json:"RequestId"` } @@ -56,6 +56,7 @@ func (sm *SMUpload) Upload(data []byte, fileName string) (string, error) { return "", fmt.Errorf("creating form file: %w", err) } builder.WriteField("format", "json") + builder.Close() headers := map[string]string{ "Content-type": "application/json", diff --git a/common/storage/storage.go b/common/storage/storage.go index b1d36f70..7aa64626 100644 --- a/common/storage/storage.go +++ b/common/storage/storage.go @@ -11,6 +11,7 @@ type Storage struct { } func InitStorage() { + InitImgurStorage() InitSMStorage() } @@ -23,3 +24,13 @@ func InitSMStorage() { smUpload := drives.NewSMUpload(smSecret) AddStorageDrive(smUpload) } + +func InitImgurStorage() { + imgurClientId := viper.GetString("storage.imgur.client_id") + if imgurClientId == "" { + return + } + + imgurUpload := drives.NewImgurUpload(imgurClientId) + AddStorageDrive(imgurUpload) +} diff --git a/common/storage/storage_test.go b/common/storage/storage_test.go index 8711d943..4a0a3705 100644 --- a/common/storage/storage_test.go +++ b/common/storage/storage_test.go @@ -38,6 +38,22 @@ func TestSMMSUpload(t *testing.T) { assert.Nil(t, err) } +func TestImgurUpload(t *testing.T) { + InitConfig() + imgurClientId := viper.GetString("storage.imgur.client_id") + imgurUpload := drives.NewImgurUpload(imgurClientId) + + image, err := base64.StdEncoding.DecodeString(testImageB64) + if err != nil { + fmt.Println(err) + } + + url, err := imgurUpload.Upload(image, common.GetUUID()+".png") + fmt.Println(url) + fmt.Println(err) + assert.Nil(t, err) +} + // func TestSMMSUploadError(t *testing.T) { // InitConfig() // access_token := viper.GetString("notify.dingtalk.token") diff --git a/config.example.yaml b/config.example.yaml index 4b775352..efaebd86 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -63,4 +63,6 @@ notify: # 通知设置, 配置了几个通知方式,就会同时发送几次 chat_id: "" # 你的 Telegram chat_id storage: # 存储设置 (可选,主要用于图片生成,有些供应商不提供url,只能返回base64图片,设置后可以正常返回url格式的图片生成) smms: # sm.ms 图床设置 - secret: "" # 你的 sm.ms API 密钥 \ No newline at end of file + secret: "" # 你的 sm.ms API 密钥 + imgur: + client_id: "" # 你的 imgur client_id \ No newline at end of file