Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Media Post Implementation #72

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- Implemented the support for arbitrary data inside a post (#52, #66)
- Implemented the support for posts reactions (#47)
- Implemented the support for posts subspaces (#46)
- Implemented the support for media in posts (#36)
RiccardoM marked this conversation as resolved.
Show resolved Hide resolved
- Automated the default bond denom change to `desmos` (#25)
- Replaced the block height with timestamps inside posts' creation dates and edit dates (#62)
- Capped the post message length to 500 characters (#67)
Expand Down
14 changes: 12 additions & 2 deletions x/posts/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ var (

// Types
NewReaction = types.NewReaction
NewPost = types.NewPost
NewTextPost = types.NewTextPost
NewMediaPost = types.NewMediaPost
ParsePostID = types.ParsePostID
DefaultGenesisState = types.DefaultGenesisState
ValidateGenesis = types.ValidateGenesis

// Msgs
NewMsgCreatePost = types.NewMsgCreatePost
NewMsgCreateTextPost = types.NewMsgCreateTextPost
NewMsgCreateMediaPost = types.NewMsgCreateMediaPost
NewMsgEditPost = types.NewMsgEditPost
NewMsgAddPostReaction = types.NewMsgAddPostReaction
NewMsgRemovePostReaction = types.NewMsgRemovePostReaction
Expand All @@ -48,12 +50,20 @@ type (
PostIDs = types.PostIDs
Post = types.Post
Posts = types.Posts
TextPost = types.TextPost
TextPosts = types.TextPosts
RiccardoM marked this conversation as resolved.
Show resolved Hide resolved
MediaPost = types.MediaPost
MediaPosts = types.MediaPosts
RiccardoM marked this conversation as resolved.
Show resolved Hide resolved
PostMedia = types.PostMedia
PostMedias = types.PostMedias
Reaction = types.Reaction
Reactions = types.Reactions
GenesisState = types.GenesisState

// Msgs
MsgCreatePost = types.MsgCreatePost
MsgCreateTextPost = types.MsgCreateTextPost
MsgCreateMediaPost = types.MsgCreateMediaPost
MsgEditPost = types.MsgEditPost
MsgAddPostReaction = types.MsgAddPostReaction
MsgRemovePostReaction = types.MsgRemovePostReaction
Expand Down
23 changes: 19 additions & 4 deletions x/posts/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cli
import (
"fmt"
"strconv"
"strings"
"time"

"github.com/cosmos/cosmos-sdk/version"
Expand Down Expand Up @@ -43,9 +44,9 @@ func GetTxCmd(_ string, cdc *codec.Codec) *cobra.Command {
// GetCmdCreatePost is the CLI command for creating a post
func GetCmdCreatePost(cdc *codec.Codec) *cobra.Command {
cmd := &cobra.Command{
Use: "create [subspace] [message] [allows-comments]",
Use: "create [subspace] [message] [allows-comments] [[[uri],[provider],[mime-type]]...]",
RiccardoM marked this conversation as resolved.
Show resolved Hide resolved
Short: "Create a new post",
Args: cobra.ExactArgs(3),
Args: cobra.MinimumNArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {

cliCtx := context.NewCLIContext().WithCodec(cdc)
Expand All @@ -67,11 +68,25 @@ func GetCmdCreatePost(cdc *codec.Codec) *cobra.Command {
return err
}

msg := types.NewMsgCreatePost(args[1], parentID, allowsComments, args[0], map[string]string{}, from, time.Now().UTC())
var msg types.MsgCreatePost

//if there's some medias
RiccardoM marked this conversation as resolved.
Show resolved Hide resolved
if len(args) > 3 {
var medias types.PostMedias
//read each media and add it to the medias if valid
for i := 3; i < len(args); i++ {
arg := strings.Split(args[i], ",")
media := types.NewPostMedia(arg[0], arg[1], arg[2])
RiccardoM marked this conversation as resolved.
Show resolved Hide resolved
medias = append(medias, media)
}
msg = types.NewMsgCreateMediaPost(args[1], parentID, allowsComments, args[0], map[string]string{}, from, time.Now().UTC(), medias)
} else {
msg = types.NewMsgCreateTextPost(args[1], parentID, allowsComments, args[0], map[string]string{}, from, time.Now().UTC())
}

RiccardoM marked this conversation as resolved.
Show resolved Hide resolved
if err = msg.ValidateBasic(); err != nil {
return err
}

return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg})
},
}
Expand Down
2 changes: 2 additions & 0 deletions x/posts/client/rest/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/types/rest"
"github.com/desmos-labs/desmos/x/posts/internal/types"
"github.com/gorilla/mux"
)

Expand All @@ -23,6 +24,7 @@ type CreatePostReq struct {
Subspace string `json:"subspace"`
OptionalData map[string]string `json:"optional_data"`
CreationTime time.Time `json:"creation_time"`
Medias types.PostMedias `json:"medias,omitempty"`
}

// AddReactionReq defines the properties of a reaction adding request's body.
Expand Down
10 changes: 9 additions & 1 deletion x/posts/client/rest/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,15 @@ func createPostHandler(cliCtx context.CLIContext) http.HandlerFunc {
return
}

msg := types.NewMsgCreatePost(req.Message, parentID, req.AllowsComments, req.Subspace, req.OptionalData, addr, req.CreationTime)
var msg types.MsgCreatePost
if req.Medias != nil && len(req.Medias) != 0 {
leobragaz marked this conversation as resolved.
Show resolved Hide resolved
msg = types.NewMsgCreateMediaPost(req.Message, parentID, req.AllowsComments, req.Subspace, req.OptionalData,
addr, req.CreationTime, req.Medias)
} else {
msg = types.NewMsgCreateTextPost(req.Message, parentID, req.AllowsComments, req.Subspace, req.OptionalData,
RiccardoM marked this conversation as resolved.
Show resolved Hide resolved
addr, req.CreationTime)
}

err = msg.ValidateBasic()
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
Expand Down
2 changes: 1 addition & 1 deletion x/posts/internal/keeper/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func testCodec() *codec.Codec {
var testPostOwner, _ = sdk.AccAddressFromBech32("cosmos1y54exmx84cqtasvjnskf9f63djuuj68p7hqf47")
var timeZone, _ = time.LoadLocation("UTC")
var testPostCreationDate = time.Date(2020, 1, 1, 15, 15, 00, 000, timeZone)
var testPost = types.NewPost(
var testPost = types.NewTextPost(
types.PostID(3257),
types.PostID(0),
"Post message",
Expand Down
88 changes: 55 additions & 33 deletions x/posts/internal/keeper/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import (
func NewHandler(keeper Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
switch msg := msg.(type) {
case types.MsgCreatePost:
return handleMsgCreatePost(ctx, keeper, msg)
case types.MsgEditPost:
return handleMsgEditPost(ctx, keeper, msg)
case types.MsgAddPostReaction:
return handleMsgAddPostReaction(ctx, keeper, msg)
case types.MsgRemovePostReaction:
return handleMsgRemovePostReaction(ctx, keeper, msg)
case types.MsgCreatePost:
return handleMsgCreatePost(ctx, keeper, msg)
default:
errMsg := fmt.Sprintf("Unrecognized Posts message type: %v", msg.Type())
return sdk.ErrUnknownRequest(errMsg).Result()
Expand All @@ -28,47 +28,69 @@ func NewHandler(keeper Keeper) sdk.Handler {

// handleMsgCreatePost handles the creation of a new post
func handleMsgCreatePost(ctx sdk.Context, keeper Keeper, msg types.MsgCreatePost) sdk.Result {
post := types.NewPost(
keeper.GetLastPostID(ctx).Next(),
msg.ParentID,
msg.Message,
msg.AllowsComments,
msg.Subspace,
msg.OptionalData,
msg.CreationDate,
msg.Creator,
)

var post types.Post

if textMsg, ok := msg.(types.MsgCreateTextPost); ok {
post = types.NewTextPost(
keeper.GetLastPostID(ctx).Next(),
textMsg.ParentID,
textMsg.Message,
textMsg.AllowsComments,
textMsg.Subspace,
textMsg.OptionalData,
textMsg.CreationDate,
textMsg.Creator,
)
}

if mediaMsg, ok := msg.(types.MsgCreateMediaPost); ok {
textPost := types.NewTextPost(
leobragaz marked this conversation as resolved.
Show resolved Hide resolved
keeper.GetLastPostID(ctx).Next(),
mediaMsg.MsgCreatePost.ParentID,
mediaMsg.MsgCreatePost.Message,
mediaMsg.MsgCreatePost.AllowsComments,
mediaMsg.MsgCreatePost.Subspace,
mediaMsg.MsgCreatePost.OptionalData,
mediaMsg.MsgCreatePost.CreationDate,
mediaMsg.MsgCreatePost.Creator,
)

post = types.NewMediaPost(textPost, mediaMsg.Medias)
}

// Check for double posting
if _, found := keeper.GetPost(ctx, post.PostID); found {
return sdk.ErrUnknownRequest(fmt.Sprintf("Post with id %s already exists", post.PostID)).Result()
if _, found := keeper.GetPost(ctx, post.GetID()); found {
return sdk.ErrUnknownRequest(fmt.Sprintf("Post with id %s already exists", post.GetID())).Result()
}

// If valid, check the parent post
if post.ParentID.Valid() {
parentPost, found := keeper.GetPost(ctx, post.ParentID)
if post.GetParentID().Valid() {
parentPost, found := keeper.GetPost(ctx, post.GetParentID())
if !found {
return sdk.ErrUnknownRequest(fmt.Sprintf("Parent post with id %s not found", post.ParentID)).Result()
return sdk.ErrUnknownRequest(fmt.Sprintf("Parent post with id %s not found",
post.GetParentID())).Result()
}

if !parentPost.AllowsComments {
return sdk.ErrUnknownRequest(fmt.Sprintf("Post with id %s does not allow comments", parentPost.PostID)).Result()
if !parentPost.CanComment() {
return sdk.ErrUnknownRequest(fmt.Sprintf("Post with id %s does not allow comments",
parentPost.GetID())).Result()
}
}

keeper.SavePost(ctx, post)

createEvent := sdk.NewEvent(
types.EventTypePostCreated,
sdk.NewAttribute(types.AttributeKeyPostID, post.PostID.String()),
sdk.NewAttribute(types.AttributeKeyPostParentID, post.ParentID.String()),
sdk.NewAttribute(types.AttributeKeyCreationTime, post.Created.String()),
sdk.NewAttribute(types.AttributeKeyPostOwner, post.Creator.String()),
sdk.NewAttribute(types.AttributeKeyPostID, post.GetID().String()),
sdk.NewAttribute(types.AttributeKeyPostParentID, post.GetParentID().String()),
sdk.NewAttribute(types.AttributeKeyCreationTime, post.CreationTime().String()),
sdk.NewAttribute(types.AttributeKeyPostOwner, post.Owner().String()),
)
ctx.EventManager().EmitEvent(createEvent)

return sdk.Result{
Data: keeper.Cdc.MustMarshalBinaryLengthPrefixed(post.PostID),
Data: keeper.Cdc.MustMarshalBinaryLengthPrefixed(post.GetID()),
Events: sdk.Events{createEvent},
}
}
Expand All @@ -83,29 +105,29 @@ func handleMsgEditPost(ctx sdk.Context, keeper Keeper, msg types.MsgEditPost) sd
}

// Checks if the the msg sender is the same as the current owner
if !msg.Editor.Equals(existing.Creator) {
if !msg.Editor.Equals(existing.Owner()) {
RiccardoM marked this conversation as resolved.
Show resolved Hide resolved
return sdk.ErrUnauthorized("Incorrect owner").Result()
}

// Check the validity of the current block height respect to the creation date of the post
if existing.Created.After(msg.EditDate) {
if existing.CreationTime().After(msg.EditDate) {
return sdk.ErrUnknownRequest("Edit date cannot be before creation date").Result()
}

// Edit the post
existing.Message = msg.Message
existing.LastEdited = msg.EditDate
existing = existing.SetMessage(msg.Message)
existing = existing.SetEditTime(msg.EditDate)
keeper.SavePost(ctx, existing)

editEvent := sdk.NewEvent(
types.EventTypePostEdited,
sdk.NewAttribute(types.AttributeKeyPostID, existing.PostID.String()),
sdk.NewAttribute(types.AttributeKeyPostEditTime, existing.LastEdited.String()),
sdk.NewAttribute(types.AttributeKeyPostID, existing.GetID().String()),
sdk.NewAttribute(types.AttributeKeyPostEditTime, existing.GetEditTime().String()),
)
ctx.EventManager().EmitEvent(editEvent)

return sdk.Result{
Data: keeper.Cdc.MustMarshalBinaryLengthPrefixed(existing.PostID),
Data: keeper.Cdc.MustMarshalBinaryLengthPrefixed(existing.GetID()),
Events: sdk.Events{editEvent},
}
}
Expand All @@ -120,7 +142,7 @@ func handleMsgAddPostReaction(ctx sdk.Context, keeper Keeper, msg types.MsgAddPo

// Create and store the reaction
reaction := types.NewReaction(msg.Value, msg.User)
if err := keeper.SaveReaction(ctx, post.PostID, reaction); err != nil {
if err := keeper.SaveReaction(ctx, post.GetID(), reaction); err != nil {
return err.Result()
}

Expand Down Expand Up @@ -148,7 +170,7 @@ func handleMsgRemovePostReaction(ctx sdk.Context, keeper Keeper, msg types.MsgRe
}

// Remove the reaction
if err := keeper.RemoveReaction(ctx, post.PostID, msg.User, msg.Reaction); err != nil {
if err := keeper.RemoveReaction(ctx, post.GetID(), msg.User, msg.Reaction); err != nil {
return err.Result()
}

Expand Down
Loading