Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[chore] media pipeline improvements #3110

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cmd/process-emoji/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"os/signal"
"syscall"

"codeberg.org/gruf/go-logger/v2/level"
"codeberg.org/gruf/go-storage/memory"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db/bundb"
Expand All @@ -40,6 +41,8 @@ func main() {
ctx, cncl := signal.NotifyContext(ctx, syscall.SIGTERM, syscall.SIGINT)
defer cncl()

log.SetLevel(level.INFO)

if len(os.Args) != 3 {
log.Panic(ctx, "Usage: go run ./cmd/process-emoji <input-file> <output-static>")
}
Expand Down
3 changes: 3 additions & 0 deletions cmd/process-media/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"os/signal"
"syscall"

"codeberg.org/gruf/go-logger/v2/level"
"codeberg.org/gruf/go-storage/memory"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db/bundb"
Expand All @@ -39,6 +40,8 @@ func main() {
ctx, cncl := signal.NotifyContext(ctx, syscall.SIGTERM, syscall.SIGINT)
defer cncl()

log.SetLevel(level.INFO)

if len(os.Args) != 4 {
log.Panic(ctx, "Usage: go run ./cmd/process-media <input-file> <output-processed> <output-thumbnail>")
}
Expand Down
2 changes: 1 addition & 1 deletion internal/api/client/accounts/mute.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func (m *Module) AccountMutePOSTHandler(c *gin.Context) {

func normalizeCreateUpdateMute(form *apimodel.UserMuteCreateUpdateRequest) error {
// Apply defaults for missing fields.
form.Notifications = util.Ptr(util.PtrValueOr(form.Notifications, false))
form.Notifications = util.Ptr(util.PtrOrValue(form.Notifications, false))

// Normalize mute duration if necessary.
// If we parsed this as JSON, expires_in
Expand Down
4 changes: 2 additions & 2 deletions internal/api/client/filters/v1/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ func validateNormalizeCreateUpdateFilter(form *model.FilterCreateUpdateRequestV1
}

// Apply defaults for missing fields.
form.WholeWord = util.Ptr(util.PtrValueOr(form.WholeWord, false))
form.Irreversible = util.Ptr(util.PtrValueOr(form.Irreversible, false))
form.WholeWord = util.Ptr(util.PtrOrValue(form.WholeWord, false))
form.Irreversible = util.Ptr(util.PtrOrValue(form.Irreversible, false))

if *form.Irreversible {
return errors.New("irreversible aka server-side drop filters are not supported yet")
Expand Down
2 changes: 1 addition & 1 deletion internal/api/client/filters/v2/filterkeywordget_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (suite *FiltersTestSuite) TestGetFilterKeyword() {
suite.NotEmpty(filterKeyword)
suite.Equal(expectedFilterKeyword.ID, filterKeyword.ID)
suite.Equal(expectedFilterKeyword.Keyword, filterKeyword.Keyword)
suite.Equal(util.PtrValueOr(expectedFilterKeyword.WholeWord, false), filterKeyword.WholeWord)
suite.Equal(util.PtrOrValue(expectedFilterKeyword.WholeWord, false), filterKeyword.WholeWord)
}

func (suite *FiltersTestSuite) TestGetAnotherAccountsFilterKeyword() {
Expand Down
2 changes: 1 addition & 1 deletion internal/api/client/filters/v2/filterkeywordpost.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func validateNormalizeCreateUpdateFilterKeyword(form *apimodel.FilterKeywordCrea
return err
}

form.WholeWord = util.Ptr(util.PtrValueOr(form.WholeWord, false))
form.WholeWord = util.Ptr(util.PtrOrValue(form.WholeWord, false))

return nil
}
4 changes: 2 additions & 2 deletions internal/api/client/filters/v2/filterpost.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ func validateNormalizeCreateFilter(form *apimodel.FilterCreateRequestV2) error {
if err := validate.FilterTitle(form.Title); err != nil {
return err
}
action := util.PtrValueOr(form.FilterAction, apimodel.FilterActionWarn)
action := util.PtrOrValue(form.FilterAction, apimodel.FilterActionWarn)
if err := validate.FilterAction(action); err != nil {
return err
}
Expand Down Expand Up @@ -253,7 +253,7 @@ func validateNormalizeCreateFilter(form *apimodel.FilterCreateRequestV2) error {
if err := validate.FilterKeyword(formKeyword.Keyword); err != nil {
return err
}
form.Keywords[i].WholeWord = util.Ptr(util.PtrValueOr(formKeyword.WholeWord, false))
form.Keywords[i].WholeWord = util.Ptr(util.PtrOrValue(formKeyword.WholeWord, false))
}
for _, formStatus := range form.Statuses {
if err := validate.ULID(formStatus.StatusID, "status_id"); err != nil {
Expand Down
4 changes: 2 additions & 2 deletions internal/api/client/filters/v2/filterput.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ func validateNormalizeUpdateFilter(form *apimodel.FilterUpdateRequestV2) error {
}
}

destroy := util.PtrValueOr(formKeyword.Destroy, false)
destroy := util.PtrOrValue(formKeyword.Destroy, false)
form.Keywords[i].Destroy = &destroy

if destroy && formKeyword.ID == nil {
Expand All @@ -305,7 +305,7 @@ func validateNormalizeUpdateFilter(form *apimodel.FilterUpdateRequestV2) error {
}
}

destroy := util.PtrValueOr(formStatus.Destroy, false)
destroy := util.PtrOrValue(formStatus.Destroy, false)
form.Statuses[i].Destroy = &destroy

switch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ func init() {
CreatedAt: account.CreatedAt,
Reason: account.Reason,
Privacy: newgtsmodel.Visibility(account.Privacy),
Sensitive: util.Ptr(util.PtrValueOr(account.Sensitive, false)),
Sensitive: util.Ptr(util.PtrOrValue(account.Sensitive, false)),
Language: account.Language,
StatusContentType: account.StatusContentType,
CustomCSS: account.CustomCSS,
EnableRSS: util.Ptr(util.PtrValueOr(account.EnableRSS, false)),
HideCollections: util.Ptr(util.PtrValueOr(account.HideCollections, false)),
EnableRSS: util.Ptr(util.PtrOrValue(account.EnableRSS, false)),
HideCollections: util.Ptr(util.PtrOrValue(account.HideCollections, false)),
}

// Insert the settings model.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// GoToSocial
// Copyright (C) GoToSocial Authors [email protected]
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// 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 migrations

import (
"context"

old_gtsmodel "github.com/superseriousbusiness/gotosocial/internal/db/bundb/migrations/20240715204203_media_pipeline_improvements"
new_gtsmodel "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"

"github.com/uptrace/bun"
)

func init() {
up := func(ctx context.Context, db *bun.DB) error {
if err := db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error {
if _, err := tx.NewAddColumn().
Table("media_attachments").
ColumnExpr("? INTEGER NOT NULL DEFAULT ?", bun.Ident("type_new"), 0).
Exec(ctx); err != nil {
return err
}

for old, new := range map[old_gtsmodel.FileType]new_gtsmodel.FileType{
old_gtsmodel.FileTypeAudio: new_gtsmodel.FileTypeAudio,
old_gtsmodel.FileTypeImage: new_gtsmodel.FileTypeImage,
old_gtsmodel.FileTypeGifv: new_gtsmodel.FileTypeImage,
old_gtsmodel.FileTypeVideo: new_gtsmodel.FileTypeVideo,
old_gtsmodel.FileTypeUnknown: new_gtsmodel.FileTypeUnknown,
} {
if _, err := tx.NewUpdate().
Table("media_attachments").
Where("? = ?", bun.Ident("type"), old).
Set("? = ?", bun.Ident("type_new"), new).
Exec(ctx); err != nil {
return err
}
}

if _, err := tx.NewDropColumn().
Table("media_attachments").
ColumnExpr("?", bun.Ident("type")).
Exec(ctx); err != nil {
return err
}

if _, err := tx.NewRaw(
"ALTER TABLE ? RENAME COLUMN ? TO ?",
bun.Ident("media_attachments"),
bun.Ident("type_new"),
bun.Ident("type"),
).Exec(ctx); err != nil {
return err
}

return nil
}); err != nil {
return err
}

// Zero-out attachment data
// for "unknown" non-locally
// stored media attachments.
if _, err := db.NewUpdate().
Table("media_attachments").
Where("? = ?", bun.Ident("type"), new_gtsmodel.FileTypeUnknown).
Set("? = ?", bun.Ident("url"), "").
Set("? = ?", bun.Ident("file_path"), "").
Set("? = ?", bun.Ident("file_content_type"), "").
Set("? = ?", bun.Ident("file_file_size"), 0).
Set("? = ?", bun.Ident("thumbnail_path"), "").
Set("? = ?", bun.Ident("thumbnail_content_type"), "").
Set("? = ?", bun.Ident("thumbnail_file_size"), 0).
Set("? = ?", bun.Ident("thumbnail_url"), "").
Exec(ctx); err != nil {
return err
}

// Zero-out emoji data for
// non-locally stored emoji.
if _, err := db.NewUpdate().
Table("emojis").
WhereOr("? = ?", bun.Ident("image_url"), "").
WhereOr("? = ?", bun.Ident("image_path"), "").
Set("? = ?", bun.Ident("image_path"), "").
Set("? = ?", bun.Ident("image_url"), "").
Set("? = ?", bun.Ident("image_file_size"), 0).
Set("? = ?", bun.Ident("image_content_type"), "").
Set("? = ?", bun.Ident("image_static_path"), "").
Set("? = ?", bun.Ident("image_static_url"), "").
Set("? = ?", bun.Ident("image_static_file_size"), 0).
Set("? = ?", bun.Ident("image_static_content_type"), "").
Exec(ctx); err != nil {
return err
}

return nil
}

down := func(ctx context.Context, db *bun.DB) error {
return db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error {
return nil
})
}

if err := Migrations.Register(up, down); err != nil {
panic(err)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// GoToSocial
// Copyright (C) GoToSocial Authors [email protected]
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// 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 gtsmodel

import "time"

// Emoji represents a custom emoji that's been uploaded through the admin UI or downloaded from a remote instance.
type Emoji struct {
ID string `bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database
CreatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item created
UpdatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item last updated
Shortcode string `bun:",nullzero,notnull,unique:domainshortcode"` // String shortcode for this emoji -- the part that's between colons. This should be a-zA-Z_ eg., 'blob_hug' 'purple_heart' 'Gay_Otter' Must be unique with domain.
Domain string `bun:",nullzero,unique:domainshortcode"` // Origin domain of this emoji, eg 'example.org', 'queer.party'. empty string for local emojis.
ImageRemoteURL string `bun:",nullzero"` // Where can this emoji be retrieved remotely? Null for local emojis.
ImageStaticRemoteURL string `bun:",nullzero"` // Where can a static / non-animated version of this emoji be retrieved remotely? Null for local emojis.
ImageURL string `bun:",nullzero"` // Where can this emoji be retrieved from the local server? Null for remote emojis.
ImageStaticURL string `bun:",nullzero"` // Where can a static version of this emoji be retrieved from the local server? Null for remote emojis.
ImagePath string `bun:",notnull"` // Path of the emoji image in the server storage system.
ImageStaticPath string `bun:",notnull"` // Path of a static version of the emoji image in the server storage system
ImageContentType string `bun:",notnull"` // MIME content type of the emoji image
ImageStaticContentType string `bun:",notnull"` // MIME content type of the static version of the emoji image.
ImageFileSize int `bun:",notnull"` // Size of the emoji image file in bytes, for serving purposes.
ImageStaticFileSize int `bun:",notnull"` // Size of the static version of the emoji image file in bytes, for serving purposes.
Disabled *bool `bun:",nullzero,notnull,default:false"` // Has a moderation action disabled this emoji from being shown?
URI string `bun:",nullzero,notnull,unique"` // ActivityPub uri of this emoji. Something like 'https://example.org/emojis/1234'
VisibleInPicker *bool `bun:",nullzero,notnull,default:true"` // Is this emoji visible in the admin emoji picker?
Category *EmojiCategory `bun:"rel:belongs-to"` // In which emoji category is this emoji visible?
CategoryID string `bun:"type:CHAR(26),nullzero"` // ID of the category this emoji belongs to.
Cached *bool `bun:",nullzero,notnull,default:false"` // whether emoji is cached in locally in gotosocial storage.
}

// IsLocal returns true if the emoji is
// local to this instance., ie., it did
// not originate from a remote instance.
func (e *Emoji) IsLocal() bool {
return e.Domain == ""
}

// ShortcodeDomain returns the [shortcode]@[domain] for the given emoji.
func (e *Emoji) ShortcodeDomain() string {
return e.Shortcode + "@" + e.Domain
}

// EmojiCategory represents a grouping of custom emojis.
type EmojiCategory struct {
ID string `bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database
CreatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item created
UpdatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item last updated
Name string `bun:",nullzero,notnull,unique"` // name of this category
}
Loading