mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-02 20:02:25 -06:00 
			
		
		
		
	* Add Swagger spec test script * Fix Swagger spec errors not related to statuses with polls * Add API tests that post a status with a poll * Fix creating a status with a poll from form params * Fix Swagger spec errors related to statuses with polls (this is the last error) * Fix Swagger spec warnings not related to unused definitions * Suppress a duplicate list update params definition that was somehow causing wrong param names * Add Swagger test to CI - updates Drone config - vendorizes go-swagger - fixes a file extension issue that caused the test script to generate JSON instead of YAML with the vendorized version * Put `Sample: ` on its own line everywhere * Remove unused id param from emojiCategoriesGet * Add 5 more pairs of profile fields to account update API Swagger * Remove Swagger prefix from dummy fields It makes the generated code look weird * Manually annotate params for statusCreate operation * Fix all remaining Swagger spec warnings - Change some models into operation parameters - Ignore models that already correspond to manually documented operation parameters but can't be trivially changed (those with file fields) * Documented that creating a status with scheduled_at isn't implemented yet * sign drone.yml * Fix filter API Swagger errors * fixup! Fix filter API Swagger errors --------- Co-authored-by: tobi <tobi.smethurst@protonmail.com>
		
			
				
	
	
		
			357 lines
		
	
	
	
		
			7.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			357 lines
		
	
	
	
		
			7.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2012 Jesse van den Kieboom. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
package flags
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"reflect"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
// Marshaler is the interface implemented by types that can marshal themselves
 | 
						|
// to a string representation of the flag.
 | 
						|
type Marshaler interface {
 | 
						|
	// MarshalFlag marshals a flag value to its string representation.
 | 
						|
	MarshalFlag() (string, error)
 | 
						|
}
 | 
						|
 | 
						|
// Unmarshaler is the interface implemented by types that can unmarshal a flag
 | 
						|
// argument to themselves. The provided value is directly passed from the
 | 
						|
// command line.
 | 
						|
type Unmarshaler interface {
 | 
						|
	// UnmarshalFlag unmarshals a string value representation to the flag
 | 
						|
	// value (which therefore needs to be a pointer receiver).
 | 
						|
	UnmarshalFlag(value string) error
 | 
						|
}
 | 
						|
 | 
						|
// ValueValidator is the interface implemented by types that can validate a
 | 
						|
// flag argument themselves. The provided value is directly passed from the
 | 
						|
// command line.
 | 
						|
type ValueValidator interface {
 | 
						|
	// IsValidValue returns an error if the provided string value is valid for
 | 
						|
	// the flag.
 | 
						|
	IsValidValue(value string) error
 | 
						|
}
 | 
						|
 | 
						|
func getBase(options multiTag, base int) (int, error) {
 | 
						|
	sbase := options.Get("base")
 | 
						|
 | 
						|
	var err error
 | 
						|
	var ivbase int64
 | 
						|
 | 
						|
	if sbase != "" {
 | 
						|
		ivbase, err = strconv.ParseInt(sbase, 10, 32)
 | 
						|
		base = int(ivbase)
 | 
						|
	}
 | 
						|
 | 
						|
	return base, err
 | 
						|
}
 | 
						|
 | 
						|
func convertMarshal(val reflect.Value) (bool, string, error) {
 | 
						|
	// Check first for the Marshaler interface
 | 
						|
	if val.Type().NumMethod() > 0 && val.CanInterface() {
 | 
						|
		if marshaler, ok := val.Interface().(Marshaler); ok {
 | 
						|
			ret, err := marshaler.MarshalFlag()
 | 
						|
			return true, ret, err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return false, "", nil
 | 
						|
}
 | 
						|
 | 
						|
func convertToString(val reflect.Value, options multiTag) (string, error) {
 | 
						|
	if ok, ret, err := convertMarshal(val); ok {
 | 
						|
		return ret, err
 | 
						|
	}
 | 
						|
 | 
						|
	tp := val.Type()
 | 
						|
 | 
						|
	// Support for time.Duration
 | 
						|
	if tp == reflect.TypeOf((*time.Duration)(nil)).Elem() {
 | 
						|
		stringer := val.Interface().(fmt.Stringer)
 | 
						|
		return stringer.String(), nil
 | 
						|
	}
 | 
						|
 | 
						|
	switch tp.Kind() {
 | 
						|
	case reflect.String:
 | 
						|
		return val.String(), nil
 | 
						|
	case reflect.Bool:
 | 
						|
		if val.Bool() {
 | 
						|
			return "true", nil
 | 
						|
		}
 | 
						|
 | 
						|
		return "false", nil
 | 
						|
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | 
						|
		base, err := getBase(options, 10)
 | 
						|
 | 
						|
		if err != nil {
 | 
						|
			return "", err
 | 
						|
		}
 | 
						|
 | 
						|
		return strconv.FormatInt(val.Int(), base), nil
 | 
						|
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
 | 
						|
		base, err := getBase(options, 10)
 | 
						|
 | 
						|
		if err != nil {
 | 
						|
			return "", err
 | 
						|
		}
 | 
						|
 | 
						|
		return strconv.FormatUint(val.Uint(), base), nil
 | 
						|
	case reflect.Float32, reflect.Float64:
 | 
						|
		return strconv.FormatFloat(val.Float(), 'g', -1, tp.Bits()), nil
 | 
						|
	case reflect.Slice:
 | 
						|
		if val.Len() == 0 {
 | 
						|
			return "", nil
 | 
						|
		}
 | 
						|
 | 
						|
		ret := "["
 | 
						|
 | 
						|
		for i := 0; i < val.Len(); i++ {
 | 
						|
			if i != 0 {
 | 
						|
				ret += ", "
 | 
						|
			}
 | 
						|
 | 
						|
			item, err := convertToString(val.Index(i), options)
 | 
						|
 | 
						|
			if err != nil {
 | 
						|
				return "", err
 | 
						|
			}
 | 
						|
 | 
						|
			ret += item
 | 
						|
		}
 | 
						|
 | 
						|
		return ret + "]", nil
 | 
						|
	case reflect.Map:
 | 
						|
		ret := "{"
 | 
						|
 | 
						|
		for i, key := range val.MapKeys() {
 | 
						|
			if i != 0 {
 | 
						|
				ret += ", "
 | 
						|
			}
 | 
						|
 | 
						|
			keyitem, err := convertToString(key, options)
 | 
						|
 | 
						|
			if err != nil {
 | 
						|
				return "", err
 | 
						|
			}
 | 
						|
 | 
						|
			item, err := convertToString(val.MapIndex(key), options)
 | 
						|
 | 
						|
			if err != nil {
 | 
						|
				return "", err
 | 
						|
			}
 | 
						|
 | 
						|
			ret += keyitem + ":" + item
 | 
						|
		}
 | 
						|
 | 
						|
		return ret + "}", nil
 | 
						|
	case reflect.Ptr:
 | 
						|
		return convertToString(reflect.Indirect(val), options)
 | 
						|
	case reflect.Interface:
 | 
						|
		if !val.IsNil() {
 | 
						|
			return convertToString(val.Elem(), options)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return "", nil
 | 
						|
}
 | 
						|
 | 
						|
func convertUnmarshal(val string, retval reflect.Value) (bool, error) {
 | 
						|
	if retval.Type().NumMethod() > 0 && retval.CanInterface() {
 | 
						|
		if unmarshaler, ok := retval.Interface().(Unmarshaler); ok {
 | 
						|
			if retval.IsNil() {
 | 
						|
				retval.Set(reflect.New(retval.Type().Elem()))
 | 
						|
 | 
						|
				// Re-assign from the new value
 | 
						|
				unmarshaler = retval.Interface().(Unmarshaler)
 | 
						|
			}
 | 
						|
 | 
						|
			return true, unmarshaler.UnmarshalFlag(val)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if retval.Type().Kind() != reflect.Ptr && retval.CanAddr() {
 | 
						|
		return convertUnmarshal(val, retval.Addr())
 | 
						|
	}
 | 
						|
 | 
						|
	if retval.Type().Kind() == reflect.Interface && !retval.IsNil() {
 | 
						|
		return convertUnmarshal(val, retval.Elem())
 | 
						|
	}
 | 
						|
 | 
						|
	return false, nil
 | 
						|
}
 | 
						|
 | 
						|
func convert(val string, retval reflect.Value, options multiTag) error {
 | 
						|
	if ok, err := convertUnmarshal(val, retval); ok {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	tp := retval.Type()
 | 
						|
 | 
						|
	// Support for time.Duration
 | 
						|
	if tp == reflect.TypeOf((*time.Duration)(nil)).Elem() {
 | 
						|
		parsed, err := time.ParseDuration(val)
 | 
						|
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		retval.SetInt(int64(parsed))
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
 | 
						|
	switch tp.Kind() {
 | 
						|
	case reflect.String:
 | 
						|
		retval.SetString(val)
 | 
						|
	case reflect.Bool:
 | 
						|
		if val == "" {
 | 
						|
			retval.SetBool(true)
 | 
						|
		} else {
 | 
						|
			b, err := strconv.ParseBool(val)
 | 
						|
 | 
						|
			if err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
 | 
						|
			retval.SetBool(b)
 | 
						|
		}
 | 
						|
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | 
						|
		base, err := getBase(options, 10)
 | 
						|
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		parsed, err := strconv.ParseInt(val, base, tp.Bits())
 | 
						|
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		retval.SetInt(parsed)
 | 
						|
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
 | 
						|
		base, err := getBase(options, 10)
 | 
						|
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		parsed, err := strconv.ParseUint(val, base, tp.Bits())
 | 
						|
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		retval.SetUint(parsed)
 | 
						|
	case reflect.Float32, reflect.Float64:
 | 
						|
		parsed, err := strconv.ParseFloat(val, tp.Bits())
 | 
						|
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		retval.SetFloat(parsed)
 | 
						|
	case reflect.Slice:
 | 
						|
		elemtp := tp.Elem()
 | 
						|
 | 
						|
		elemvalptr := reflect.New(elemtp)
 | 
						|
		elemval := reflect.Indirect(elemvalptr)
 | 
						|
 | 
						|
		if err := convert(val, elemval, options); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		retval.Set(reflect.Append(retval, elemval))
 | 
						|
	case reflect.Map:
 | 
						|
		parts := strings.SplitN(val, ":", 2)
 | 
						|
 | 
						|
		key := parts[0]
 | 
						|
		var value string
 | 
						|
 | 
						|
		if len(parts) == 2 {
 | 
						|
			value = parts[1]
 | 
						|
		}
 | 
						|
 | 
						|
		keytp := tp.Key()
 | 
						|
		keyval := reflect.New(keytp)
 | 
						|
 | 
						|
		if err := convert(key, keyval, options); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		valuetp := tp.Elem()
 | 
						|
		valueval := reflect.New(valuetp)
 | 
						|
 | 
						|
		if err := convert(value, valueval, options); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		if retval.IsNil() {
 | 
						|
			retval.Set(reflect.MakeMap(tp))
 | 
						|
		}
 | 
						|
 | 
						|
		retval.SetMapIndex(reflect.Indirect(keyval), reflect.Indirect(valueval))
 | 
						|
	case reflect.Ptr:
 | 
						|
		if retval.IsNil() {
 | 
						|
			retval.Set(reflect.New(retval.Type().Elem()))
 | 
						|
		}
 | 
						|
 | 
						|
		return convert(val, reflect.Indirect(retval), options)
 | 
						|
	case reflect.Interface:
 | 
						|
		if !retval.IsNil() {
 | 
						|
			return convert(val, retval.Elem(), options)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func isPrint(s string) bool {
 | 
						|
	for _, c := range s {
 | 
						|
		if !strconv.IsPrint(c) {
 | 
						|
			return false
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
func quoteIfNeeded(s string) string {
 | 
						|
	if !isPrint(s) {
 | 
						|
		return strconv.Quote(s)
 | 
						|
	}
 | 
						|
 | 
						|
	return s
 | 
						|
}
 | 
						|
 | 
						|
func quoteIfNeededV(s []string) []string {
 | 
						|
	ret := make([]string, len(s))
 | 
						|
 | 
						|
	for i, v := range s {
 | 
						|
		ret[i] = quoteIfNeeded(v)
 | 
						|
	}
 | 
						|
 | 
						|
	return ret
 | 
						|
}
 | 
						|
 | 
						|
func quoteV(s []string) []string {
 | 
						|
	ret := make([]string, len(s))
 | 
						|
 | 
						|
	for i, v := range s {
 | 
						|
		ret[i] = strconv.Quote(v)
 | 
						|
	}
 | 
						|
 | 
						|
	return ret
 | 
						|
}
 | 
						|
 | 
						|
func unquoteIfPossible(s string) (string, error) {
 | 
						|
	if len(s) == 0 || s[0] != '"' {
 | 
						|
		return s, nil
 | 
						|
	}
 | 
						|
 | 
						|
	return strconv.Unquote(s)
 | 
						|
}
 |