Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
6b210f7
wip: init + testing social feed
hthieu1110 Jul 3, 2023
7562657
feat: add tests
hthieu1110 Jul 4, 2023
8f67fcb
wip: try to output object to strinng
hthieu1110 Jul 4, 2023
3f5d519
wip: stringify objects
Jul 5, 2023
72eb493
feat: user binutils to convert data to buffer
hthieu1110 Jul 5, 2023
121faab
feat: add binutils
hthieu1110 Jul 5, 2023
5dc2d12
Merge branch 'feat/add-socia-feed-realm' of github.com:TERITORI/gno i…
hthieu1110 Jul 5, 2023
87cf403
wip: encoding reactions
Jul 6, 2023
7c1f7a2
feat: add GetPost by id
hthieu1110 Jul 6, 2023
fc909b0
wip: handle subposts
hthieu1110 Jul 10, 2023
e2a6a60
feat: add pagination for query posts/comments
Jul 10, 2023
736143e
feat: handle pginnations for posts
hthieu1110 Jul 10, 2023
c683cd3
chore: remove uneeded files
hthieu1110 Jul 10, 2023
c6ea0c6
Merge remote-tracking branch 'origin' into feat/add-socia-feed-realm
hthieu1110 Aug 3, 2023
18d7e3b
fix: remove unneeded AssertOrig
hthieu1110 Aug 3, 2023
b48e66d
feat: add render + remove check for origCaller
hthieu1110 Aug 5, 2023
6fb95d7
feat: add extra binutils
hthieu1110 Aug 5, 2023
dc88135
feat: add extra binutils
hthieu1110 Aug 5, 2023
a440d7f
chore: update module name
hthieu1110 Aug 5, 2023
5adb1a9
chore: update module name
hthieu1110 Aug 5, 2023
20481ba
feat: handle all categories
hthieu1110 Aug 8, 2023
030a5fb
feat: update social_feeds_v4
hthieu1110 Aug 8, 2023
5f05ad7
chore: optimize test code
hthieu1110 Aug 12, 2023
0f93a72
Add TipPost + tests
hthieu1110 Aug 12, 2023
480ebcc
Add filter by user + test
hthieu1110 Aug 12, 2023
e681af4
feat: add migration to social_feeds
hthieu1110 Aug 13, 2023
03e03a9
wip: add flag
hthieu1110 Aug 14, 2023
c662f34
wip: add flags
hthieu1110 Aug 14, 2023
2e93a46
wip
hthieu1110 Aug 15, 2023
208face
wip: add missinng files
hthieu1110 Aug 15, 2023
f9ffa3c
fix: test bank send
hthieu1110 Aug 15, 2023
d282920
chore: change branch
hthieu1110 Aug 16, 2023
cefd249
wip: handle flag posts
hthieu1110 Aug 17, 2023
cecc1fd
wip: handle flag post + temporary fix filter hidden posts due to Get…
hthieu1110 Aug 18, 2023
5871be5
feat: add hiddenPostsForUser
hthieu1110 Aug 18, 2023
56df907
chore: add daodao pkg
hthieu1110 Aug 21, 2023
1301aeb
Merge remote-tracking branch 'origin/master' into feat/add-socia-feed…
hthieu1110 Aug 21, 2023
a6b3eb1
chore: add files for daodao plg
hthieu1110 Aug 21, 2023
af44d23
chore: add needed utils
hthieu1110 Aug 21, 2023
c5b3f9f
wip: add flag post
hthieu1110 Aug 21, 2023
ea6a39b
feat: done flag post + exec
hthieu1110 Aug 22, 2023
95285aa
chore: rename social_feeds_v5
hthieu1110 Aug 22, 2023
749b9b2
feat: deploy all updated versions
hthieu1110 Aug 22, 2023
86d82b0
fix: add missing pkg to gno.mod
hthieu1110 Sep 5, 2023
c9502dd
fix: fix pagination when querying posts
hthieu1110 Sep 5, 2023
5af5dbe
feat: add test for query out of range
hthieu1110 Sep 5, 2023
f645019
wip: migrate
hthieu1110 Sep 6, 2023
a45fd60
wip
hthieu1110 Sep 6, 2023
80c5aad
feat: done migration + wip: testing migration
hthieu1110 Sep 8, 2023
0f72bcd
feat: handle comments by parentID instead of comments array
hthieu1110 Sep 8, 2023
8948048
feat: use json encoding + adjust tests
hthieu1110 Sep 8, 2023
fcad5c5
feat: done migration JSON
hthieu1110 Sep 8, 2023
7371b6f
fix: optimize char used for metadata
hthieu1110 Sep 8, 2023
8800438
feat: add social_feeds_v8 + social_feeds_dao_v2
hthieu1110 Sep 9, 2023
ddd6f11
fix unicode pkg
hthieu1110 Sep 11, 2023
758edfc
fix: parserString
hthieu1110 Sep 11, 2023
8a20006
update gno pkg with updated ujson
hthieu1110 Sep 11, 2023
af6c3dc
update feeds with update string parsed
hthieu1110 Sep 11, 2023
3ea5128
update teritori group name
hthieu1110 Sep 14, 2023
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
77 changes: 77 additions & 0 deletions examples/gno.land/r/demo/social_feeds/feed.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package social_feeds

import (
"std"
"time"

"gno.land/p/demo/avl"
)

type FeedID uint64

type Feed struct {
id FeedID
url string
name string
creator std.Address
owner std.Address
posts avl.Tree // Post.id -> *Post
createdAt time.Time
deleted avl.Tree

postsCtr uint64
}

func newFeed(fid FeedID, url string, name string, creator std.Address) *Feed {
if !reName.MatchString(name) {
panic("invalid feed name: " + name)
}

if gFeedsByName.Has(name) {
panic("feed already exists: " + name)
}

return &Feed{
id: fid,
url: url,
name: name,
creator: creator,
owner: creator,
posts: avl.Tree{},
createdAt: time.Now(),
deleted: avl.Tree{},

postsCtr: 0,
}
}

func (feed *Feed) incGetPostID() PostID {
feed.postsCtr++
return PostID(feed.postsCtr)
}

func (feed *Feed) GetPost(pid PostID) *Post {
Copy link
Collaborator

@n0izn0iz n0izn0iz Jul 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these should return a copy of Post, otherwise other realms could arbitrarily call Post.Update or Post.Delete I think

Copy link
Collaborator

@n0izn0iz n0izn0iz Aug 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually there is a mechanism where a realm cannot modify objects owned by other realms so this might not be needed

just FYI: currently there is a bug in it that allows to change ownership when you store a pointer that is passed to you

pidkey := postIDKey(pid)
post_, exists := feed.posts.Get(pidkey)
if !exists {
return nil
}
return post_.(*Post)
}

func (feed *Feed) MustGetPost(pid PostID) *Post {
post := feed.GetPost(pid)
if post == nil {
panic("post does not exist")
}
return post
}

func (feed *Feed) AddPost(creator std.Address, parentID PostID, category uint64, metadata string) *Post {
pid := feed.incGetPostID()
pidkey := postIDKey(pid)

post := newPost(feed, pid, creator, parentID, category, metadata)
feed.posts.Set(pidkey, post)
return post
}
22 changes: 22 additions & 0 deletions examples/gno.land/r/demo/social_feeds/feeds.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package social_feeds

import (
"regexp"

"gno.land/p/demo/avl"
)

//----------------------------------------
// Realm (package) state

var (
gFeeds avl.Tree // id -> *Feed
gFeedsCtr int // increments Feed.id
gFeedsByName avl.Tree // name -> *Feed
gDefaultAnonFee = 100000000 // minimum fee required if anonymous
)

//----------------------------------------
// Constants

var reName = regexp.MustCompile(`^[a-z]+[_a-z0-9]{2,29}$`)
45 changes: 45 additions & 0 deletions examples/gno.land/r/demo/social_feeds/feeds_test.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package social_feeds

import (
"fmt"
"testing"

"gno.land/r/demo/users"
)

func Test(t *testing.T) {
{
// Create Feed
testing.SetOrigCaller("yo")
feedID := CreateFeed("teritori")

if feedID != 1 {
t.Fatalf("expected feedID: 1, got %q.", feedID)
}
}
{
// Create Post
postID := CreatePost(1, 0, 0, `{"gifs": [], "files": [], "title": "", "message": "testouille", "hashtags": [], "mentions": [], "createdAt": "2023-03-29T12:19:04.858Z", "updatedAt": "2023-03-29T12:19:04.858Z"}`)

if postID != 1 {
t.Fatalf("expected postID: 1, got %q.", postID)
}
}
{
// React Post
ReactPost(1, 1, "🥰", true)

feed := mustGetFeed(1)
post := feed.MustGetPost(1)

reactionCount_, ok := post.reactions.Get("🥰")
if !ok {
t.Fatalf("expected 🥰 exists")
}

reactionCount := reactionCount_.(int)
if reactionCount != 1 {
t.Fatalf("expected reactionCount: 1, got %q.", reactionCount)
}
}
}
6 changes: 6 additions & 0 deletions examples/gno.land/r/demo/social_feeds/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module gno.land/r/demo/social_feeds

require (
"gno.land/p/demo/avl" v0.0.0-latest
"gno.land/r/demo/users" v0.0.0-latest
)
66 changes: 66 additions & 0 deletions examples/gno.land/r/demo/social_feeds/misc.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package social_feeds

import (
"std"
"strconv"
"strings"

"gno.land/r/demo/users"
)

func getFeed(fid FeedID) *Feed {
fidkey := feedIDKey(fid)
feed_, exists := gFeeds.Get(fidkey)
if !exists {
return nil
}
feed := feed_.(*Feed)
return feed
}

