PathrockNetwork Gno Explorer
HomeBlocksTransactionsRealmsPackagesValidators

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/gnoland/boards2/v0

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v0
Namespace
gnoland / boards2
Files
252 (README)(gnomod.toml)
Exported functions
51
Module
gno.land/r/gnoland/boards2/v0
gno
0.9

Files (252)

  • README.mdmarkdown
  • gnomod.tomltoml
  • boards.gnogno
  • doc.gnogno
  • flag.gnogno
  • format.gnogno
  • hub.gnogno
  • meta.gnogno
  • permissions_validators_basic.gnogno
  • permissions_validators_open.gnogno
  • permissions.gnogno
  • public_ban.gnogno
  • public_flag.gnogno
  • public_freeze.gnogno
  • public_invite.gnogno
  • public_lock.gnogno
  • public.gnogno
  • render_board.gnogno
  • render_post.gnogno
  • render_reply.gnogno
  • render_thread.gnogno
  • render.gnogno
  • uris_board.gnogno
  • uris_post.gnogno
  • z_accept_invite_00_filetest.gnogno
  • z_accept_invite_01_filetest.gnogno
  • z_accept_invite_02_filetest.gnogno
  • z_accept_invite_03_filetest.gnogno
  • z_ban_00_filetest.gnogno
  • z_ban_01_filetest.gnogno
  • z_ban_02_filetest.gnogno
  • z_change_member_role_00_filetest.gnogno
  • z_change_member_role_01_filetest.gnogno
  • z_change_member_role_02_filetest.gnogno
  • z_change_member_role_03_filetest.gnogno
  • z_change_member_role_04_filetest.gnogno
  • z_change_member_role_05_filetest.gnogno
  • z_change_member_role_06_filetest.gnogno
  • z_change_member_role_07_filetest.gnogno
  • z_create_board_00_filetest.gnogno
  • z_create_board_01_filetest.gnogno
  • z_create_board_02_filetest.gnogno
  • z_create_board_03_filetest.gnogno
  • z_create_board_04_filetest.gnogno
  • z_create_board_05_filetest.gnogno
  • z_create_board_06_filetest.gnogno
  • z_create_board_07_filetest.gnogno
  • z_create_board_08_filetest.gnogno
  • z_create_board_09_filetest.gnogno
  • z_create_board_10_filetest.gnogno
  • z_create_reply_00_filetest.gnogno
  • z_create_reply_01_filetest.gnogno
  • z_create_reply_02_filetest.gnogno
  • z_create_reply_03_filetest.gnogno
  • z_create_reply_04_filetest.gnogno
  • z_create_reply_05_filetest.gnogno
  • z_create_reply_06_filetest.gnogno
  • z_create_reply_07_filetest.gnogno
  • z_create_reply_08_filetest.gnogno
  • z_create_reply_09_filetest.gnogno
  • z_create_reply_10_filetest.gnogno
  • z_create_reply_11_filetest.gnogno
  • z_create_reply_12_filetest.gnogno
  • z_create_reply_13_filetest.gnogno
  • z_create_reply_14_filetest.gnogno
  • z_create_reply_15_filetest.gnogno
  • z_create_reply_16_filetest.gnogno
  • z_create_repost_00_filetest.gnogno
  • z_create_repost_01_filetest.gnogno
  • z_create_repost_02_filetest.gnogno
  • z_create_repost_03_filetest.gnogno
  • z_create_repost_04_filetest.gnogno
  • z_create_thread_00_filetest.gnogno
  • z_create_thread_01_filetest.gnogno
  • z_create_thread_02_filetest.gnogno
  • z_create_thread_03_filetest.gnogno
  • z_create_thread_04_filetest.gnogno
  • z_create_thread_05_filetest.gnogno
  • z_create_thread_06_filetest.gnogno
  • z_delete_reply_00_filetest.gnogno
  • z_delete_reply_01_filetest.gnogno
  • z_delete_reply_02_filetest.gnogno
  • z_delete_reply_03_filetest.gnogno
  • z_delete_reply_04_filetest.gnogno
  • z_delete_reply_05_filetest.gnogno
  • z_delete_reply_06_filetest.gnogno
  • z_delete_reply_07_filetest.gnogno
  • z_delete_reply_08_filetest.gnogno
  • z_delete_reply_09_filetest.gnogno
  • z_delete_thread_00_filetest.gnogno
  • z_delete_thread_01_filetest.gnogno
  • z_delete_thread_02_filetest.gnogno
  • z_delete_thread_03_filetest.gnogno
  • z_delete_thread_04_filetest.gnogno
  • z_delete_thread_05_filetest.gnogno
  • z_delete_thread_06_filetest.gnogno
  • z_edit_reply_00_filetest.gnogno
  • z_edit_reply_01_filetest.gnogno
  • z_edit_reply_02_filetest.gnogno
  • z_edit_reply_03_filetest.gnogno
  • z_edit_reply_04_filetest.gnogno
  • z_edit_reply_05_filetest.gnogno
  • z_edit_reply_06_filetest.gnogno
  • z_edit_reply_07_filetest.gnogno
  • z_edit_reply_08_filetest.gnogno
  • z_edit_thread_00_filetest.gnogno
  • z_edit_thread_01_filetest.gnogno
  • z_edit_thread_02_filetest.gnogno
  • z_edit_thread_03_filetest.gnogno
  • z_edit_thread_04_filetest.gnogno
  • z_edit_thread_05_filetest.gnogno
  • z_edit_thread_06_filetest.gnogno
  • z_edit_thread_07_filetest.gnogno
  • z_flag_reply_00_filetest.gnogno
  • z_flag_reply_01_filetest.gnogno
  • z_flag_reply_02_filetest.gnogno
  • z_flag_reply_03_filetest.gnogno
  • z_flag_reply_04_filetest.gnogno
  • z_flag_reply_05_filetest.gnogno
  • z_flag_reply_06_filetest.gnogno
  • z_flag_reply_07_filetest.gnogno
  • z_flag_reply_08_filetest.gnogno
  • z_flag_reply_09_filetest.gnogno
  • z_flag_thread_00_filetest.gnogno
  • z_flag_thread_01_filetest.gnogno
  • z_flag_thread_02_filetest.gnogno
  • z_flag_thread_03_filetest.gnogno
  • z_flag_thread_04_filetest.gnogno
  • z_flag_thread_05_filetest.gnogno
  • z_flag_thread_06_filetest.gnogno
  • z_flag_thread_07_filetest.gnogno
  • z_flag_thread_08_filetest.gnogno
  • z_freeze_board_00_filetest.gnogno
  • z_freeze_board_01_filetest.gnogno
  • z_freeze_thread_00_filetest.gnogno
  • z_freeze_thread_01_filetest.gnogno
  • z_freeze_thread_02_filetest.gnogno
  • z_get_board_id_from_name_00_filetest.gnogno
  • z_get_board_id_from_name_01_filetest.gnogno
  • z_hub_0_a_filetest.gnogno
  • z_hub_0_b_filetest.gnogno
  • z_hub_0_c_filetest.gnogno
  • z_hub_1_a_filetest.gnogno
  • z_hub_1_b_filetest.gnogno
  • z_hub_1_c_filetest.gnogno
  • z_hub_2_a_filetest.gnogno
  • z_hub_2_b_filetest.gnogno
  • z_hub_3_a_filetest.gnogno
  • z_hub_3_b_filetest.gnogno
  • z_hub_4_a_filetest.gnogno
  • z_hub_4_b_filetest.gnogno
  • z_hub_5_a_filetest.gnogno
  • z_hub_5_b_filetest.gnogno
  • z_hub_6_a_filetest.gnogno
  • z_hub_6_b_filetest.gnogno
  • z_hub_6_c_filetest.gnogno
  • z_hub_6_d_filetest.gnogno
  • z_hub_6_e_filetest.gnogno
  • z_hub_7_a_filetest.gnogno
  • z_hub_7_b_filetest.gnogno
  • z_hub_8_a_filetest.gnogno
  • z_hub_8_b_filetest.gnogno
  • z_hub_8_c_filetest.gnogno
  • z_hub_9_a_filetest.gnogno
  • z_hub_9_b_filetest.gnogno
  • z_hub_9_c_filetest.gnogno
  • z_invite_member_00_filetest.gnogno
  • z_invite_member_01_filetest.gnogno
  • z_invite_member_02_filetest.gnogno
  • z_invite_member_03_filetest.gnogno
  • z_invite_member_04_filetest.gnogno
  • z_invite_member_05_filetest.gnogno
  • z_invite_member_06_filetest.gnogno
  • z_is_banned_00_filetest.gnogno
  • z_is_banned_01_filetest.gnogno
  • z_is_member_00_filetest.gnogno
  • z_is_member_01_filetest.gnogno
  • z_lock_realm_00_filetest.gnogno
  • z_lock_realm_01_filetest.gnogno
  • z_lock_realm_02_filetest.gnogno
  • z_lock_realm_03_filetest.gnogno
  • z_lock_realm_04_filetest.gnogno
  • z_lock_realm_05_filetest.gnogno
  • z_remove_member_00_filetest.gnogno
  • z_remove_member_01_filetest.gnogno
  • z_remove_member_02_filetest.gnogno
  • z_remove_member_03_filetest.gnogno
  • z_rename_board_00_filetest.gnogno
  • z_rename_board_01_filetest.gnogno
  • z_rename_board_02_filetest.gnogno
  • z_rename_board_03_filetest.gnogno
  • z_rename_board_04_filetest.gnogno
  • z_rename_board_05_filetest.gnogno
  • z_rename_board_06_filetest.gnogno
  • z_rename_board_07_filetest.gnogno
  • z_rename_board_08_filetest.gnogno
  • z_rename_board_09_filetest.gnogno
  • z_request_invite_00_filetest.gnogno
  • z_request_invite_01_filetest.gnogno
  • z_request_invite_02_filetest.gnogno
  • z_request_invite_03_filetest.gnogno
  • z_request_invite_04_filetest.gnogno
  • z_revoke_invite_00_filetest.gnogno
  • z_revoke_invite_01_filetest.gnogno
  • z_revoke_invite_02_filetest.gnogno
  • z_set_flagging_threshold_00_filetest.gnogno
  • z_set_flagging_threshold_01_filetest.gnogno
  • z_set_flagging_threshold_02_filetest.gnogno
  • z_set_permissions_00_filetest.gnogno
  • z_set_permissions_01_filetest.gnogno
  • z_set_permissions_02_filetest.gnogno
  • z_set_realm_notice_00_filetest.gnogno
  • z_set_realm_notice_01_filetest.gnogno
  • z_set_realm_notice_02_filetest.gnogno
  • z_set_realm_notice_03_filetest.gnogno
  • z_set_required_account_amount_00_filetest.gnogno
  • z_set_required_account_amount_01_filetest.gnogno
  • z_set_required_account_amount_02_filetest.gnogno
  • z_ui_admin_users_00_filetest.gnogno
  • z_ui_board_00_filetest.gnogno
  • z_ui_board_01_filetest.gnogno
  • z_ui_board_02_filetest.gnogno
  • z_ui_board_03_filetest.gnogno
  • z_ui_board_04_filetest.gnogno
  • z_ui_board_05_filetest.gnogno
  • z_ui_board_members_00_filetest.gnogno
  • z_ui_home_00_filetest.gnogno
  • z_ui_home_01_filetest.gnogno
  • z_ui_home_02_filetest.gnogno
  • z_ui_reply_00_filetest.gnogno
  • z_ui_reply_01_filetest.gnogno
  • z_ui_reply_02_filetest.gnogno
  • z_ui_reply_03_filetest.gnogno
  • z_ui_reply_04_filetest.gnogno
  • z_ui_thread_00_filetest.gnogno
  • z_ui_thread_01_filetest.gnogno
  • z_ui_thread_02_filetest.gnogno
  • z_ui_thread_03_filetest.gnogno
  • z_ui_thread_04_filetest.gnogno
  • z_ui_thread_05_filetest.gnogno
  • z_ui_thread_06_filetest.gnogno
  • z_ui_thread_07_filetest.gnogno
  • z_ui_thread_08_filetest.gnogno
  • z_ui_thread_09_filetest.gnogno
  • z_ui_thread_10_filetest.gnogno
  • z_ui_thread_11_filetest.gnogno
  • z_ui_thread_12_filetest.gnogno
  • z_ui_thread_13_filetest.gnogno
  • z_ui_thread_14_filetest.gnogno
  • z_unban_00_filetest.gnogno
  • z_unban_01_filetest.gnogno
  • z_unban_02_filetest.gnogno
  • render_post.gnogno
    1package boards223import (4	"strconv"5	"strings"67	"gno.land/p/gnoland/boards/v0"8

    Functions

    • AcceptInvite(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, user string)

    • AreRealmMembersLocked() bool

    • Ban(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, user string, hours uint, reason string)

    • BoardCount() int

    • ChangeMemberRole(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, member string, role string)

    • CreateBoard(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, name string, listed bool, open bool) uint64

    • CreateReply(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, threadID uint64, replyID uint64, body string) uint64

    • CreateRepost(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, threadID uint64, destinationBoardID uint64, title string, body string) uint64

    • CreateThread(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, title string, body string) uint64

    • DeleteReply(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, threadID uint64, replyID uint64)

    • DeleteThread(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, threadID uint64)

    • EditReply(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, threadID uint64, replyID uint64, body string)

    • EditThread(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, threadID uint64, title string, body string)

    • FlagReply(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, threadID uint64, replyID uint64, reason string)

    • FlagThread(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, threadID uint64, reason string)

    • FreezeBoard(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64)

    • FreezeThread(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, threadID uint64)

    • GetBoard(id uint64) (struct{id uint64; name string; aliases []string; readonly bool; threadCount int; memberCount int; creator .uverse.address; createdAt int64; updatedAt int64}, bool)

    • GetBoardIDFromName(interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, name string) (uint64, found bool)

    • GetBoards(start int, count int) []gno.land/p/gnoland/boards/exts/hub/v0.Board

    • GetComment(boardID uint64, threadID uint64, commentID uint64) (struct{id uint64; boardID uint64; threadID uint64; parentID uint64; body string; hidden bool; replyCount int; flagCount int; creator .uverse.address; createdAt int64; updatedAt int64}, bool)

    • GetComments(boardID uint64, threadID uint64, start int, count int) []gno.land/p/gnoland/boards/exts/hub/v0.Comment

    • GetFlaggingThreshold(boardID uint64) int

    • GetFlags(boardID uint64, threadID uint64, commentID uint64, start int, count int) []gno.land/p/gnoland/boards/exts/hub/v0.Flag

    • GetMembers(boardID uint64, start int, count int) []gno.land/p/gnoland/boards/exts/hub/v0.Member

    • GetReplies(boardID uint64, threadID uint64, commentID uint64, start int, count int) []gno.land/p/gnoland/boards/exts/hub/v0.Comment

    • GetReposts(boardID uint64, threadID uint64, start int, count int) []gno.land/p/gnoland/boards/exts/hub/v0.Thread

    • GetThread(boardID uint64, threadID uint64) (struct{id uint64; originalBoardID uint64; originalThreadID uint64; boardID uint64; title string; body string; hidden bool; readonly bool; commentCount int; repostCount int; flagCount int; creator .uverse.address; createdAt int64; updatedAt int64}, bool)

    • GetThreads(boardID uint64, start int, count int) []gno.land/p/gnoland/boards/exts/hub/v0.Thread

    • HasMemberRole(boardID uint64, member string, role string) bool

    • InviteMember(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, user string, role string)

    • InviteMembers(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, invites ...gno.land/r/gnoland/boards2/v0.Invite)

    • IsBanned(boardID uint64, user string) bool

    • IsBoardFrozen(boardID uint64) bool

    • IsMember(boardID uint64, user string) bool

    • IsRealmLocked() bool

    • IsThreadFrozen(boardID uint64, threadID uint64) bool

    • LockRealm(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, lockRealmMembers bool)

    • RemoveMember(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, member string)

    • RenameBoard(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, name string, newName string)

    • Render(path string) string

    • RequestInvite(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64)

    • RevokeInvite(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, user string)

    • SetFlaggingThreshold(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, threshold int)

    • SetHelp(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, content string)

    • SetPermissions(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, p interface {HasPermission func(.uverse.address, gno.land/p/gnoland/boards/v0.Permission) bool; HasRole func(.uverse.address, gno.land/p/gnoland/boards/v0.Role) bool; HasUser func(.uverse.address) bool; IterateUsers func(int, int, gno.land/p/gnoland/boards/v0.UsersIterFn) bool; RemoveUser func(.uverse.address) bool; SetUserRoles func(.uverse.address, ...gno.land/p/gnoland/boards/v0.Role); UsersCount func() int; WithPermission func(.uverse.address, gno.land/p/gnoland/boards/v0.Permission, gno.land/p/gnoland/boards/v0.Args, func())})

    • SetRealmNotice(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, message string)

    • SetRequiredAccountAmount(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, amount int64)

    • Unban(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, user string, reason string)

    • UnfreezeBoard(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64)

    • UnfreezeThread(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, boardID uint64, threadID uint64)

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    Rendered

    RenderedRawgnoweb ↗

    vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.

    "gno.land/p/jeronimoalbi/mdform/v0"
    9 "gno.land/p/leon/svgbtn/v0"
    10 "gno.land/p/moul/md/v0"
    11 "gno.land/p/moul/mdtable/v0"
    12 "gno.land/p/nt/markdown/foreign/v0"
    13 "gno.land/p/nt/mdalert/v0"
    14 "gno.land/p/nt/mux/v0"
    15 "gno.land/p/nt/ufmt/v0"
    16)
    17
    18// renderPost renders a post and (unless it's a leaf or capped) its replies.
    19// desc is the page's sort order, forwarded so a comment's nested inline
    20// children (renderSubReplies) match the order of the view they appear in. It
    21// is unused for the top-level/re-root call (path != "" routes to
    22// renderTopLevelReplies, which derives the order from the path); those
    23// callers pass false.
    24func renderPost(post *boards.Post, path, indent string, levels int, budget *int, desc bool) string {
    25 var b strings.Builder
    26
    27 // Thread reposts might not have a title, if so get title from source thread
    28 title := post.Title
    29 if boards.IsRepost(post) && title == "" {
    30 if board, ok := gBoards.Get(post.OriginalBoardID); ok {
    31 if src, ok := getThread(board, post.ParentID); ok {
    32 title = src.Title
    33 }
    34 }
    35 }
    36
    37 if title != "" { // Replies don't have a title
    38 b.WriteString(md.H2(md.EscapeText(title)))
    39 }
    40
    41 b.WriteString(indent + "\n")
    42 b.WriteString(renderPostContent(post, indent, levels, budget))
    43
    44 if post.Replies.Size() == 0 {
    45 return b.String()
    46 }
    47
    48 // In practice this only fires for the re-rooted view's context-parent,
    49 // which renderPostInner renders with an explicit levels==0. The thread
    50 // recursion does levels-1 in BOTH renderPost and renderTopLevelReplies/
    51 // renderSubReplies, so levels drops by 2 per nesting level and skips 0 —
    52 // i.e. levels does NOT bound depth in the thread view; the render budget
    53 // and the per-node breadth cap (renderSubReplies) are the real bounds.
    54 if levels == 0 {
    55 b.WriteString(indent + "\n")
    56 return b.String()
    57 }
    58
    59 if path != "" {
    60 b.WriteString(renderTopLevelReplies(post, path, indent, levels-1, budget))
    61 } else {
    62 b.WriteString(renderSubReplies(post, indent, levels-1, budget, desc))
    63 }
    64 return b.String()
    65}
    66
    67func renderPostContent(post *boards.Post, indent string, levels int, budget *int) string {
    68 var b strings.Builder
    69
    70 // Author and date header
    71 creatorLink := userLink(post.Creator)
    72 roleBadge := getRoleBadge(post)
    73 date := post.CreatedAt.Format(dateFormat)
    74 b.WriteString(indent)
    75 b.WriteString(md.Bold(creatorLink) + roleBadge + " · " + date)
    76 if !boards.IsThread(post) {
    77 b.WriteString(" " + md.Link("#"+post.ID.String(), makeReplyURI(post)))
    78 }
    79 b.WriteString(" \n")
    80
    81 // Flagged comment should be hidden, but replies still visible (see: #3480)
    82 // Flagged threads will be hidden by render function caller.
    83 if post.Hidden {
    84 link := md.Link("inappropriate", makeFlaggingReasonsURI(post))
    85 b.WriteString(indentBody(indent, "⚠ Reply is hidden as it has been flagged as "+link))
    86 b.WriteString("\n")
    87 return b.String()
    88 }
    89
    90 srcContent, srcPost := renderSourcePost(post, indent, budget)
    91 if boards.IsRepost(post) && srcPost != nil {
    92 msg := ufmt.Sprintf(
    93 "Original thread is %s \nCreated by %s on %s",
    94 md.Link(srcPost.Title, makeThreadURI(srcPost)),
    95 userLink(srcPost.Creator),
    96 srcPost.CreatedAt.Format(dateFormat),
    97 )
    98
    99 b.WriteString(mdalert.New(mdalert.TypeInfo, "Thread Repost", msg, true).String())
    100 b.WriteString("\n")
    101 }
    102
    103 // Render repost body before original thread's body
    104 if post.Body != "" {
    105 b.WriteString(indentForeignBody(indent, post.Body, budget) + "\n")
    106 if srcContent != "" {
    107 // Add extra line to separate repost content from original thread content
    108 b.WriteString("\n")
    109 }
    110 }
    111
    112 b.WriteString(srcContent)
    113
    114 // Add a newline to separate source deleted message from repost body content
    115 if boards.IsRepost(post) && srcPost == nil && len(post.Body) > 0 {
    116 b.WriteString("\n\n")
    117 }
    118
    119 // Split thread content and actions
    120 if boards.IsThread(post) && !boards.IsRepost(post) {
    121 b.WriteString("\n")
    122 }
    123
    124 // Action buttons
    125 b.WriteString(indent)
    126 if !boards.IsThread(post) { // is comment
    127 b.WriteString(" \n")
    128 b.WriteString(indent)
    129 }
    130
    131 actions := []string{
    132 md.Link("Flag", makeFlagURI(post)),
    133 }
    134
    135 if boards.IsThread(post) {
    136 repostAction := md.Link("Repost", makeCreateRepostURI(post))
    137 if post.Reposts.Size() > 0 {
    138 repostAction += " [" + strconv.Itoa(post.Reposts.Size()) + "]"
    139 }
    140 actions = append(actions, repostAction)
    141 }
    142
    143 isReadonly := post.Readonly || post.Board.Readonly
    144 // A reply doesn't carry the thread's frozen flag (FreezeThread sets
    145 // Readonly on the thread post only), so check the enclosing thread too —
    146 // otherwise a frozen thread's replies show Reply/Edit/Delete links that
    147 // the backend rejects. Mirrors the IsReadonly helper (board || thread).
    148 if !isReadonly && !boards.IsThread(post) {
    149 if t, ok := getThread(post.Board, post.ThreadID); ok {
    150 isReadonly = t.Readonly
    151 }
    152 }
    153 if !isReadonly {
    154 replyLabel := "Reply"
    155 if boards.IsThread(post) {
    156 replyLabel = "Comment"
    157 }
    158 replyAction := md.Link(replyLabel, makeCreateReplyURI(post))
    159 // Add reply count if any
    160 if post.Replies.Size() > 0 {
    161 replyAction += " [" + strconv.Itoa(post.Replies.Size()) + "]"
    162 }
    163
    164 actions = append(
    165 actions,
    166 replyAction,
    167 md.Link("Edit", makeEditPostURI(post)),
    168 md.Link("Delete", makeDeletePostURI(post)),
    169 )
    170 }
    171
    172 if levels == 0 {
    173 switch {
    174 case boards.IsThread(post):
    175 actions = append(actions, md.Link("Show all Replies", makeThreadURI(post)))
    176 case post.Replies.Size() > 0:
    177 // Reached at levels==0 — in practice the re-rooted view's
    178 // context-parent (see renderPost). It still has replies below, so
    179 // re-root here (Reddit/HN "continue this thread") to keep the
    180 // subtree drillable instead of bouncing to the thread root.
    181 actions = append(actions, md.Link("Continue this thread →", makeReplyURI(post)))
    182 }
    183 }
    184
    185 b.WriteString("↳ " + strings.Join(actions, " • ") + "\n")
    186 return b.String()
    187}
    188
    189func renderPostInner(post *boards.Post, path string) string {
    190 if boards.IsThread(post) {
    191 return ""
    192 }
    193
    194 var (
    195 s string
    196 threadID = post.ThreadID
    197 thread, _ = getThread(post.Board, threadID)
    198 budget = maxRenderedBodies()
    199 )
    200
    201 // Fully render parent if it's not a repost.
    202 if !boards.IsRepost(post) {
    203 parentID := post.ParentID
    204 parent := thread
    205
    206 if thread.ID != parentID {
    207 parent, _ = getReply(thread, parentID)
    208 }
    209
    210 s += renderPost(parent, "", "", 0, &budget, false) + "\n"
    211 }
    212
    213 // Pass the reply's own path so renderPost routes to renderTopLevelReplies
    214 // and paginates this comment's direct replies (the re-root has its own
    215 // ?page= — no collision with the thread view, which is a different path).
    216 // desc=false: order is derived from path by renderTopLevelReplies.
    217 s += renderPost(post, path, "> ", 5, &budget, false)
    218 return s
    219}
    220
    221func renderSourcePost(post *boards.Post, indent string, budget *int) (string, *boards.Post) {
    222 if !boards.IsRepost(post) {
    223 return "", nil
    224 }
    225
    226 indent += "> "
    227
    228 // TODO: figure out a way to decouple posts from a global storage.
    229 board, ok := gBoards.Get(post.OriginalBoardID)
    230 if !ok {
    231 // TODO: Boards can't be deleted so this might be redundant
    232 return indentBody(indent, "⚠ Source board has been deleted"), nil
    233 }
    234
    235 srcPost, ok := getThread(board, post.ParentID)
    236 if !ok {
    237 return indentBody(indent, "⚠ Source post has been deleted"), nil
    238 }
    239
    240 if srcPost.Hidden {
    241 return indentBody(indent, "⚠ Source post has been flagged as inappropriate"), nil
    242 }
    243
    244 return indentForeignBody(indent, srcPost.Body, budget) + "\n\n", srcPost
    245}
    246
    247func renderFlagPost(res *mux.ResponseWriter, req *mux.Request) {
    248 name := req.GetVar("board")
    249 board, found := gBoards.GetByName(name)
    250 if !found {
    251 res.Write("Board not found")
    252 return
    253 }
    254
    255 // Thread ID must always be available
    256 rawID := req.GetVar("thread")
    257 threadID, err := strconv.Atoi(rawID)
    258 if err != nil {
    259 res.Write("Invalid thread ID: " + md.EscapeText(rawID))
    260 return
    261 }
    262
    263 thread, found := getThread(board, boards.ID(threadID))
    264 if !found {
    265 res.Write("Thread not found")
    266 return
    267 }
    268
    269 // Parse reply ID when post is a reply
    270 var reply *boards.Post
    271 rawID = req.GetVar("reply")
    272 isReply := rawID != ""
    273 if isReply {
    274 replyID, err := strconv.Atoi(rawID)
    275 if err != nil {
    276 res.Write("Invalid reply ID: " + md.EscapeText(rawID))
    277 return
    278 }
    279
    280 reply, _ = getReply(thread, boards.ID(replyID))
    281 if reply == nil {
    282 res.Write("Reply not found")
    283 return
    284 }
    285 }
    286
    287 exec := "FlagThread"
    288 if isReply {
    289 exec = "FlagReply"
    290 }
    291
    292 form := mdform.New("exec", exec)
    293 form.Input(
    294 "boardID",
    295 "placeholder", "Board ID",
    296 "value", board.ID.String(),
    297 "readonly", "true",
    298 )
    299 form.Input(
    300 "threadID",
    301 "placeholder", "Thread ID",
    302 "value", thread.ID.String(),
    303 "readonly", "true",
    304 )
    305
    306 if isReply {
    307 form.Input(
    308 "replyID",
    309 "placeholder", "Reply ID",
    310 "value", reply.ID.String(),
    311 "readonly", "true",
    312 )
    313 }
    314
    315 form.Input(
    316 "reason",
    317 "placeholder", "Flagging Reason",
    318 )
    319
    320 // Breadcrumb navigation
    321 backLink := md.Link("← Back to thread", makeThreadURI(thread))
    322
    323 if isReply {
    324 res.Write(md.H1(board.Name + ": Flag Comment"))
    325 } else {
    326 res.Write(md.H1(board.Name + ": Flag Thread"))
    327 }
    328 res.Write(backLink + "\n\n")
    329
    330 res.Write(
    331 md.Paragraph(
    332 "Thread or comment moderation is done through flagging, which is usually done "+
    333 "by board members with the moderator role, though other roles could also potentially flag.",
    334 ) +
    335 md.Paragraph(
    336 "Flagging relies on a configurable threshold, which by default is of one flag, that when "+
    337 "reached leads to the flagged thread or comment to be hidden.",
    338 ) +
    339 md.Paragraph(
    340 "Flagging thresholds can be different within each board.",
    341 ),
    342 )
    343
    344 if isReply {
    345 res.Write(
    346 md.Paragraph(
    347 ufmt.Sprintf(
    348 "⚠ You are flagging a %s from %s ⚠",
    349 md.Link("comment", makeReplyURI(reply)),
    350 userLink(reply.Creator),
    351 ),
    352 ),
    353 )
    354 } else {
    355 res.Write(
    356 md.Paragraph(
    357 ufmt.Sprintf(
    358 "⚠ You are flagging the thread: %s ⚠",
    359 md.Link(thread.Title, makeThreadURI(thread)),
    360 ),
    361 ),
    362 )
    363 }
    364
    365 res.Write(form.String())
    366 res.Write("\n\n**Done?** " + svgbtn.ButtonWithRadius(136, 32, 4, "#E2E2E2", "#54595D", "Return to thread", makeThreadURI(thread)) + "\n")
    367}
    368
    369func renderFlaggingReasonsPost(res *mux.ResponseWriter, req *mux.Request) {
    370 name := req.GetVar("board")
    371 board, found := gBoards.GetByName(name)
    372 if !found {
    373 res.Write("Board not found")
    374 return
    375 }
    376
    377 // Thread ID must always be available
    378 rawID := req.GetVar("thread")
    379 threadID, err := strconv.Atoi(rawID)
    380 if err != nil {
    381 res.Write("Invalid thread ID: " + md.EscapeText(rawID))
    382 return
    383 }
    384
    385 thread, found := getThread(board, boards.ID(threadID))
    386 if !found {
    387 res.Write("Thread not found")
    388 return
    389 }
    390
    391 flags := thread.Flags
    392
    393 // Parse reply ID when post is a reply
    394 var reply *boards.Post
    395 rawID = req.GetVar("reply")
    396 isReply := rawID != ""
    397 if isReply {
    398 replyID, err := strconv.Atoi(rawID)
    399 if err != nil {
    400 res.Write("Invalid reply ID: " + md.EscapeText(rawID))
    401 return
    402 }
    403
    404 reply, found = getReply(thread, boards.ID(replyID))
    405 if !found {
    406 res.Write("Reply not found")
    407 return
    408 }
    409
    410 flags = reply.Flags
    411 }
    412
    413 table := mdtable.Table{
    414 Headers: []string{"Moderator", "Reason"},
    415 }
    416
    417 flags.Iterate(0, flags.Size(), func(f boards.Flag) bool {
    418 // f.Reason is user-supplied (only trimmed at write); escape it so a
    419 // flag reason can't inject markdown (links/images) or HTML into the
    420 // reasons table. md.EscapeText leaves '|' for mdtable to escape.
    421 table.Append([]string{userLink(f.User), md.EscapeText(f.Reason)})
    422 return false
    423 })
    424
    425 // Breadcrumb navigation
    426 backLink := md.Link("← Back to thread", makeThreadURI(thread))
    427
    428 res.Write(md.H1("Flagging Reasons"))
    429 res.Write(backLink + "\n\n")
    430 if isReply {
    431 res.Write(
    432 md.Paragraph(
    433 ufmt.Sprintf(
    434 "Moderation flags for a %s submitted by %s",
    435 md.Link("comment", makeReplyURI(reply)),
    436 userLink(reply.Creator),
    437 ),
    438 ),
    439 )
    440 } else {
    441 res.Write(
    442 md.Paragraph(
    443 // Intentionally hide flagged thread title
    444 ufmt.Sprintf("Moderation flags for %s", md.Link("thread", makeThreadURI(thread))),
    445 ),
    446 )
    447 }
    448 res.Write(table.String())
    449}
    450
    451func renderReplyPost(res *mux.ResponseWriter, req *mux.Request) {
    452 name := req.GetVar("board")
    453 board, found := gBoards.GetByName(name)
    454 if !found {
    455 res.Write("Board not found")
    456 return
    457 }
    458
    459 // Thread ID must always be available
    460 rawID := req.GetVar("thread")
    461 threadID, err := strconv.Atoi(rawID)
    462 if err != nil {
    463 res.Write("Invalid thread ID: " + md.EscapeText(rawID))
    464 return
    465 }
    466
    467 thread, found := board.Threads.Get(boards.ID(threadID))
    468 if !found {
    469 res.Write("Thread not found")
    470 return
    471 }
    472
    473 // Parse reply ID when post is a reply
    474 var reply *boards.Post
    475 rawID = req.GetVar("reply")
    476 isReply := rawID != ""
    477 if isReply {
    478 replyID, err := strconv.Atoi(rawID)
    479 if err != nil {
    480 res.Write("Invalid reply ID: " + md.EscapeText(rawID))
    481 return
    482 }
    483
    484 reply, _ = getReply(thread, boards.ID(replyID))
    485 if reply == nil {
    486 res.Write("Reply not found")
    487 return
    488 }
    489 }
    490
    491 form := mdform.New("exec", "CreateReply")
    492 form.Input(
    493 "boardID",
    494 "placeholder", "Board ID",
    495 "value", board.ID.String(),
    496 "readonly", "true",
    497 )
    498 form.Input(
    499 "threadID",
    500 "placeholder", "Thread ID",
    501 "value", thread.ID.String(),
    502 "readonly", "true",
    503 )
    504
    505 if isReply {
    506 form.Input(
    507 "replyID",
    508 "placeholder", "Reply ID",
    509 "value", reply.ID.String(),
    510 "readonly", "true",
    511 )
    512 } else {
    513 form.Input(
    514 "replyID",
    515 "placeholder", "Reply ID",
    516 "value", "0",
    517 "readonly", "true",
    518 )
    519 }
    520
    521 form.Textarea(
    522 "body",
    523 "placeholder", "Comment",
    524 "required", "true",
    525 )
    526
    527 // Breadcrumb navigation
    528 backLink := md.Link("← Back to thread", makeThreadURI(thread))
    529
    530 if isReply {
    531 res.Write(md.H1(board.Name + ": Reply"))
    532 res.Write(backLink + "\n\n")
    533 res.Write(
    534 md.Paragraph(ufmt.Sprintf("Replying to a comment posted by %s:", userLink(reply.Creator))) +
    535 foreign.ForeignWithLabel("Quoted comment", reply.Body),
    536 )
    537 } else {
    538 res.Write(md.H1(board.Name + ": Comment"))
    539 res.Write(backLink + "\n\n")
    540 res.Write(
    541 md.Paragraph(
    542 ufmt.Sprintf("Commenting on the thread: %s", md.Link(thread.Title, makeThreadURI(thread))),
    543 ),
    544 )
    545 }
    546
    547 res.Write(form.String())
    548 res.Write("\n\n**Done?** " + svgbtn.ButtonWithRadius(136, 32, 4, "#E2E2E2", "#54595D", "Return to thread", makeThreadURI(thread)) + "\n")
    549}
    550