171 lines
6.5 KiB
Go
171 lines
6.5 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"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"
|
|
v1connect "github.com/tigorlazuardi/bluemage/go/gen/proto/subreddits/v1/subredditsv1connect"
|
|
"github.com/tigorlazuardi/bluemage/go/pkg/errs"
|
|
)
|
|
|
|
var subredditConverter = converter.SubredditConverterImpl{}
|
|
|
|
type SubredditHandler struct {
|
|
API *api.API
|
|
|
|
v1connect.UnimplementedSubredditsServiceHandler
|
|
}
|
|
|
|
// SubredditExists checks if the subreddits already handled in database.
|
|
// THIS ENDPOINT DOES NOT CALL REDDIT API, ONLY DATABASE.
|
|
//
|
|
// Use ResolveSubredditName to check if subreddit actually exists in Reddit.
|
|
func (su *SubredditHandler) SubredditExists(ctx context.Context, request *connect.Request[subreddits.SubredditExistsRequest]) (*connect.Response[subreddits.SubredditExistsResponse], error) {
|
|
exist, err := su.API.SubredditExists(ctx, request.Msg.Name)
|
|
if err != nil {
|
|
return nil, errs.IntoConnectError(err)
|
|
}
|
|
resp := &subreddits.SubredditExistsResponse{
|
|
Exist: exist,
|
|
}
|
|
return connect.NewResponse(resp), nil
|
|
}
|
|
|
|
// Count the existing subreddits using given filter.
|
|
// Default values count all.
|
|
func (su *SubredditHandler) CountSubreddits(ctx context.Context, request *connect.Request[subreddits.CountSubredditsRequest]) (*connect.Response[subreddits.CountSubredditsResponse], error) {
|
|
countRequest := subredditConverter.ProtoCountSubredditsRequestToAPICountSubredditsRequest(request.Msg)
|
|
count, err := su.API.CountSubreddits(ctx, countRequest)
|
|
if err != nil {
|
|
return nil, errs.IntoConnectError(err)
|
|
}
|
|
resp := &subreddits.CountSubredditsResponse{
|
|
Count: count,
|
|
}
|
|
return connect.NewResponse(resp), nil
|
|
}
|
|
|
|
// 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) {
|
|
resolveRequest := subredditConverter.ProtoCreateSubredditRequestToAPISubredditResolveNameRequest(request.Msg)
|
|
resolved, err := su.API.SubredditResolveName(ctx, resolveRequest)
|
|
if err != nil {
|
|
return nil, errs.IntoConnectError(err)
|
|
}
|
|
request.Msg.Name = resolved
|
|
|
|
data := subredditConverter.CreateSubredditRequestToModelsSubredditSetter(request.Msg)
|
|
if err := su.API.SubredditCreate(ctx, data); err != nil {
|
|
return nil, errs.IntoConnectError(err)
|
|
}
|
|
|
|
resp := &subreddits.CreateSubredditResponse{
|
|
Name: resolved,
|
|
}
|
|
|
|
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(ctx context.Context, request *connect.Request[subreddits.GetSubredditRequest]) (*connect.Response[subreddits.GetSubredditResponse], error) {
|
|
data, err := su.API.GetSubreddit(ctx, request.Msg.Name)
|
|
if err != nil {
|
|
return nil, errs.IntoConnectError(err)
|
|
}
|
|
|
|
resp := &subreddits.GetSubredditResponse{
|
|
Subreddit: subredditConverter.JetSubredditToProtoSubreddit(data),
|
|
}
|
|
return connect.NewResponse(resp), nil
|
|
}
|
|
|
|
// ListSubreddits returns a list of subreddits.
|
|
func (su *SubredditHandler) ListSubreddits(ctx context.Context, request *connect.Request[subreddits.ListSubredditsRequest]) (*connect.Response[subreddits.ListSubredditsResponse], error) {
|
|
req := subredditConverter.ProtoListSubredditsRequestToAPIListSubredditsRequest(request.Msg)
|
|
subs, err := su.API.ListSubreddits(ctx, req)
|
|
if err != nil {
|
|
return nil, errs.IntoConnectError(err)
|
|
}
|
|
resp := &subreddits.ListSubredditsResponse{
|
|
Subreddits: subredditConverter.JetSubredditsToProtoSubreddits(subs),
|
|
}
|
|
return connect.NewResponse(resp), nil
|
|
}
|
|
|
|
// 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(ctx context.Context, request *connect.Request[subreddits.UpdateSubredditRequest]) (*connect.Response[subreddits.UpdateSubredditResponse], error) {
|
|
exist, err := su.API.SubredditExists(ctx, request.Msg.Name)
|
|
if err != nil {
|
|
return nil, errs.IntoConnectError(err)
|
|
}
|
|
if !exist {
|
|
err := errs.
|
|
Failf("subreddit '%s' is not registered", request.Msg.Name).
|
|
Details("request", request.Msg).
|
|
Code(connect.CodeNotFound)
|
|
return nil, errs.IntoConnectError(err)
|
|
}
|
|
set := subredditConverter.ProtoSubredditSetterToBobSubredditSetter(request.Msg.Set)
|
|
err = su.API.UpdateSubreddit(ctx, request.Msg.Name, set)
|
|
if err != nil {
|
|
return nil, errs.IntoConnectError(err)
|
|
}
|
|
resp := &subreddits.UpdateSubredditResponse{
|
|
Name: request.Msg.Name,
|
|
}
|
|
return connect.NewResponse(resp), nil
|
|
}
|
|
|
|
// DeleteSubreddit deletes a subreddit.
|
|
//
|
|
// Returns error with connect.CodeNotFound if subreddit does not exist.
|
|
func (su *SubredditHandler) DeleteSubreddit(ctx context.Context, request *connect.Request[subreddits.DeleteSubredditRequest]) (*connect.Response[subreddits.DeleteSubredditResponse], error) {
|
|
exist, err := su.API.SubredditExists(ctx, request.Msg.Name)
|
|
if err != nil {
|
|
return nil, errs.IntoConnectError(err)
|
|
}
|
|
if !exist {
|
|
err := errs.
|
|
Failf("subreddit '%s' is not registered", request.Msg.Name).
|
|
Code(connect.CodeNotFound)
|
|
return nil, errs.IntoConnectError(err)
|
|
}
|
|
|
|
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("deleting subreddit is still unimplemented"))
|
|
}
|
|
|
|
// 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(ctx context.Context, request *connect.Request[subreddits.ResolveSubredditNameRequest]) (*connect.Response[subreddits.ResolveSubredditNameResponse], error) {
|
|
req := subredditConverter.ProtoResolveSubredditNameRequestToAPISubredditResolveName(request.Msg)
|
|
resolved, err := su.API.SubredditResolveName(ctx, req)
|
|
if err != nil {
|
|
return nil, errs.IntoConnectError(err)
|
|
}
|
|
resp := &subreddits.ResolveSubredditNameResponse{
|
|
Resolved: resolved,
|
|
}
|
|
return connect.NewResponse(resp), nil
|
|
}
|