func mustGetFeed(fid FeedID) *Feed {
feed := getFeed(fid)
if feed == nil {
panic("Feed does not exist")
}
return feed
}

func incGetFeedID() FeedID {
gFeedsCtr++
return FeedID(gFeedsCtr)
}

func usernameOf(addr std.Address) string {
user := users.GetUserByAddress(addr)
if user == nil {
return ""
} else {
return user.Name()
}
}

func feedIDKey(fid FeedID) string {
return padZero(uint64(fid), 10)
}

func postIDKey(pid PostID) string {
return padZero(uint64(pid), 10)
}

func padLeft(str string, length int) string {
if len(str) >= length {
return str
} else {
return strings.Repeat(" ", length-len(str)) + str
}
}

func padZero(u64 uint64, length int) string {
str := strconv.Itoa(int(u64))
if len(str) >= length {
return str
} else {
return strings.Repeat("0", length-len(str)) + str
}
}
87 changes: 87 additions & 0 deletions examples/gno.land/r/demo/social_feeds/post.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package social_feeds

import (
"std"
"strconv"
"time"

"gno.land/p/demo/avl"
)

type PostID uint64

type Reaction struct {
icon string
count uint64
}

var Categories []string = []string{
"Reaction",
"Comment",
"Norman",
"Article",
"Picture",
"Audio",
"Video",
}

type Post struct {
id PostID
parentID PostID
feedID FeedID
category uint64
metadata string
reactions avl.Tree
creator std.Address
deleted bool

createdAt time.Time
updatedAt time.Time
deletedAt time.Time
}

func newPost(feed *Feed, id PostID, creator std.Address, parentID PostID, category uint64, metadata string) *Post {
return &Post{
id: id,
parentID: parentID,
feedID: feed.id,
category: category,
metadata: metadata,
reactions: avl.Tree{},
creator: creator,
createdAt: time.Now(),
}
}

func (post *Post) Update(category uint64, metadata string) {
post.category = category
post.metadata = metadata
post.updatedAt = time.Now()
}

func (post *Post) Delete() {
post.deleted = true
post.deletedAt = time.Now()
}

// Always remove reaction if count = 0
func (post *Post) React(icon string, up bool) {
count_, ok := post.reactions.Get(icon)
count := 0

if ok {
count = count_.(int)
}

if up {
count++
} else {
count--
}

if count <= 0 {
post.reactions.Remove(icon)
} else {
post.reactions.Set(icon, count)
}
}
84 changes: 84 additions & 0 deletions examples/gno.land/r/demo/social_feeds/public.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package social_feeds

import (
"std"
"strconv"
)

func CreateFeed(name string) FeedID {
std.AssertOriginCall()
fid := incGetFeedID()
caller := std.PrevRealm().Addr()
if usernameOf(caller) == "" {
panic("unauthorized")
}
url := "/r/demo/feeds:" + name
feed := newFeed(fid, url, name, caller)
fidkey := feedIDKey(fid)
gFeeds.Set(fidkey, feed)
gFeedsByName.Set(name, feed)
return feed.id
}

// Anyone can create a post in a existing feed
// Anonymous user has to pay a configurable minimum fee
func CreatePost(fid FeedID, parentID PostID, catetory uint64, metadata string) PostID {
std.AssertOriginCall()
caller := std.PrevRealm().Addr()

// if usernameOf(caller) == "" {
// if !checkAnonFee() {
// panic("please register, otherwise minimum fee " + strconv.Itoa(gDefaultAnonFee) + " is required if anonymous")
// }
// }
feed := mustGetFeed(fid)
post := feed.AddPost(caller, parentID, catetory, metadata)
return post.id
}

// Only post's owner can edit post
func EditPost(fid FeedID, pid PostID, category uint64, metadata string) {
std.AssertOriginCall()
caller := std.PrevRealm().Addr()
feed := mustGetFeed(fid)
post := feed.MustGetPost(pid)

if caller != post.creator {
panic("you are not creator of this post")
}

post.Update(category, metadata)
}

// Only owner can delete the post
func DeletePost(fid FeedID, pid PostID) {
std.AssertOriginCall()
caller := std.PrevRealm().Addr()
feed := mustGetFeed(fid)
post := feed.MustGetPost(pid)

if caller != post.creator {
panic("you are not creator of this post")
}

post.Delete()
}

// Any one can react post
func ReactPost(fid FeedID, pid PostID, icon string, up bool) {
std.AssertOriginCall()
caller := std.PrevRealm().Addr()
feed := mustGetFeed(fid)
post := feed.MustGetPost(pid)

post.React(icon, up)
}

func checkAnonFee() bool {
sent := std.GetOrigSend()
anonFeeCoin := std.Coin{"ugnot", int64(gDefaultAnonFee)}
if len(sent) == 1 && sent[0].IsGTE(anonFeeCoin) {
return true
}
return false
}