2021-05-17 17:06:58 +00:00
/ *
GoToSocial
Copyright ( C ) 2021 GoToSocial Authors admin @ gotosocial . org
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU Affero General Public License for more details .
You should have received a copy of the GNU Affero General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
* /
package media
import (
"errors"
"fmt"
"strings"
"time"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
2021-06-13 16:42:28 +00:00
"github.com/superseriousbusiness/gotosocial/internal/id"
2021-05-17 17:06:58 +00:00
)
2021-09-04 12:02:01 +00:00
func ( mh * mediaHandler ) processImageAttachment ( data [ ] byte , minAttachment * gtsmodel . MediaAttachment ) ( * gtsmodel . MediaAttachment , error ) {
2021-05-17 17:06:58 +00:00
var clean [ ] byte
var err error
var original * imageAndMeta
var small * imageAndMeta
2021-09-04 12:02:01 +00:00
contentType := minAttachment . File . ContentType
2021-05-17 17:06:58 +00:00
switch contentType {
case MIMEJpeg , MIMEPng :
if clean , err = purgeExif ( data ) ; err != nil {
return nil , fmt . Errorf ( "error cleaning exif data: %s" , err )
}
original , err = deriveImage ( clean , contentType )
if err != nil {
return nil , fmt . Errorf ( "error parsing image: %s" , err )
}
case MIMEGif :
clean = data
original , err = deriveGif ( clean , contentType )
if err != nil {
return nil , fmt . Errorf ( "error parsing gif: %s" , err )
}
default :
return nil , errors . New ( "media type unrecognized" )
}
small , err = deriveThumbnail ( clean , contentType , 256 , 256 )
if err != nil {
return nil , fmt . Errorf ( "error deriving thumbnail: %s" , err )
}
2021-06-13 16:42:28 +00:00
// now put it in storage, take a new id for the name of the file so we don't store any unnecessary info about it
2021-05-17 17:06:58 +00:00
extension := strings . Split ( contentType , "/" ) [ 1 ]
2021-06-13 16:42:28 +00:00
newMediaID , err := id . NewRandomULID ( )
if err != nil {
return nil , err
}
2021-05-17 17:06:58 +00:00
URLbase := fmt . Sprintf ( "%s://%s%s" , mh . config . StorageConfig . ServeProtocol , mh . config . StorageConfig . ServeHost , mh . config . StorageConfig . ServeBasePath )
2021-09-04 12:02:01 +00:00
originalURL := fmt . Sprintf ( "%s/%s/attachment/original/%s.%s" , URLbase , minAttachment . AccountID , newMediaID , extension )
smallURL := fmt . Sprintf ( "%s/%s/attachment/small/%s.jpeg" , URLbase , minAttachment . AccountID , newMediaID ) // all thumbnails/smalls are encoded as jpeg
2021-05-17 17:06:58 +00:00
// we store the original...
2021-09-04 12:02:01 +00:00
originalPath := fmt . Sprintf ( "%s/%s/%s/%s/%s.%s" , mh . config . StorageConfig . BasePath , minAttachment . AccountID , Attachment , Original , newMediaID , extension )
2021-05-17 17:06:58 +00:00
if err := mh . storage . StoreFileAt ( originalPath , original . image ) ; err != nil {
return nil , fmt . Errorf ( "storage error: %s" , err )
}
// and a thumbnail...
2021-09-04 12:02:01 +00:00
smallPath := fmt . Sprintf ( "%s/%s/%s/%s/%s.jpeg" , mh . config . StorageConfig . BasePath , minAttachment . AccountID , Attachment , Small , newMediaID ) // all thumbnails/smalls are encoded as jpeg
2021-05-17 17:06:58 +00:00
if err := mh . storage . StoreFileAt ( smallPath , small . image ) ; err != nil {
return nil , fmt . Errorf ( "storage error: %s" , err )
}
2021-09-04 12:02:01 +00:00
minAttachment . FileMeta . Original = gtsmodel . Original {
Width : original . width ,
Height : original . height ,
Size : original . size ,
Aspect : original . aspect ,
}
minAttachment . FileMeta . Small = gtsmodel . Small {
Width : small . width ,
Height : small . height ,
Size : small . size ,
Aspect : small . aspect ,
}
attachment := & gtsmodel . MediaAttachment {
ID : newMediaID ,
StatusID : minAttachment . StatusID ,
URL : originalURL ,
RemoteURL : minAttachment . RemoteURL ,
CreatedAt : minAttachment . CreatedAt ,
UpdatedAt : minAttachment . UpdatedAt ,
Type : gtsmodel . FileTypeImage ,
FileMeta : minAttachment . FileMeta ,
AccountID : minAttachment . AccountID ,
Description : minAttachment . Description ,
ScheduledStatusID : minAttachment . ScheduledStatusID ,
2021-05-17 17:06:58 +00:00
Blurhash : original . blurhash ,
Processing : 2 ,
File : gtsmodel . File {
Path : originalPath ,
ContentType : contentType ,
FileSize : len ( original . image ) ,
UpdatedAt : time . Now ( ) ,
} ,
Thumbnail : gtsmodel . Thumbnail {
Path : smallPath ,
ContentType : MIMEJpeg , // all thumbnails/smalls are encoded as jpeg
FileSize : len ( small . image ) ,
UpdatedAt : time . Now ( ) ,
URL : smallURL ,
2021-09-04 12:02:01 +00:00
RemoteURL : minAttachment . Thumbnail . RemoteURL ,
2021-05-17 17:06:58 +00:00
} ,
2021-09-04 12:02:01 +00:00
Avatar : minAttachment . Avatar ,
Header : minAttachment . Header ,
2021-05-17 17:06:58 +00:00
}
2021-09-04 12:02:01 +00:00
return attachment , nil
2021-05-17 17:06:58 +00:00
}