mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-10-29 12:12:24 -05:00
[feature] scheduled statuses (#4274)
An implementation of [`scheduled_statuses`](https://docs.joinmastodon.org/methods/scheduled_statuses/). Will fix #1006. this is heavily WIP and I need to reorganize some of the code, working on this made me somehow familiar with the codebase and led to my other recent contributions i told some fops on fedi i'd work on this so i have no choice but to complete it 🤷♀️ btw iirc my avatar presents me working on this branch Signed-off-by: nicole mikołajczyk <git@mkljczk.pl> Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4274 Co-authored-by: nicole mikołajczyk <git@mkljczk.pl> Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
parent
cead741c16
commit
660cf2c94c
46 changed files with 2354 additions and 68 deletions
|
|
@ -48,6 +48,7 @@ import (
|
|||
"code.superseriousbusiness.org/gotosocial/internal/api/client/preferences"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/api/client/push"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/api/client/reports"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/api/client/scheduledstatuses"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/api/client/search"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/api/client/statuses"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/api/client/streaming"
|
||||
|
|
@ -95,6 +96,7 @@ type Client struct {
|
|||
preferences *preferences.Module // api/v1/preferences
|
||||
push *push.Module // api/v1/push
|
||||
reports *reports.Module // api/v1/reports
|
||||
scheduledStatuses *scheduledstatuses.Module // api/v1/scheduled_statuses
|
||||
search *search.Module // api/v1/search, api/v2/search
|
||||
statuses *statuses.Module // api/v1/statuses
|
||||
streaming *streaming.Module // api/v1/streaming
|
||||
|
|
@ -149,6 +151,7 @@ func (c *Client) Route(r *router.Router, m ...gin.HandlerFunc) {
|
|||
c.preferences.Route(h)
|
||||
c.push.Route(h)
|
||||
c.reports.Route(h)
|
||||
c.scheduledStatuses.Route(h)
|
||||
c.search.Route(h)
|
||||
c.statuses.Route(h)
|
||||
c.streaming.Route(h)
|
||||
|
|
@ -191,6 +194,7 @@ func NewClient(state *state.State, p *processing.Processor) *Client {
|
|||
preferences: preferences.New(p),
|
||||
push: push.New(p),
|
||||
reports: reports.New(p),
|
||||
scheduledStatuses: scheduledstatuses.New(p),
|
||||
search: search.New(p),
|
||||
statuses: statuses.New(p),
|
||||
streaming: streaming.New(p, time.Second*30, 4096),
|
||||
|
|
|
|||
52
internal/api/client/scheduledstatuses/scheduledstatus.go
Normal file
52
internal/api/client/scheduledstatuses/scheduledstatus.go
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// 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 scheduledstatuses
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"code.superseriousbusiness.org/gotosocial/internal/processing"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const (
|
||||
// IDKey is for status UUIDs
|
||||
IDKey = "id"
|
||||
// BasePath is the base path for serving the scheduled statuses API, minus the 'api' prefix
|
||||
BasePath = "/v1/scheduled_statuses"
|
||||
// BasePathWithID is just the base path with the ID key in it.
|
||||
// Use this anywhere you need to know the ID of the scheduled status being queried.
|
||||
BasePathWithID = BasePath + "/:" + IDKey
|
||||
)
|
||||
|
||||
type Module struct {
|
||||
processor *processing.Processor
|
||||
}
|
||||
|
||||
func New(processor *processing.Processor) *Module {
|
||||
return &Module{
|
||||
processor: processor,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Module) Route(attachHandler func(method string, path string, f ...gin.HandlerFunc) gin.IRoutes) {
|
||||
attachHandler(http.MethodGet, BasePath, m.ScheduledStatusesGETHandler)
|
||||
attachHandler(http.MethodGet, BasePathWithID, m.ScheduledStatusGETHandler)
|
||||
attachHandler(http.MethodPut, BasePathWithID, m.ScheduledStatusPUTHandler)
|
||||
attachHandler(http.MethodDelete, BasePathWithID, m.ScheduledStatusDELETEHandler)
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
// 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 scheduledstatuses
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
apiutil "code.superseriousbusiness.org/gotosocial/internal/api/util"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/gtserror"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ScheduledStatusDELETEHandler swagger:operation DELETE /api/v1/scheduled_statuses/{id} deleteScheduledStatus
|
||||
//
|
||||
// Cancel a scheduled status with the given id.
|
||||
//
|
||||
// ---
|
||||
// tags:
|
||||
// - scheduled_statuses
|
||||
//
|
||||
// produces:
|
||||
// - application/json
|
||||
//
|
||||
// parameters:
|
||||
// -
|
||||
// name: id
|
||||
// type: string
|
||||
// description: ID of the status
|
||||
// in: path
|
||||
// required: true
|
||||
//
|
||||
// security:
|
||||
// - OAuth2 Bearer:
|
||||
// - write:statuses
|
||||
//
|
||||
// responses:
|
||||
// '200':
|
||||
// description: status canceled
|
||||
// '400':
|
||||
// description: bad request
|
||||
// '401':
|
||||
// description: unauthorized
|
||||
// '404':
|
||||
// description: not found
|
||||
// '406':
|
||||
// description: not acceptable
|
||||
// '500':
|
||||
// description: internal server error
|
||||
func (m *Module) ScheduledStatusDELETEHandler(c *gin.Context) {
|
||||
authed, errWithCode := apiutil.TokenAuth(c,
|
||||
true, true, true, true,
|
||||
apiutil.ScopeWriteStatuses,
|
||||
)
|
||||
if errWithCode != nil {
|
||||
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := apiutil.NegotiateAccept(c, apiutil.JSONAcceptHeaders...); err != nil {
|
||||
apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
targetScheduledStatusID, errWithCode := apiutil.ParseID(c.Param(apiutil.IDKey))
|
||||
if errWithCode != nil {
|
||||
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
errWithCode = m.processor.Status().ScheduledStatusesDelete(
|
||||
c.Request.Context(),
|
||||
authed.Account,
|
||||
targetScheduledStatusID,
|
||||
)
|
||||
if errWithCode != nil {
|
||||
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, apiutil.EmptyJSONObject)
|
||||
}
|
||||
136
internal/api/client/scheduledstatuses/scheduledstatusesget.go
Normal file
136
internal/api/client/scheduledstatuses/scheduledstatusesget.go
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
// 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 scheduledstatuses
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
apiutil "code.superseriousbusiness.org/gotosocial/internal/api/util"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/gtserror"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/paging"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ScheduledStatusesGETHandler swagger:operation GET /api/v1/scheduled_statuses getScheduledStatuses
|
||||
//
|
||||
// Get an array of statuses scheduled by authorized user.
|
||||
//
|
||||
// ---
|
||||
// tags:
|
||||
// - scheduled_statuses
|
||||
//
|
||||
// produces:
|
||||
// - application/json
|
||||
//
|
||||
// parameters:
|
||||
// -
|
||||
// name: max_id
|
||||
// type: string
|
||||
// description: >-
|
||||
// Return only statuses *OLDER* than the given max status ID.
|
||||
// The status with the specified ID will not be included in the response.
|
||||
// in: query
|
||||
// required: false
|
||||
// -
|
||||
// name: since_id
|
||||
// type: string
|
||||
// description: >-
|
||||
// Return only statuses *newer* than the given since status ID.
|
||||
// The status with the specified ID will not be included in the response.
|
||||
// in: query
|
||||
// -
|
||||
// name: min_id
|
||||
// type: string
|
||||
// description: >-
|
||||
// Return only statuses *immediately newer* than the given min ID.
|
||||
// The status with the specified ID will not be included in the response.
|
||||
// in: query
|
||||
// required: false
|
||||
// -
|
||||
// name: limit
|
||||
// type: integer
|
||||
// description: Number of scheduled statuses to return.
|
||||
// default: 20
|
||||
// in: query
|
||||
// required: false
|
||||
//
|
||||
// security:
|
||||
// - OAuth2 Bearer:
|
||||
// - read:statuses
|
||||
//
|
||||
// responses:
|
||||
// '200':
|
||||
// headers:
|
||||
// Link:
|
||||
// type: string
|
||||
// description: Links to the next and previous queries.
|
||||
// schema:
|
||||
// type: array
|
||||
// items:
|
||||
// "$ref": "#/definitions/scheduledStatus"
|
||||
// '400':
|
||||
// description: bad request
|
||||
// '401':
|
||||
// description: unauthorized
|
||||
// '404':
|
||||
// description: not found
|
||||
// '406':
|
||||
// description: not acceptable
|
||||
// '500':
|
||||
// description: internal server error
|
||||
func (m *Module) ScheduledStatusesGETHandler(c *gin.Context) {
|
||||
authed, errWithCode := apiutil.TokenAuth(c,
|
||||
true, true, true, true,
|
||||
apiutil.ScopeReadStatuses,
|
||||
)
|
||||
if errWithCode != nil {
|
||||
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := apiutil.NegotiateAccept(c, apiutil.JSONAcceptHeaders...); err != nil {
|
||||
apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
page, errWithCode := paging.ParseIDPage(c,
|
||||
1, // min limit
|
||||
80, // max limit
|
||||
20, // default limit
|
||||
)
|
||||
if errWithCode != nil {
|
||||
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
resp, errWithCode := m.processor.Status().ScheduledStatusesGetPage(
|
||||
c.Request.Context(),
|
||||
authed.Account,
|
||||
page,
|
||||
)
|
||||
if errWithCode != nil {
|
||||
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
if resp.LinkHeader != "" {
|
||||
c.Header("Link", resp.LinkHeader)
|
||||
}
|
||||
|
||||
apiutil.JSON(c, http.StatusOK, resp.Items)
|
||||
}
|
||||
98
internal/api/client/scheduledstatuses/scheduledstatusget.go
Normal file
98
internal/api/client/scheduledstatuses/scheduledstatusget.go
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
// 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 scheduledstatuses
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
apiutil "code.superseriousbusiness.org/gotosocial/internal/api/util"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/gtserror"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ScheduledStatusGETHandler swagger:operation GET /api/v1/scheduled_statuses/{id} getScheduledStatus
|
||||
//
|
||||
// Get a scheduled status with the given id.
|
||||
//
|
||||
// ---
|
||||
// tags:
|
||||
// - scheduled_statuses
|
||||
//
|
||||
// produces:
|
||||
// - application/json
|
||||
//
|
||||
// parameters:
|
||||
// -
|
||||
// name: id
|
||||
// type: string
|
||||
// description: ID of the status
|
||||
// in: path
|
||||
// required: true
|
||||
//
|
||||
// security:
|
||||
// - OAuth2 Bearer:
|
||||
// - read:statuses
|
||||
//
|
||||
// responses:
|
||||
// '200':
|
||||
// schema:
|
||||
// "$ref": "#/definitions/scheduledStatus"
|
||||
// '400':
|
||||
// description: bad request
|
||||
// '401':
|
||||
// description: unauthorized
|
||||
// '404':
|
||||
// description: not found
|
||||
// '406':
|
||||
// description: not acceptable
|
||||
// '500':
|
||||
// description: internal server error
|
||||
func (m *Module) ScheduledStatusGETHandler(c *gin.Context) {
|
||||
authed, errWithCode := apiutil.TokenAuth(c,
|
||||
true, true, true, true,
|
||||
apiutil.ScopeReadStatuses,
|
||||
)
|
||||
if errWithCode != nil {
|
||||
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := apiutil.NegotiateAccept(c, apiutil.JSONAcceptHeaders...); err != nil {
|
||||
apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
targetScheduledStatusID, errWithCode := apiutil.ParseID(c.Param(apiutil.IDKey))
|
||||
if errWithCode != nil {
|
||||
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
scheduledStatus, errWithCode := m.processor.Status().ScheduledStatusesGetOne(
|
||||
c.Request.Context(),
|
||||
authed.Account,
|
||||
targetScheduledStatusID,
|
||||
)
|
||||
if errWithCode != nil {
|
||||
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
apiutil.JSON(c, http.StatusOK, scheduledStatus)
|
||||
}
|
||||
131
internal/api/client/scheduledstatuses/scheduledstatusput.go
Normal file
131
internal/api/client/scheduledstatuses/scheduledstatusput.go
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
// 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 scheduledstatuses
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
apimodel "code.superseriousbusiness.org/gotosocial/internal/api/model"
|
||||
apiutil "code.superseriousbusiness.org/gotosocial/internal/api/util"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/gtserror"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ScheduledStatusPUTHandler swagger:operation PUT /api/v1/scheduled_statuses/{id} updateScheduledStatus
|
||||
//
|
||||
// Update a scheduled status's publishing date
|
||||
//
|
||||
// ---
|
||||
// tags:
|
||||
// - scheduled_statuses
|
||||
//
|
||||
// produces:
|
||||
// - application/json
|
||||
//
|
||||
// parameters:
|
||||
// -
|
||||
// name: id
|
||||
// type: string
|
||||
// description: ID of the status
|
||||
// in: path
|
||||
// required: true
|
||||
// -
|
||||
// name: scheduled_at
|
||||
// x-go-name: ScheduledAt
|
||||
// description: |-
|
||||
// ISO 8601 Datetime at which to schedule a status.
|
||||
//
|
||||
// Must be at least 5 minutes in the future.
|
||||
// type: string
|
||||
// format: date-time
|
||||
// in: formData
|
||||
//
|
||||
// security:
|
||||
// - OAuth2 Bearer:
|
||||
// - write:statuses
|
||||
//
|
||||
// responses:
|
||||
// '200':
|
||||
// schema:
|
||||
// "$ref": "#/definitions/scheduledStatus"
|
||||
// '400':
|
||||
// description: bad request
|
||||
// '401':
|
||||
// description: unauthorized
|
||||
// '404':
|
||||
// description: not found
|
||||
// '406':
|
||||
// description: not acceptable
|
||||
// '422':
|
||||
// description: unprocessable content
|
||||
// '500':
|
||||
// description: internal server error
|
||||
func (m *Module) ScheduledStatusPUTHandler(c *gin.Context) {
|
||||
authed, errWithCode := apiutil.TokenAuth(c,
|
||||
true, true, true, true,
|
||||
apiutil.ScopeWriteStatuses,
|
||||
)
|
||||
if errWithCode != nil {
|
||||
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
if authed.Account.IsMoving() {
|
||||
apiutil.ForbiddenAfterMove(c)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := apiutil.NegotiateAccept(c, apiutil.JSONAcceptHeaders...); err != nil {
|
||||
apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
targetScheduledStatusID, errWithCode := apiutil.ParseID(c.Param(apiutil.IDKey))
|
||||
if errWithCode != nil {
|
||||
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
form := &apimodel.ScheduledStatusUpdateRequest{}
|
||||
if err := c.ShouldBind(form); err != nil {
|
||||
apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
if !now.Add(5 * time.Minute).Before(*form.ScheduledAt) {
|
||||
const errText = "scheduled_at must be at least 5 minutes in the future"
|
||||
apiutil.ErrorHandler(c, gtserror.NewErrorUnprocessableEntity(gtserror.New(errText), errText), m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
scheduledStatus, errWithCode := m.processor.Status().ScheduledStatusesUpdate(
|
||||
c.Request.Context(),
|
||||
authed.Account,
|
||||
targetScheduledStatusID,
|
||||
form.ScheduledAt,
|
||||
)
|
||||
if errWithCode != nil {
|
||||
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
|
||||
return
|
||||
}
|
||||
|
||||
apiutil.JSON(c, http.StatusOK, scheduledStatus)
|
||||
}
|
||||
|
|
@ -181,7 +181,6 @@ import (
|
|||
//
|
||||
// Providing this parameter with a *future* time will cause ScheduledStatus to be returned instead of Status.
|
||||
// Must be at least 5 minutes in the future.
|
||||
// This feature isn't implemented yet.
|
||||
//
|
||||
// Providing this parameter with a *past* time will cause the status to be backdated,
|
||||
// and will not push it to the user's followers. This is intended for importing old statuses.
|
||||
|
|
@ -256,6 +255,8 @@ import (
|
|||
// description: not found
|
||||
// '406':
|
||||
// description: not acceptable
|
||||
// '422':
|
||||
// description: unprocessable content
|
||||
// '500':
|
||||
// description: internal server error
|
||||
// '501':
|
||||
|
|
@ -300,7 +301,9 @@ func (m *Module) StatusCreatePOSTHandler(c *gin.Context) {
|
|||
authed.Account,
|
||||
authed.Application,
|
||||
form,
|
||||
nil,
|
||||
)
|
||||
|
||||
if errWithCode != nil {
|
||||
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -476,13 +476,24 @@ func (suite *StatusCreateTestSuite) TestPostNewScheduledStatus() {
|
|||
"scheduled_at": {"2080-10-04T15:32:02.018Z"},
|
||||
}, "")
|
||||
|
||||
// We should have 501 from
|
||||
// We should have OK from
|
||||
// our call to the function.
|
||||
suite.Equal(http.StatusNotImplemented, recorder.Code)
|
||||
suite.Equal(http.StatusOK, recorder.Code)
|
||||
|
||||
// We should have a helpful error message.
|
||||
// A scheduled status with scheduled_at and status params should be returned.
|
||||
suite.Equal(`{
|
||||
"error": "Not Implemented: scheduled statuses are not yet supported"
|
||||
"id": "ZZZZZZZZZZZZZZZZZZZZZZZZZZ",
|
||||
"media_attachments": [],
|
||||
"params": {
|
||||
"application_id": "01F8MGY43H3N2C8EWPR2FPYEXG",
|
||||
"language": "",
|
||||
"scheduled_at": null,
|
||||
"sensitive": true,
|
||||
"spoiler_text": "hello hello",
|
||||
"text": "this is a brand new status! #helloworld",
|
||||
"visibility": "private"
|
||||
},
|
||||
"scheduled_at": "2080-10-04T15:32:02.018Z"
|
||||
}`, out)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,22 +17,46 @@
|
|||
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
// ScheduledStatus represents a status that will be published at a future scheduled date.
|
||||
//
|
||||
// swagger:model scheduledStatus
|
||||
type ScheduledStatus struct {
|
||||
ID string `json:"id"`
|
||||
ScheduledAt string `json:"scheduled_at"`
|
||||
Params *StatusParams `json:"params"`
|
||||
MediaAttachments []Attachment `json:"media_attachments"`
|
||||
ID string `json:"id"`
|
||||
ScheduledAt string `json:"scheduled_at"`
|
||||
Params *ScheduledStatusParams `json:"params"`
|
||||
MediaAttachments []*Attachment `json:"media_attachments"`
|
||||
}
|
||||
|
||||
// StatusParams represents parameters for a scheduled status.
|
||||
type StatusParams struct {
|
||||
Text string `json:"text"`
|
||||
InReplyToID string `json:"in_reply_to_id,omitempty"`
|
||||
MediaIDs []string `json:"media_ids,omitempty"`
|
||||
Sensitive bool `json:"sensitive,omitempty"`
|
||||
SpoilerText string `json:"spoiler_text,omitempty"`
|
||||
Visibility string `json:"visibility"`
|
||||
ScheduledAt string `json:"scheduled_at,omitempty"`
|
||||
ApplicationID string `json:"application_id"`
|
||||
type ScheduledStatusParams struct {
|
||||
Text string `json:"text"`
|
||||
MediaIDs []string `json:"media_ids,omitempty"`
|
||||
Sensitive bool `json:"sensitive,omitempty"`
|
||||
Poll *ScheduledStatusParamsPoll `json:"poll,omitempty"`
|
||||
SpoilerText string `json:"spoiler_text,omitempty"`
|
||||
Visibility Visibility `json:"visibility"`
|
||||
InReplyToID string `json:"in_reply_to_id,omitempty"`
|
||||
Language string `json:"language"`
|
||||
ApplicationID string `json:"application_id"`
|
||||
LocalOnly bool `json:"local_only,omitempty"`
|
||||
ContentType StatusContentType `json:"content_type,omitempty"`
|
||||
InteractionPolicy *InteractionPolicy `json:"interaction_policy,omitempty"`
|
||||
ScheduledAt *string `json:"scheduled_at"`
|
||||
}
|
||||
|
||||
type ScheduledStatusParamsPoll struct {
|
||||
Options []string `json:"options"`
|
||||
ExpiresIn int `json:"expires_in"`
|
||||
Multiple bool `json:"multiple"`
|
||||
HideTotals bool `json:"hide_totals"`
|
||||
}
|
||||
|
||||
// ScheduledStatusUpdateRequest models a request to update the scheduled status publication date.
|
||||
//
|
||||
// swagger:ignore
|
||||
type ScheduledStatusUpdateRequest struct {
|
||||
// ISO 8601 Datetime at which to schedule a status.
|
||||
ScheduledAt *time.Time `form:"scheduled_at" json:"scheduled_at"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -252,7 +252,6 @@ type StatusCreateRequest struct {
|
|||
//
|
||||
// Providing this parameter with a *future* time will cause ScheduledStatus to be returned instead of Status.
|
||||
// Must be at least 5 minutes in the future.
|
||||
// This feature isn't implemented yet.
|
||||
//
|
||||
// Providing this parameter with a *past* time will cause the status to be backdated,
|
||||
// and will not push it to the user's followers. This is intended for importing old statuses.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue