package util import ( "bytes" "encoding/json" "errors" "fmt" "mime/multipart" "net/http" "strconv" "strings" "sync" "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" "github.com/aws/aws-sdk-go/service/s3/s3manager" "github.com/happierall/l" "github.com/metarare/metarare_api/common" "github.com/metarare/metarare_api/models" "gorm.io/gorm" ) type AWSConfs struct { Region string BucketName string Access_key_id string Access_key string } type MetaPack struct { BoosterID int `json:"booster_id"` ID int `json:"id"` TxHash string `json:"tx_hash"` RandomNumber string `json:"random_number"` Image string `json:"image"` ExternalURL string `json:"external_url"` Description string `json:"description"` Name string `json:"name"` Attributes []Trait `json:"attributes"` AnimationURL string `json:"animation_url,omitempty"` Signature string `json:"signature"` } type Trait struct { TraitType string `json:"trait_type,omitempty"` Value string `json:"value,omitempty"` } //NOTE x AppendData func AppendData(prevData interface{}, dataObject interface{}, key string) map[string]interface{} { prev, _ := json.Marshal(prevData) convert := map[string]interface{}{} if prevData != nil { json.Unmarshal(prev, &convert) } datas, err := json.Marshal(dataObject) if err != nil { return nil } new := map[string]interface{}{} err = json.Unmarshal(datas, &new) if err != nil { var payload interface{} json.Unmarshal(datas, &payload) convert[key] = payload } for k, v := range new { convert[k] = v } return convert } func GetCredentials(awsConf AWSConfs) (*session.Session, error) { return session.NewSession(&aws.Config{ Region: aws.String(awsConf.Region), Credentials: credentials.NewStaticCredentials(awsConf.Access_key_id, awsConf.Access_key, ""), }) } var mutex sync.Mutex func UploadToS3(awsConf AWSConfs, path string, header *multipart.FileHeader) (string, error) { mutex.Lock() s, err := GetCredentials(awsConf) if err != nil { return "", err } file, err := header.Open() if err != nil { return "", err } fileSize := header.Size buffer := make([]byte, fileSize) file.Read(buffer) var obj *s3.PutObjectOutput now := time.Now() _split := strings.Split(header.Filename, ".") _extension := _split[len(_split)-1] _hex := common.GenerateRandomString(10, "") time := now.UnixNano() / 1000000 formattedFileName := fmt.Sprintf("%s_%d.%s", _hex, time, _extension) // runeFileName := []rune(header.Filename) // index2 := float64(len(runeFileName)) - math.Min(float64(len(runeFileName)), 10) // str := runeFileName[int(index2):] // tailOfFile := "" // for _, r := range str { // tailOfFile = fmt.Sprintf("%s%s", tailOfFile, string(r)) // } // formattedFileName := fmt.Sprintf("%s_%s_%s_%s", // fmt.Sprintf("%04d%02d%02d", now.Year(), now.Month(), now.Day()), // fmt.Sprintf("%02d%02d%02d", now.Hour(), now.Minute(), now.Second()), // fmt.Sprintf("%03d", now.Nanosecond()/1000000), // fmt.Sprintf("%s", tailOfFile), // ) k := fmt.Sprintf("%s/%s", path, formattedFileName, ) extension := strings.Split(formattedFileName, ".") if extension[len(extension)-1] != "gif" { //NOTE x resize image imgResize := &ContentsCenter{} if pbImage, err := imgResize.Resize(buffer); err == nil { buffer = make([]byte, len(pbImage)) workingEleCount := copy(buffer, pbImage) fmt.Printf("copied ele count : %d", workingEleCount) } } obj, err = s3.New(s).PutObject(&s3.PutObjectInput{ Bucket: aws.String(awsConf.BucketName), Key: aws.String(k), ACL: aws.String("public-read"), Body: bytes.NewReader(buffer), ContentLength: aws.Int64(int64(len(buffer))), ContentType: aws.String(http.DetectContentType(buffer)), ContentDisposition: aws.String("attachment"), ServerSideEncryption: aws.String("AES256"), }) if err != nil { l.Error(err, obj) return "", err } url := "https://s3.%s.amazonaws.com/%s/%s" url = fmt.Sprintf(url, awsConf.Region, awsConf.BucketName, k) l.Log("uploaded file link : ", url) mutex.Unlock() return url, err } func UploadToMetaJson(awsConf AWSConfs, fileName string, serializedData []byte) (string, error) { s, err := GetCredentials(awsConf) if err != nil { return "", err } uploader := s3manager.NewUploader(s) _, err = uploader.Upload(&s3manager.UploadInput{ Bucket: aws.String(awsConf.BucketName), Key: aws.String(fileName), ACL: aws.String("public-read"), Body: bytes.NewReader(serializedData), }) if err != nil { return "", fmt.Errorf("Error occurred while s3uploader", err.Error()) } filePath := "https://nftinfo.meta-rare.net/" + fileName return filePath, nil } func MakeMetaData(awsConf AWSConfs, db *gorm.DB, tokenID uint64, txHash string, name string, description string, assets string) error { _tokneID := strconv.FormatUint(tokenID, 10) meta := MetaPack{ BoosterID: 0, ID: int(tokenID), TxHash: txHash, RandomNumber: common.GenerateRandomNumber(32), Name: name, Description: description, ExternalURL: `https://nftinfo.meta-rare.net/` + _tokneID, } str := strings.Split(assets, ".") kind := str[len(str)-1] if kind == "mp4" { meta.AnimationURL = assets meta.Image = assets } else { meta.Image = assets } _t := []models.Traits{} err := db.Where("token_id = ?", tokenID).Find(&_t).Error if errors.Is(err, gorm.ErrRecordNotFound) { fmt.Printf("%s", err) } _trait := make([]Trait, 0) for _, item := range _t { _trait = append(_trait, Trait{TraitType: item.Key, Value: item.Value}) } meta.Attributes = _trait serializedData, _ := json.Marshal(meta) path, _err := UploadToMetaJson(awsConf, _tokneID, serializedData) if _err != nil { fmt.Print(err.Error()) return _err } else { fmt.Println("path :", path) } return nil }