The types needed in the entire system are defined here.

The complete types.mo file:

import Principal "mo:base/Principal";
import Time "mo:base/Time";

module {

// ==================== Feed ====================

    public type UserId = Principal;
    public type Time = Time.Time;
    public type PostId = Text; // Post ID = BucketCanisterID + UserId + Incremental

    public type Post = {
        postId: PostId; // Post ID
        feedCanister: Principal;
        index: Nat; // Post Index
        user: UserId; // Publisher
        content: Text;
        var repost: [Repost]; // Reposters
        var like: [Like];
        var comment: [Comment];
        createdAt: Time; // Publication time
    };

    public type PostImmutable = {
        postId: PostId; // Post ID
        feedCanister: Principal;
        index: Nat; // Post Index
        user: UserId; // Publisher
        content: Text;
        repost: [Repost]; // Reposters
        like: [Like];
        comment: [Comment];
        createdAt: Time; // Publication time
    };

    public type Comment = {
        user: UserId;
        content: Text;
        createdAt: Time;
    };

    public type NewComment = [Comment];

    public type Like = {
        user: UserId;
        createdAt: Time;
    };

    public type Repost = {
        user: UserId;
        createdAt: Time;
    };

    public type NewRepost = [Repost];

    public type NewLike = [Like];

    public type RootFeedActor = actor {
        getAllUserFeedCanister: shared query () -> async [(Principal, Principal)];
    };

    public type FeedActor = actor {
        getPosts: shared query () -> async [PostImmutable];
        receiveFeed: shared (Text) -> async Bool;
        batchReceiveFeed: shared ([Text]) -> async ();
        batchReceiveComment: shared ([Text]) -> async ();
        batchReceiveLike: shared ([Text]) -> async ();
        createComment: shared (Principal, Nat, Text) -> async ();
        deleteComment: shared (Principal, Nat, Nat) -> async ();
        createLike: shared (Principal, Nat) -> async ();
        deleteLike: shared (Principal, Nat) -> async ();
        updateFollowers: shared ([Principal]) -> async ();
    };

// ==================== Post ====================

    public type RootPostActor = actor {
        getAvailableBucket: shared query () -> async ?Principal;
        getAllBuckets: shared query () -> async [Principal];
        getAllAvailableBuckets: shared query () -> async [Principal];
        getAllUnavailableBuckets: shared query () -> async [Principal];
        reCreateBucket: shared () -> async ();
    };

// ==================== Bucket ====================

    public type BucketActor = actor {
        storeFeed: shared (PostImmutable) -> async Bool;
        updatePostComment: shared (Text, NewComment) -> async Bool;
        updatePostLike: shared (Text, NewLike) -> async Bool;
        updatePostRepost: shared (Text, NewRepost) -> async Bool;
        getPosts: shared query ([Text]) -> async [PostImmutable];
        getPost: shared query (Text) -> async ?PostImmutable;
    };

// ==================== Fetch ====================

    public type RootFetchActor = actor {
        createPostFetchCanister: shared () -> async Principal;
        createCommentFetchCanister: shared () -> async Principal;
        createLikeFetchCanister: shared () -> async Principal;
        getAllPostFetchCanister: shared query () -> async [Principal];
        getAllCommentFetchCanister: shared query () -> async [Principal];
        getAllLikeFetchCanister: shared query () -> async [Principal];
    };

    public type PostFetchActor = actor {
        receiveNotify: shared ([Principal], Text) -> async ();
        addUserToFeedEntry: shared ((Principal, Principal)) -> async Bool;
        initUserToFeed: shared ([(Principal, Principal)]) -> async Bool;
    };

    public type CommentFetchActor = actor {
        receiveNotify: shared (PostImmutable) -> async ();
        receiveRepostUserNotify: shared ([Principal], Text) -> async ();
        addUserToFeedEntry: shared ((Principal, Principal)) -> async Bool;
        initUserToFeed: shared ([(Principal, Principal)]) -> async Bool;
    };

    public type LikeFetchActor = actor {
        receiveNotify: shared (PostImmutable) -> async ();
        receiveRepostUserNotify: shared ([Principal], Text) -> async ();
        addUserToFeedEntry: shared ((Principal, Principal)) -> async Bool;
        initUserToFeed: shared ([(Principal, Principal)]) -> async Bool;
    };

// ==================== User ====================

    public type Vertex = Principal;

    public type UserActor = actor {
        getFollowersList: shared query (Vertex) -> async [Vertex];
    };

}

utils.mo file provides some helper functions for handling posts.

The checkPostId function extracts the bucket ID, user ID, and post index from the post ID.

  • Parameters: postId - The unique identifier of the post (composed of BucketCanisterID + UserId + Incremental).
  • Return value: A tuple containing the extracted bucket (bucket ID), user (user ID), and postIndex (post index) from the post ID.

The _convertPostToImmutable function is used to convert a mutable post to an immutable post.

  • Parameters: post - Mutable post (Post).
  • Return value: A function that converts a mutable post to an immutable post (PostImmutable).

The _isRepostUser function checks if a specified user is one of the repost users for a given post.

  • Parameters: post - Immutable post (PostImmutable), user - User ID to check if it is a repost user.
  • Return value: Returns true if the specified user is one of the repost users for the post; otherwise, returns false.
import Iter "mo:base/Iter";
import Text "mo:base/Text";
import Principal "mo:base/Principal";
import Option "mo:base/Option";
import Nat "mo:base/Nat";
import Debug "mo:base/Debug";
import Types "./types";

module {
    type Post = Types.Post;
    type PostImmutable = Types.PostImmutable;

    public func checkPostId(postId: Text): (Principal, Principal, Nat) {
        let words = Iter.toArray(Text.split(postId, #char '#'));
        let bucket = Principal.fromText(words[0]);
        let user = Principal.fromText(words[1]);
        let postIndex = Option.unwrap(Nat.fromText(words[2]));
        // Debug.print("(bucket, user, index): (" # words[0] # "," # words[1] # "," # words[2] # ")");
        (bucket, user, postIndex)
    };

    public func _convertPostToImmutable(post: Post): PostImmutable {
      {
        postId = post.postId;
        index = post.index;
        feedCanister = post.feedCanister;
        user = post.user;
        repost = post.repost;
        content = post.content;
        like =

 post.like;
        comment = post.comment;
        createdAt = post.createdAt;
      }
    };

    public func _isRepostUser(post: PostImmutable, user: Principal): Bool {
        for (_repostUser in post.repost.vals()) {
            if (_repostUser.user == user) {
                return true;
            };
        };
        false
    };

}