subreddits: implemented create subreddit rpc endpoint
This commit is contained in:
parent
114a6d5116
commit
8ff3bc4fd8
38
go/api/subreddits_create.go
Normal file
38
go/api/subreddits_create.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"connectrpc.com/connect"
|
||||||
|
"github.com/aarondl/opt/omit"
|
||||||
|
"github.com/mattn/go-sqlite3"
|
||||||
|
"github.com/tigorlazuardi/bluemage/go/gen/models"
|
||||||
|
"github.com/tigorlazuardi/bluemage/go/pkg/errs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (api *API) SubredditCreate(ctx context.Context, subreddit *models.Subreddit) (err error) {
|
||||||
|
// TODO: add check to Reddit API to see if subreddit exists.
|
||||||
|
|
||||||
|
api.lockf(func() {
|
||||||
|
_, err = models.Subreddits.Insert(ctx, api.DB, &models.SubredditSetter{
|
||||||
|
Name: omit.From(subreddit.Name),
|
||||||
|
DisableScheduler: omit.From(subreddit.DisableScheduler),
|
||||||
|
Type: omit.From(subreddit.Type),
|
||||||
|
Schedule: omit.From(subreddit.Schedule),
|
||||||
|
Countback: omit.From(subreddit.Countback),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
if sqlite3err := new(sqlite3.Error); errors.As(err, &sqlite3err) {
|
||||||
|
if sqlite3err.Code == sqlite3.ErrConstraint {
|
||||||
|
return errs.
|
||||||
|
Wrapw(err, "subreddit already exists", "input", subreddit).
|
||||||
|
Code(connect.CodeAlreadyExists)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errs.Wrap(err, "failed to insert subreddit")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package converter
|
package converts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/aarondl/opt/omit"
|
"github.com/aarondl/opt/omit"
|
||||||
|
|
21
go/converts/subreddit.go
Normal file
21
go/converts/subreddit.go
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
package converts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tigorlazuardi/bluemage/go/gen/models"
|
||||||
|
subreddits "github.com/tigorlazuardi/bluemage/go/gen/proto/subreddits/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// goverter:converter
|
||||||
|
// goverter:extend BoolToInt8 SubredditTypeToString Int8ToBool PtrBoolToOmitInt8
|
||||||
|
// goverter:extend PtrStringToOmitString PtrFloat64ToOmitFloat64 PtrInt32ToOmitInt32
|
||||||
|
type SubredditConverter interface {
|
||||||
|
// goverter:ignore CreatedAt UpdatedAt R CoverImageID
|
||||||
|
CreateSubredditRequestToModelsSubreddit(*subreddits.CreateSubredditRequest) *models.Subreddit
|
||||||
|
}
|
||||||
|
|
||||||
|
func SubredditTypeToString(subType subreddits.SubredditType) string {
|
||||||
|
if subType == subreddits.SubredditType_SUBREDDIT_TYPE_USER {
|
||||||
|
return "user"
|
||||||
|
}
|
||||||
|
return "r"
|
||||||
|
}
|
|
@ -19,16 +19,16 @@ type DeviceHandler struct {
|
||||||
v1connect.UnimplementedDeviceServiceHandler
|
v1connect.UnimplementedDeviceServiceHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
var convert converter.DeviceConverterImpl
|
var deviceConvert converter.DeviceConverterImpl
|
||||||
|
|
||||||
// CreateDevice implements v1connect.DeviceServiceHandler.
|
// CreateDevice implements v1connect.DeviceServiceHandler.
|
||||||
func (d *DeviceHandler) CreateDevice(ctx context.Context, request *connect.Request[device.CreateDeviceRequest]) (*connect.Response[device.CreateDeviceResponse], error) {
|
func (d *DeviceHandler) CreateDevice(ctx context.Context, request *connect.Request[device.CreateDeviceRequest]) (*connect.Response[device.CreateDeviceResponse], error) {
|
||||||
dev := convert.CreateDeviceRequestToModelsDevice(request.Msg)
|
dev := deviceConvert.CreateDeviceRequestToModelsDevice(request.Msg)
|
||||||
dev, err := d.API.DevicesCreate(ctx, dev)
|
dev, err := d.API.DevicesCreate(ctx, dev)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errs.IntoConnectError(err)
|
return nil, errs.IntoConnectError(err)
|
||||||
}
|
}
|
||||||
devResp := convert.ModelsDeviceToCreateDeviceResponse(dev)
|
devResp := deviceConvert.ModelsDeviceToCreateDeviceResponse(dev)
|
||||||
return connect.NewResponse(devResp), nil
|
return connect.NewResponse(devResp), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ func (d *DeviceHandler) GetDevice(ctx context.Context, request *connect.Request[
|
||||||
return nil, errs.IntoConnectError(err)
|
return nil, errs.IntoConnectError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
devResp := convert.ModelsDeviceToGetDeviceResponse(dev)
|
devResp := deviceConvert.ModelsDeviceToGetDeviceResponse(dev)
|
||||||
return connect.NewResponse(devResp), nil
|
return connect.NewResponse(devResp), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ func (d *DeviceHandler) ListDevices(ctx context.Context, request *connect.Reques
|
||||||
// Only fields that are set in the request will be updated.
|
// Only fields that are set in the request will be updated.
|
||||||
func (de *DeviceHandler) UpdateDevice(ctx context.Context, request *connect.Request[device.UpdateDeviceRequest]) (*connect.Response[device.UpdateDeviceResponse], error) {
|
func (de *DeviceHandler) UpdateDevice(ctx context.Context, request *connect.Request[device.UpdateDeviceRequest]) (*connect.Response[device.UpdateDeviceResponse], error) {
|
||||||
slug := request.Msg.Slug
|
slug := request.Msg.Slug
|
||||||
set := convert.DeviceSetterProtoToModelsDeviceSetter(request.Msg.Set)
|
set := deviceConvert.DeviceSetterProtoToModelsDeviceSetter(request.Msg.Set)
|
||||||
err := de.API.DevicesUpdate(ctx, slug, set)
|
err := de.API.DevicesUpdate(ctx, slug, set)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errs.IntoConnectError(err)
|
return nil, errs.IntoConnectError(err)
|
||||||
|
|
79
go/server/subreddit_handlers.go
Normal file
79
go/server/subreddit_handlers.go
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"connectrpc.com/connect"
|
||||||
|
"github.com/tigorlazuardi/bluemage/go/api"
|
||||||
|
"github.com/tigorlazuardi/bluemage/go/gen/converter"
|
||||||
|
subreddits "github.com/tigorlazuardi/bluemage/go/gen/proto/subreddits/v1"
|
||||||
|
"github.com/tigorlazuardi/bluemage/go/gen/proto/subreddits/v1/v1connect"
|
||||||
|
"github.com/tigorlazuardi/bluemage/go/pkg/errs"
|
||||||
|
)
|
||||||
|
|
||||||
|
var subredditConverter = converter.SubredditConverterImpl{}
|
||||||
|
|
||||||
|
type SubredditHandler struct {
|
||||||
|
API *api.API
|
||||||
|
|
||||||
|
v1connect.UnimplementedSubredditsServiceHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateSubreddit creates a new subreddit
|
||||||
|
// Returns the subreddit name.
|
||||||
|
//
|
||||||
|
// Returns the following error codes:
|
||||||
|
// - connect.CodeAlreadyExists if subreddit with the same name already exists.
|
||||||
|
// - connect.CodeInvalidArgument if validation failed, e.g. Invalid schedule cron format.
|
||||||
|
// - connect.CodeNotFound if the subreddit does not exist.
|
||||||
|
func (su *SubredditHandler) CreateSubreddit(ctx context.Context, request *connect.Request[subreddits.CreateSubredditRequest]) (*connect.Response[subreddits.CreateSubredditResponse], error) {
|
||||||
|
data := subredditConverter.CreateSubredditRequestToModelsSubreddit(request.Msg)
|
||||||
|
if err := su.API.SubredditCreate(ctx, data); err != nil {
|
||||||
|
return nil, errs.IntoConnectError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := &subreddits.CreateSubredditResponse{
|
||||||
|
Name: data.Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
return connect.NewResponse(resp), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSubreddit returns a subreddit by its name.
|
||||||
|
//
|
||||||
|
// Returns error with connect.CodeNotFound if subreddit does not exist.
|
||||||
|
func (su *SubredditHandler) GetSubreddit(_ context.Context, _ *connect.Request[subreddits.GetSubredditRequest]) (*connect.Response[subreddits.GetSubredditResponse], error) {
|
||||||
|
panic("not implemented") // TODO: Implement
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListSubreddits returns a list of subreddits.
|
||||||
|
func (su *SubredditHandler) ListSubreddits(_ context.Context, _ *connect.Request[subreddits.ListSubredditsRequest]) (*connect.Response[subreddits.ListSubredditsResponse], error) {
|
||||||
|
panic("not implemented") // TODO: Implement
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSubreddit updates a subreddit.
|
||||||
|
//
|
||||||
|
// Only the fields that are set in the request will be updated.
|
||||||
|
//
|
||||||
|
// Returns error with connect.CodeNotFound if subreddit does not exist.
|
||||||
|
func (su *SubredditHandler) UpdateSubreddit(_ context.Context, _ *connect.Request[subreddits.UpdateSubredditRequest]) (*connect.Response[subreddits.UpdateSubredditResponse], error) {
|
||||||
|
panic("not implemented") // TODO: Implement
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteSubreddit deletes a subreddit.
|
||||||
|
//
|
||||||
|
// Returns error with connect.CodeNotFound if subreddit does not exist.
|
||||||
|
func (su *SubredditHandler) DeleteSubreddit(_ context.Context, _ *connect.Request[subreddits.DeleteSubredditRequest]) (*connect.Response[subreddits.DeleteSubredditResponse], error) {
|
||||||
|
panic("not implemented") // TODO: Implement
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolveSubredditName resolves the given subreddit name.
|
||||||
|
//
|
||||||
|
// The returned resolved_name is the name that is actually
|
||||||
|
// used in Reddit.
|
||||||
|
//
|
||||||
|
// Returns error with connect.CodeNotFound if subreddit does not exist.
|
||||||
|
// So this rpc endpoint also acts to check subreddit's existence.
|
||||||
|
func (su *SubredditHandler) ResolveSubredditName(_ context.Context, _ *connect.Request[subreddits.ResolveSubredditNameRequest]) (*connect.Response[subreddits.ResolveSubredditNameResponse], error) {
|
||||||
|
panic("not implemented") // TODO: Implement
|
||||||
|
}
|
|
@ -18,7 +18,7 @@ message CreateSubredditRequest {
|
||||||
// schedule is cron job spec to set schedule on when
|
// schedule is cron job spec to set schedule on when
|
||||||
// the runner for this subreddit runs.
|
// the runner for this subreddit runs.
|
||||||
string schedule = 4 [(buf.validate.field).string.min_len = 1];
|
string schedule = 4 [(buf.validate.field).string.min_len = 1];
|
||||||
uint32 countback = 5 [(buf.validate.field).uint32.gt = 0];
|
int64 countback = 5 [(buf.validate.field).int64.gt = 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SubredditType {
|
enum SubredditType {
|
||||||
|
|
Loading…
Reference in a new issue