diff options
Diffstat (limited to 'internal/api/client')
| -rw-r--r-- | internal/api/client/markers/markers.go | 45 | ||||
| -rw-r--r-- | internal/api/client/markers/markersget.go | 108 | ||||
| -rw-r--r-- | internal/api/client/markers/markerspost.go | 110 | 
3 files changed, 263 insertions, 0 deletions
| diff --git a/internal/api/client/markers/markers.go b/internal/api/client/markers/markers.go new file mode 100644 index 000000000..fcf584d12 --- /dev/null +++ b/internal/api/client/markers/markers.go @@ -0,0 +1,45 @@ +// 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 markers + +import ( +	"net/http" + +	"github.com/gin-gonic/gin" +	"github.com/superseriousbusiness/gotosocial/internal/processing" +) + +const ( +	// BasePath is the base path for serving the markers API, minus the 'api' prefix +	BasePath = "/v1/markers" +) + +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.MarkersGETHandler) +	attachHandler(http.MethodPost, BasePath, m.MarkersPOSTHandler) +} diff --git a/internal/api/client/markers/markersget.go b/internal/api/client/markers/markersget.go new file mode 100644 index 000000000..eb403dcc6 --- /dev/null +++ b/internal/api/client/markers/markersget.go @@ -0,0 +1,108 @@ +// 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 markers + +import ( +	"net/http" + +	"github.com/gin-gonic/gin" +	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" +	apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util" +	"github.com/superseriousbusiness/gotosocial/internal/gtserror" +	"github.com/superseriousbusiness/gotosocial/internal/oauth" +	"github.com/superseriousbusiness/gotosocial/internal/validate" +) + +// MarkersGETHandler swagger:operation GET /api/v1/markers markersGet +// +// Get timeline markers by name +// +//	--- +//	tags: +//	- markers +// +//	produces: +//	- application/json +// +//	parameters: +//	- +//		name: timeline +//		type: array +//		items: +//			type: string +//			enum: +//				- home +//				- notifications +//		description: Timelines to retrieve. +//		in: query +// +//	security: +//	- OAuth2 Bearer: +//		- read:statuses +// +//	responses: +//		'200': +//			description: Requested markers +//			schema: +//				"$ref": "#/definitions/markers" +//		'400': +//			description: bad request +//		'401': +//			description: unauthorized +//		'500': +//			description: internal server error +func (m *Module) MarkersGETHandler(c *gin.Context) { +	authed, err := oauth.Authed(c, true, true, true, true) +	if err != nil { +		apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGetV1) +		return +	} + +	names, errWithCode := parseMarkerNames(c.QueryArray("timeline[]")) +	if errWithCode != nil { +		apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) +	} + +	marker, errWithCode := m.processor.Markers().Get(c.Request.Context(), authed.Account, names) +	if errWithCode != nil { +		apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) +		return +	} + +	c.JSON(http.StatusOK, marker) +} + +// parseMarkerNames turns a list of strings into a set of valid marker timeline names, or returns an error. +func parseMarkerNames(nameStrings []string) ([]apimodel.MarkerName, gtserror.WithCode) { +	nameSet := make(map[apimodel.MarkerName]struct{}, apimodel.MarkerNameNumValues) +	for _, timelineString := range nameStrings { +		if err := validate.MarkerName(timelineString); err != nil { +			return nil, gtserror.NewErrorBadRequest(err, err.Error()) +		} +		nameSet[apimodel.MarkerName(timelineString)] = struct{}{} +	} + +	i := 0 +	names := make([]apimodel.MarkerName, len(nameSet)) +	for name := range nameSet { +		names[i] = name +		i++ +	} + +	return names, nil +} diff --git a/internal/api/client/markers/markerspost.go b/internal/api/client/markers/markerspost.go new file mode 100644 index 000000000..3167becac --- /dev/null +++ b/internal/api/client/markers/markerspost.go @@ -0,0 +1,110 @@ +// 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 markers + +import ( +	"net/http" + +	"github.com/gin-gonic/gin" +	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" +	apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util" +	"github.com/superseriousbusiness/gotosocial/internal/gtserror" +	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" +	"github.com/superseriousbusiness/gotosocial/internal/oauth" +) + +// MarkersPOSTHandler swagger:operation POST /api/v1/markers markersPost +// +// Update timeline markers by name +// +//	--- +//	tags: +//	- markers +// +//	consumes: +//	- multipart/form-data +// +//	produces: +//	- application/json +// +//	parameters: +//	- +//		name: home[last_read_id] +//		type: string +//		description: Last status ID read on the home timeline. +//		in: formData +//	- +//		name: notifications[last_read_id] +//		type: string +//		description: Last notification ID read on the notifications timeline. +//		in: formData +// +//	security: +//	- OAuth2 Bearer: +//		- write:statuses +// +//	responses: +//		'200': +//			description: Requested markers +//			schema: +//				"$ref": "#/definitions/markers" +//		'400': +//			description: bad request +//		'401': +//			description: unauthorized +//		'409': +//			description: conflict (when two clients try to update the same timeline at the same time) +//		'500': +//			description: internal server error +func (m *Module) MarkersPOSTHandler(c *gin.Context) { +	authed, err := oauth.Authed(c, true, true, true, true) +	if err != nil { +		apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGetV1) +		return +	} + +	form := &apimodel.MarkerPostRequest{} +	if err := c.ShouldBind(form); err != nil { +		apiutil.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGetV1) +		return +	} + +	markers := make([]*gtsmodel.Marker, 0, apimodel.MarkerNameNumValues) +	if homeLastReadID := form.HomeLastReadID(); homeLastReadID != "" { +		markers = append(markers, >smodel.Marker{ +			AccountID:  authed.Account.ID, +			Name:       gtsmodel.MarkerNameHome, +			LastReadID: homeLastReadID, +		}) +	} +	if notificationsLastReadID := form.NotificationsLastReadID(); notificationsLastReadID != "" { +		markers = append(markers, >smodel.Marker{ +			AccountID:  authed.Account.ID, +			Name:       gtsmodel.MarkerNameNotifications, +			LastReadID: notificationsLastReadID, +		}) +	} + +	marker, errWithCode := m.processor.Markers().Update(c.Request.Context(), markers) +	if errWithCode != nil { +		apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) +		return +	} + +	c.JSON(http.StatusOK, marker) +} | 
