mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-03 22:52:25 -06:00 
			
		
		
		
	* Add whereNotEmptyAndNotNull * Add GetRemoteOlderThanDays * Add GetRemoteOlderThanDays * Add PruneRemote to Manager interface * Start implementing PruneRemote * add new attachment + status to tests * fix up and test GetRemoteOlderThan * fix bad import * PruneRemote: return number pruned * add Cached column to mediaattachment * update + test pruneRemote * update mediaTest * use Cached column * upstep bun to latest version * embed structs in mediaAttachment * migrate mediaAttachment to new format * don't default cached to true * select only remote media * update db dependencies * step bun back to last working version * update pruneRemote to use Cached field * fix storage path of test attachments * add recache logic to manager * fix trimmed aspect ratio * test prune and recache * return errwithcode * tidy up different paths for emoji vs attachment * fix incorrect thumbnail type being stored * expose TransportController to media processor * implement tee-ing recached content * add thoughts of dog to test fedi attachments * test get remote files * add comment on PruneRemote * add postData cleanup to recache * test thumbnail fetching * add incredible diagram * go mod tidy * buffer pipes for recache streaming * test for client stops reading after 1kb * add media-remote-cache-days to config * add cron package * wrap logrus so it's available to cron * start and stop cron jobs gracefully
		
			
				
	
	
		
			246 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			246 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package schema
 | 
						|
 | 
						|
import (
 | 
						|
	"reflect"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"github.com/uptrace/bun/dialect"
 | 
						|
	"github.com/uptrace/bun/dialect/feature"
 | 
						|
	"github.com/uptrace/bun/internal"
 | 
						|
	"github.com/uptrace/bun/internal/parser"
 | 
						|
)
 | 
						|
 | 
						|
var nopFormatter = Formatter{
 | 
						|
	dialect: newNopDialect(),
 | 
						|
}
 | 
						|
 | 
						|
type Formatter struct {
 | 
						|
	dialect Dialect
 | 
						|
	args    *namedArgList
 | 
						|
}
 | 
						|
 | 
						|
func NewFormatter(dialect Dialect) Formatter {
 | 
						|
	return Formatter{
 | 
						|
		dialect: dialect,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func NewNopFormatter() Formatter {
 | 
						|
	return nopFormatter
 | 
						|
}
 | 
						|
 | 
						|
func (f Formatter) IsNop() bool {
 | 
						|
	return f.dialect.Name() == dialect.Invalid
 | 
						|
}
 | 
						|
 | 
						|
func (f Formatter) Dialect() Dialect {
 | 
						|
	return f.dialect
 | 
						|
}
 | 
						|
 | 
						|
func (f Formatter) IdentQuote() byte {
 | 
						|
	return f.dialect.IdentQuote()
 | 
						|
}
 | 
						|
 | 
						|
func (f Formatter) AppendIdent(b []byte, ident string) []byte {
 | 
						|
	return dialect.AppendIdent(b, ident, f.IdentQuote())
 | 
						|
}
 | 
						|
 | 
						|
func (f Formatter) AppendValue(b []byte, v reflect.Value) []byte {
 | 
						|
	if v.Kind() == reflect.Ptr && v.IsNil() {
 | 
						|
		return dialect.AppendNull(b)
 | 
						|
	}
 | 
						|
	appender := Appender(f.dialect, v.Type())
 | 
						|
	return appender(f, b, v)
 | 
						|
}
 | 
						|
 | 
						|
func (f Formatter) HasFeature(feature feature.Feature) bool {
 | 
						|
	return f.dialect.Features().Has(feature)
 | 
						|
}
 | 
						|
 | 
						|
func (f Formatter) WithArg(arg NamedArgAppender) Formatter {
 | 
						|
	return Formatter{
 | 
						|
		dialect: f.dialect,
 | 
						|
		args:    f.args.WithArg(arg),
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (f Formatter) WithNamedArg(name string, value interface{}) Formatter {
 | 
						|
	return Formatter{
 | 
						|
		dialect: f.dialect,
 | 
						|
		args:    f.args.WithArg(&namedArg{name: name, value: value}),
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (f Formatter) FormatQuery(query string, args ...interface{}) string {
 | 
						|
	if f.IsNop() || (args == nil && f.args == nil) || strings.IndexByte(query, '?') == -1 {
 | 
						|
		return query
 | 
						|
	}
 | 
						|
	return internal.String(f.AppendQuery(nil, query, args...))
 | 
						|
}
 | 
						|
 | 
						|
func (f Formatter) AppendQuery(dst []byte, query string, args ...interface{}) []byte {
 | 
						|
	if f.IsNop() || (args == nil && f.args == nil) || strings.IndexByte(query, '?') == -1 {
 | 
						|
		return append(dst, query...)
 | 
						|
	}
 | 
						|
	return f.append(dst, parser.NewString(query), args)
 | 
						|
}
 | 
						|
 | 
						|
func (f Formatter) append(dst []byte, p *parser.Parser, args []interface{}) []byte {
 | 
						|
	var namedArgs NamedArgAppender
 | 
						|
	if len(args) == 1 {
 | 
						|
		if v, ok := args[0].(NamedArgAppender); ok {
 | 
						|
			namedArgs = v
 | 
						|
		} else if v, ok := newStructArgs(f, args[0]); ok {
 | 
						|
			namedArgs = v
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	var argIndex int
 | 
						|
	for p.Valid() {
 | 
						|
		b, ok := p.ReadSep('?')
 | 
						|
		if !ok {
 | 
						|
			dst = append(dst, b...)
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		if len(b) > 0 && b[len(b)-1] == '\\' {
 | 
						|
			dst = append(dst, b[:len(b)-1]...)
 | 
						|
			dst = append(dst, '?')
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		dst = append(dst, b...)
 | 
						|
 | 
						|
		name, numeric := p.ReadIdentifier()
 | 
						|
		if name != "" {
 | 
						|
			if numeric {
 | 
						|
				idx, err := strconv.Atoi(name)
 | 
						|
				if err != nil {
 | 
						|
					goto restore_arg
 | 
						|
				}
 | 
						|
 | 
						|
				if idx >= len(args) {
 | 
						|
					goto restore_arg
 | 
						|
				}
 | 
						|
 | 
						|
				dst = f.appendArg(dst, args[idx])
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
			if namedArgs != nil {
 | 
						|
				dst, ok = namedArgs.AppendNamedArg(f, dst, name)
 | 
						|
				if ok {
 | 
						|
					continue
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			dst, ok = f.args.AppendNamedArg(f, dst, name)
 | 
						|
			if ok {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
		restore_arg:
 | 
						|
			dst = append(dst, '?')
 | 
						|
			dst = append(dst, name...)
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		if argIndex >= len(args) {
 | 
						|
			dst = append(dst, '?')
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		arg := args[argIndex]
 | 
						|
		argIndex++
 | 
						|
 | 
						|
		dst = f.appendArg(dst, arg)
 | 
						|
	}
 | 
						|
 | 
						|
	return dst
 | 
						|
}
 | 
						|
 | 
						|
func (f Formatter) appendArg(b []byte, arg interface{}) []byte {
 | 
						|
	switch arg := arg.(type) {
 | 
						|
	case QueryAppender:
 | 
						|
		bb, err := arg.AppendQuery(f, b)
 | 
						|
		if err != nil {
 | 
						|
			return dialect.AppendError(b, err)
 | 
						|
		}
 | 
						|
		return bb
 | 
						|
	default:
 | 
						|
		return Append(f, b, arg)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
 | 
						|
type NamedArgAppender interface {
 | 
						|
	AppendNamedArg(fmter Formatter, b []byte, name string) ([]byte, bool)
 | 
						|
}
 | 
						|
 | 
						|
type namedArgList struct {
 | 
						|
	arg  NamedArgAppender
 | 
						|
	next *namedArgList
 | 
						|
}
 | 
						|
 | 
						|
func (l *namedArgList) WithArg(arg NamedArgAppender) *namedArgList {
 | 
						|
	return &namedArgList{
 | 
						|
		arg:  arg,
 | 
						|
		next: l,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (l *namedArgList) AppendNamedArg(fmter Formatter, b []byte, name string) ([]byte, bool) {
 | 
						|
	for l != nil && l.arg != nil {
 | 
						|
		if b, ok := l.arg.AppendNamedArg(fmter, b, name); ok {
 | 
						|
			return b, true
 | 
						|
		}
 | 
						|
		l = l.next
 | 
						|
	}
 | 
						|
	return b, false
 | 
						|
}
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
 | 
						|
type namedArg struct {
 | 
						|
	name  string
 | 
						|
	value interface{}
 | 
						|
}
 | 
						|
 | 
						|
var _ NamedArgAppender = (*namedArg)(nil)
 | 
						|
 | 
						|
func (a *namedArg) AppendNamedArg(fmter Formatter, b []byte, name string) ([]byte, bool) {
 | 
						|
	if a.name == name {
 | 
						|
		return fmter.appendArg(b, a.value), true
 | 
						|
	}
 | 
						|
	return b, false
 | 
						|
}
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
 | 
						|
type structArgs struct {
 | 
						|
	table *Table
 | 
						|
	strct reflect.Value
 | 
						|
}
 | 
						|
 | 
						|
var _ NamedArgAppender = (*structArgs)(nil)
 | 
						|
 | 
						|
func newStructArgs(fmter Formatter, strct interface{}) (*structArgs, bool) {
 | 
						|
	v := reflect.ValueOf(strct)
 | 
						|
	if !v.IsValid() {
 | 
						|
		return nil, false
 | 
						|
	}
 | 
						|
 | 
						|
	v = reflect.Indirect(v)
 | 
						|
	if v.Kind() != reflect.Struct {
 | 
						|
		return nil, false
 | 
						|
	}
 | 
						|
 | 
						|
	return &structArgs{
 | 
						|
		table: fmter.Dialect().Tables().Get(v.Type()),
 | 
						|
		strct: v,
 | 
						|
	}, true
 | 
						|
}
 | 
						|
 | 
						|
func (m *structArgs) AppendNamedArg(fmter Formatter, b []byte, name string) ([]byte, bool) {
 | 
						|
	return m.table.AppendNamedArg(fmter, b, name, m.strct)
 | 
						|
}
 |