mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2026-01-02 14:33:16 -06:00
Merge branch 'main' into instance-custom-css
This commit is contained in:
commit
7cd9b0eae0
947 changed files with 689490 additions and 178161 deletions
|
|
@ -68,6 +68,10 @@ type Account struct {
|
|||
// Description of this account's avatar, for alt text.
|
||||
// example: A cute drawing of a smiling sloth.
|
||||
AvatarDescription string `json:"avatar_description,omitempty"`
|
||||
// Database ID of the media attachment for this account's avatar image.
|
||||
// Omitted if no avatar uploaded for this account (ie., default avatar).
|
||||
// example: 01JAJ3XCD66K3T99JZESCR137W
|
||||
AvatarMediaID string `json:"avatar_media_id,omitempty"`
|
||||
// Web location of the account's header image.
|
||||
// example: https://example.org/media/some_user/header/original/header.jpeg
|
||||
Header string `json:"header"`
|
||||
|
|
@ -78,14 +82,18 @@ type Account struct {
|
|||
// Description of this account's header, for alt text.
|
||||
// example: A sunlit field with purple flowers.
|
||||
HeaderDescription string `json:"header_description,omitempty"`
|
||||
// Database ID of the media attachment for this account's header image.
|
||||
// Omitted if no header uploaded for this account (ie., default header).
|
||||
// example: 01JAJ3XCD66K3T99JZESCR137W
|
||||
HeaderMediaID string `json:"header_media_id,omitempty"`
|
||||
// Number of accounts following this account, according to our instance.
|
||||
FollowersCount int `json:"followers_count"`
|
||||
// Number of account's followed by this account, according to our instance.
|
||||
FollowingCount int `json:"following_count"`
|
||||
// Number of statuses posted by this account, according to our instance.
|
||||
StatusesCount int `json:"statuses_count"`
|
||||
// When the account's most recent status was posted (ISO 8601 Datetime).
|
||||
// example: 2021-07-30T09:20:25+00:00
|
||||
// When the account's most recent status was posted (ISO 8601 Date).
|
||||
// example: 2021-07-30
|
||||
LastStatusAt *string `json:"last_status_at"`
|
||||
// Array of custom emojis used in this account's note or display name.
|
||||
// Empty for blocked accounts.
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ type MediaDimensions struct {
|
|||
Duration float32 `json:"duration,omitempty"`
|
||||
// Bitrate of the media in bits per second.
|
||||
// example: 1000000
|
||||
Bitrate int `json:"bitrate,omitempty"`
|
||||
Bitrate uint64 `json:"bitrate,omitempty"`
|
||||
// Size of the media, in the format `[width]x[height]`.
|
||||
// Not set for audio.
|
||||
// example: 1920x1080
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ type Conversation struct {
|
|||
// Is the conversation currently marked as unread?
|
||||
Unread bool `json:"unread"`
|
||||
// Participants in the conversation.
|
||||
//
|
||||
// If this is a conversation between no accounts (ie., a self-directed DM),
|
||||
// this will include only the requesting account itself. Otherwise, it will
|
||||
// include every other account in the conversation *except* the requester.
|
||||
Accounts []Account `json:"accounts"`
|
||||
// The last status in the conversation. May be `null`.
|
||||
LastStatus *Status `json:"last_status"`
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@ type DomainPermission struct {
|
|||
// Time at which the permission entry was created (ISO 8601 Datetime).
|
||||
// example: 2021-07-30T09:20:25+00:00
|
||||
CreatedAt string `json:"created_at,omitempty"`
|
||||
// Permission type of this entry (block, allow).
|
||||
// Only set for domain permission drafts.
|
||||
PermissionType string `json:"permission_type,omitempty"`
|
||||
}
|
||||
|
||||
// DomainPermissionRequest is the form submitted as a POST to create a new domain permission entry (allow/block).
|
||||
|
|
@ -69,22 +72,24 @@ type DomainPermission struct {
|
|||
type DomainPermissionRequest struct {
|
||||
// A list of domains for which this permission request should apply.
|
||||
// Only used if import=true is specified.
|
||||
Domains *multipart.FileHeader `form:"domains" json:"domains" xml:"domains"`
|
||||
Domains *multipart.FileHeader `form:"domains" json:"domains"`
|
||||
// A single domain for which this permission request should apply.
|
||||
// Only used if import=true is NOT specified or if import=false.
|
||||
// example: example.org
|
||||
Domain string `form:"domain" json:"domain" xml:"domain"`
|
||||
Domain string `form:"domain" json:"domain"`
|
||||
// Obfuscate the domain name when displaying this permission entry publicly.
|
||||
// Ie., instead of 'example.org' show something like 'e**mpl*.or*'.
|
||||
// example: false
|
||||
Obfuscate bool `form:"obfuscate" json:"obfuscate" xml:"obfuscate"`
|
||||
Obfuscate bool `form:"obfuscate" json:"obfuscate"`
|
||||
// Private comment for other admins on why this permission entry was created.
|
||||
// example: don't like 'em!!!!
|
||||
PrivateComment string `form:"private_comment" json:"private_comment" xml:"private_comment"`
|
||||
PrivateComment string `form:"private_comment" json:"private_comment"`
|
||||
// Public comment on why this permission entry was created.
|
||||
// Will be visible to requesters at /api/v1/instance/peers if this endpoint is exposed.
|
||||
// example: foss dorks 😫
|
||||
PublicComment string `form:"public_comment" json:"public_comment" xml:"public_comment"`
|
||||
PublicComment string `form:"public_comment" json:"public_comment"`
|
||||
// Permission type to create (only applies to domain permission drafts, not explicit blocks and allows).
|
||||
PermissionType string `form:"permission_type" json:"permission_type"`
|
||||
}
|
||||
|
||||
// DomainKeysExpireRequest is the form submitted as a POST to /api/v1/admin/domain_keys_expire to expire a domain's public keys.
|
||||
|
|
@ -92,5 +97,5 @@ type DomainPermissionRequest struct {
|
|||
// swagger:parameters domainKeysExpire
|
||||
type DomainKeysExpireRequest struct {
|
||||
// hostname/domain to expire keys for.
|
||||
Domain string `form:"domain" json:"domain" xml:"domain"`
|
||||
Domain string `form:"domain" json:"domain"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,5 +95,5 @@ type FilterCreateUpdateRequestV1 struct {
|
|||
// Number of seconds from now that the filter should expire. If omitted, filter never expires.
|
||||
//
|
||||
// Example: 86400
|
||||
ExpiresInI interface{} `json:"expires_in"`
|
||||
ExpiresInI Nullable[any] `json:"expires_in"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ type FilterCreateRequestV2 struct {
|
|||
// Number of seconds from now that the filter should expire. If omitted, filter never expires.
|
||||
//
|
||||
// Example: 86400
|
||||
ExpiresInI interface{} `json:"expires_in"`
|
||||
ExpiresInI Nullable[any] `json:"expires_in"`
|
||||
|
||||
// Keywords to be added to the newly created filter.
|
||||
Keywords []FilterKeywordCreateUpdateRequest `form:"-" json:"keywords_attributes" xml:"keywords_attributes"`
|
||||
|
|
@ -199,7 +199,7 @@ type FilterUpdateRequestV2 struct {
|
|||
// Number of seconds from now that the filter should expire. If omitted, filter never expires.
|
||||
//
|
||||
// Example: 86400
|
||||
ExpiresInI interface{} `json:"expires_in"`
|
||||
ExpiresInI Nullable[any] `json:"expires_in"`
|
||||
|
||||
// Keywords to be added to the filter, modified, or removed.
|
||||
Keywords []FilterKeywordCreateUpdateDeleteRequest `form:"-" json:"keywords_attributes" xml:"keywords_attributes"`
|
||||
|
|
|
|||
107
internal/api/model/nullable.go
Normal file
107
internal/api/model/nullable.go
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
// GoToSocial
|
||||
// Copyright (C) GoToSocial Authors admin@gotosocial.org
|
||||
// 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 model
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// Nullable is a generic type, which implements a field that can be one of three states:
|
||||
//
|
||||
// - field is not set in the request
|
||||
// - field is explicitly set to `null` in the request
|
||||
// - field is explicitly set to a valid value in the request
|
||||
//
|
||||
// Nullable is intended to be used with JSON unmarshalling.
|
||||
//
|
||||
// Adapted from https://github.com/oapi-codegen/nullable/blob/main/nullable.go
|
||||
type Nullable[T any] struct {
|
||||
state nullableState
|
||||
value T
|
||||
}
|
||||
|
||||
type nullableState uint8
|
||||
|
||||
const (
|
||||
nullableStateUnspecified nullableState = 0
|
||||
nullableStateNull nullableState = 1
|
||||
nullableStateSet nullableState = 2
|
||||
)
|
||||
|
||||
// Get retrieves the underlying value, if present,
|
||||
// and returns an error if the value was not present.
|
||||
func (t Nullable[T]) Get() (T, error) {
|
||||
var empty T
|
||||
if t.IsNull() {
|
||||
return empty, errors.New("value is null")
|
||||
}
|
||||
|
||||
if !t.IsSpecified() {
|
||||
return empty, errors.New("value is not specified")
|
||||
}
|
||||
|
||||
return t.value, nil
|
||||
}
|
||||
|
||||
// IsNull indicates whether the field
|
||||
// was sent, and had a value of `null`
|
||||
func (t Nullable[T]) IsNull() bool {
|
||||
return t.state == nullableStateNull
|
||||
}
|
||||
|
||||
// IsSpecified indicates whether the field
|
||||
// was sent either as a value or as `null`.
|
||||
func (t Nullable[T]) IsSpecified() bool {
|
||||
return t.state != nullableStateUnspecified
|
||||
}
|
||||
|
||||
// If field is unspecified,
|
||||
// UnmarshalJSON won't be called.
|
||||
func (t *Nullable[T]) UnmarshalJSON(data []byte) error {
|
||||
// If field is specified as `null`.
|
||||
if bytes.Equal(data, []byte("null")) {
|
||||
t.setNull()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Otherwise, we have an
|
||||
// actual value, so parse it.
|
||||
var v T
|
||||
if err := json.Unmarshal(data, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.set(v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// setNull indicates that the field
|
||||
// was sent, and had a value of `null`
|
||||
func (t *Nullable[T]) setNull() {
|
||||
*t = Nullable[T]{state: nullableStateNull}
|
||||
}
|
||||
|
||||
// set the underlying value to given value.
|
||||
func (t *Nullable[T]) set(value T) {
|
||||
*t = Nullable[T]{
|
||||
state: nullableStateSet,
|
||||
value: value,
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue