Revamped the configuration system. If you have trouble installing this, try installing my fork of gopsutil with `go get` and delete the users_penalties table from the schema folder. That stuff will be cleaned up in the next commit. Fixed an issue with the links for the Uncategorised forum being broken. Swapped out NOW() for UTC_TIMESTAMP() in MySQL queries. We now get an error message when the server goes down for whatever reason. The template compiler now supports pointers. Swapped out shirou/gopsutil for a fork locked on an older and more stable commit of the same library. Fixed a bug where the preprocessor didn't play nice with empty CSS files. Added the site name to the navbar. Added more things to .gitignore Laid the foundations for the next commit.
669 lines
21 KiB
Go
669 lines
21 KiB
Go
package main
|
|
|
|
import (
|
|
//"fmt"
|
|
"bytes"
|
|
"strings"
|
|
"strconv"
|
|
"errors"
|
|
"context"
|
|
"net/http"
|
|
"html"
|
|
"html/template"
|
|
"database/sql"
|
|
|
|
"./query_gen/lib"
|
|
)
|
|
|
|
var socialgroups_list_stmt *sql.Stmt
|
|
var socialgroups_member_list_stmt *sql.Stmt
|
|
var socialgroups_member_list_join_stmt *sql.Stmt
|
|
var socialgroups_get_member_stmt *sql.Stmt
|
|
var socialgroups_get_group_stmt *sql.Stmt
|
|
var socialgroups_create_group_stmt *sql.Stmt
|
|
var socialgroups_attach_forum_stmt *sql.Stmt
|
|
var socialgroups_unattach_forum_stmt *sql.Stmt
|
|
var socialgroups_add_member_stmt *sql.Stmt
|
|
|
|
// TO-DO: Add a better way of splitting up giant plugins like this
|
|
type SocialGroup struct
|
|
{
|
|
ID int
|
|
Link string
|
|
Name string
|
|
Desc string
|
|
Active bool
|
|
Privacy int /* 0: Public, 1: Protected, 2: Private */
|
|
|
|
// Who should be able to accept applications and create invites? Mods+ or just admins? Mods is a good start, we can ponder over whether we should make this more flexible in the future.
|
|
Joinable int /* 0: Private, 1: Anyone can join, 2: Applications, 3: Invite-only */
|
|
|
|
MemberCount int
|
|
Owner int
|
|
Backdrop string
|
|
CreatedAt string
|
|
LastUpdateTime string
|
|
|
|
MainForumID int
|
|
MainForum *Forum
|
|
Forums []*Forum
|
|
ExtData ExtData
|
|
}
|
|
|
|
type SocialGroupPage struct
|
|
{
|
|
Title string
|
|
CurrentUser User
|
|
Header HeaderVars
|
|
ItemList []TopicUser
|
|
Forum Forum
|
|
SocialGroup SocialGroup
|
|
Page int
|
|
LastPage int
|
|
ExtData ExtData
|
|
}
|
|
|
|
type SocialGroupListPage struct
|
|
{
|
|
Title string
|
|
CurrentUser User
|
|
Header HeaderVars
|
|
GroupList []SocialGroup
|
|
ExtData ExtData
|
|
}
|
|
|
|
type SocialGroupMemberListPage struct
|
|
{
|
|
Title string
|
|
CurrentUser User
|
|
Header HeaderVars
|
|
ItemList []SocialGroupMember
|
|
SocialGroup SocialGroup
|
|
Page int
|
|
LastPage int
|
|
ExtData ExtData
|
|
}
|
|
|
|
type SocialGroupMember struct
|
|
{
|
|
Link string
|
|
Rank int /* 0: Member. 1: Mod. 2: Admin. */
|
|
RankString string /* Member, Mod, Admin, Owner */
|
|
PostCount int
|
|
JoinedAt string
|
|
Offline bool // TO-DO: Need to track the online states of members when WebSockets are enabled
|
|
|
|
User User
|
|
}
|
|
|
|
func init() {
|
|
plugins["socialgroups"] = NewPlugin("socialgroups","Social Groups","Azareal","http://github.com/Azareal","","","",init_socialgroups,nil,deactivate_socialgroups,install_socialgroups,nil)
|
|
}
|
|
|
|
func init_socialgroups() (err error) {
|
|
plugins["socialgroups"].AddHook("intercept_build_widgets", socialgroups_widgets)
|
|
plugins["socialgroups"].AddHook("trow_assign", socialgroups_trow_assign)
|
|
plugins["socialgroups"].AddHook("topic_create_pre_loop", socialgroups_topic_create_pre_loop)
|
|
plugins["socialgroups"].AddHook("pre_render_view_forum", socialgroups_pre_render_view_forum)
|
|
plugins["socialgroups"].AddHook("simple_forum_check_pre_perms", socialgroups_forum_check)
|
|
plugins["socialgroups"].AddHook("forum_check_pre_perms", socialgroups_forum_check)
|
|
// TO-DO: Auto-grant this perm to admins upon installation?
|
|
register_plugin_perm("CreateSocialGroup")
|
|
router.HandleFunc("/groups/", socialgroups_group_list)
|
|
router.HandleFunc("/group/", socialgroups_view_group)
|
|
router.HandleFunc("/group/create/", socialgroups_create_group)
|
|
router.HandleFunc("/group/create/submit/", socialgroups_create_group_submit)
|
|
router.HandleFunc("/group/members/", socialgroups_member_list)
|
|
|
|
socialgroups_list_stmt, err = qgen.Builder.SimpleSelect("socialgroups","sgid, name, desc, active, privacy, joinable, owner, memberCount, createdAt, lastUpdateTime","","","")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
socialgroups_get_group_stmt, err = qgen.Builder.SimpleSelect("socialgroups","name, desc, active, privacy, joinable, owner, memberCount, mainForum, backdrop, createdAt, lastUpdateTime","sgid = ?","","")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
socialgroups_member_list_stmt, err = qgen.Builder.SimpleSelect("socialgroups_members","sgid, uid, rank, posts, joinedAt","","","")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
socialgroups_member_list_join_stmt, err = qgen.Builder.SimpleLeftJoin("socialgroups_members","users","users.uid, socialgroups_members.rank, socialgroups_members.posts, socialgroups_members.joinedAt, users.name, users.avatar","socialgroups_members.uid = users.uid","socialgroups_members.sgid = ?","socialgroups_members.rank DESC, socialgroups_members.joinedat ASC","")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
socialgroups_get_member_stmt, err = qgen.Builder.SimpleSelect("socialgroups_members","rank, posts, joinedAt","sgid = ? AND uid = ?","","")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
socialgroups_create_group_stmt, err = qgen.Builder.SimpleInsert("socialgroups","name, desc, active, privacy, joinable, owner, memberCount, mainForum, backdrop, createdAt, lastUpdateTime","?,?,?,?,1,?,1,?,'',UTC_TIMESTAMP(),UTC_TIMESTAMP()")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
socialgroups_attach_forum_stmt, err = qgen.Builder.SimpleUpdate("forums","parentID = ?, parentType = 'socialgroup'","fid = ?")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
socialgroups_unattach_forum_stmt, err = qgen.Builder.SimpleUpdate("forums","parentID = 0, parentType = ''","fid = ?")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
socialgroups_add_member_stmt, err = qgen.Builder.SimpleInsert("socialgroups_members","sgid, uid, rank, posts, joinedAt","?,?,?,0,UTC_TIMESTAMP()")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func deactivate_socialgroups() {
|
|
plugins["socialgroups"].RemoveHook("intercept_build_widgets", socialgroups_widgets)
|
|
plugins["socialgroups"].RemoveHook("trow_assign", socialgroups_trow_assign)
|
|
plugins["socialgroups"].RemoveHook("topic_create_pre_loop", socialgroups_topic_create_pre_loop)
|
|
plugins["socialgroups"].RemoveHook("pre_render_view_forum", socialgroups_pre_render_view_forum)
|
|
plugins["socialgroups"].RemoveHook("simple_forum_check_pre_perms", socialgroups_forum_check)
|
|
plugins["socialgroups"].RemoveHook("forum_check_pre_perms", socialgroups_forum_check)
|
|
deregister_plugin_perm("CreateSocialGroup")
|
|
_ = router.RemoveFunc("/groups/")
|
|
_ = router.RemoveFunc("/group/")
|
|
_ = router.RemoveFunc("/group/create/")
|
|
_ = router.RemoveFunc("/group/create/submit/")
|
|
_ = socialgroups_list_stmt.Close()
|
|
_ = socialgroups_member_list_stmt.Close()
|
|
_ = socialgroups_member_list_join_stmt.Close()
|
|
_ = socialgroups_get_member_stmt.Close()
|
|
_ = socialgroups_get_group_stmt.Close()
|
|
_ = socialgroups_create_group_stmt.Close()
|
|
_ = socialgroups_attach_forum_stmt.Close()
|
|
_ = socialgroups_unattach_forum_stmt.Close()
|
|
_ = socialgroups_add_member_stmt.Close()
|
|
}
|
|
|
|
// TO-DO: Stop accessing the query builder directly and add a feature in Gosora which is more easily reversed, if an error comes up during the installation process
|
|
func install_socialgroups() error {
|
|
sg_table_stmt, err := qgen.Builder.CreateTable("socialgroups","utf8mb4","utf8mb4_general_ci",
|
|
[]qgen.DB_Table_Column{
|
|
qgen.DB_Table_Column{"sgid","int",0,false,true,""},
|
|
qgen.DB_Table_Column{"name","varchar",100,false,false,""},
|
|
qgen.DB_Table_Column{"desc","varchar",200,false,false,""},
|
|
qgen.DB_Table_Column{"active","boolean",1,false,false,""},
|
|
qgen.DB_Table_Column{"privacy","smallint",0,false,false,""},
|
|
qgen.DB_Table_Column{"joinable","smallint",0,false,false,"0"},
|
|
qgen.DB_Table_Column{"owner","int",0,false,false,""},
|
|
qgen.DB_Table_Column{"memberCount","int",0,false,false,""},
|
|
qgen.DB_Table_Column{"mainForum","int",0,false,false,"0"}, // The board the user lands on when they click ona group, we'll make it possible for group admins to change what users land on
|
|
//qgen.DB_Table_Column{"boards","varchar",255,false,false,""}, // Cap the max number of boards at 8 to avoid overflowing the confines of a 64-bit integer?
|
|
qgen.DB_Table_Column{"backdrop","varchar",200,false,false,""}, // File extension for the uploaded file, or an external link
|
|
qgen.DB_Table_Column{"createdAt","createdAt",0,false,false,""},
|
|
qgen.DB_Table_Column{"lastUpdateTime","datetime",0,false,false,""},
|
|
},
|
|
[]qgen.DB_Table_Key{
|
|
qgen.DB_Table_Key{"sgid","primary"},
|
|
},
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = sg_table_stmt.Exec()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
sg_members_table_stmt, err := qgen.Builder.CreateTable("socialgroups_members","","",
|
|
[]qgen.DB_Table_Column{
|
|
qgen.DB_Table_Column{"sgid","int",0,false,false,""},
|
|
qgen.DB_Table_Column{"uid","int",0,false,false,""},
|
|
qgen.DB_Table_Column{"rank","int",0,false,false,"0"}, /* 0: Member. 1: Mod. 2: Admin. */
|
|
qgen.DB_Table_Column{"posts","int",0,false,false,"0"}, /* Per-Group post count. Should we do some sort of score system? */
|
|
qgen.DB_Table_Column{"joinedAt","datetime",0,false,false,""},
|
|
},
|
|
[]qgen.DB_Table_Key{},
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = sg_members_table_stmt.Exec()
|
|
return err
|
|
}
|
|
|
|
// TO-DO; Implement an uninstallation system into Gosora. And a better installation system.
|
|
func uninstall_socialgroups() error {
|
|
return nil
|
|
}
|
|
|
|
// TO-DO: Do this properly via the widget system
|
|
func socialgroups_common_area_widgets(headerVars *HeaderVars) {
|
|
// TO-DO: Hot Groups? Featured Groups? Official Groups?
|
|
var b bytes.Buffer
|
|
var menu WidgetMenu = WidgetMenu{"Social Groups",[]WidgetMenuItem{
|
|
WidgetMenuItem{"Create Group","/group/create/",false},
|
|
}}
|
|
|
|
err := templates.ExecuteTemplate(&b,"widget_menu.html",menu)
|
|
if err != nil {
|
|
LogError(err)
|
|
return
|
|
}
|
|
|
|
if themes[defaultTheme].Sidebars == "left" {
|
|
headerVars.Widgets.LeftSidebar = template.HTML(string(b.Bytes()))
|
|
} else if themes[defaultTheme].Sidebars == "right" || themes[defaultTheme].Sidebars == "both" {
|
|
headerVars.Widgets.RightSidebar = template.HTML(string(b.Bytes()))
|
|
}
|
|
}
|
|
|
|
// TO-DO: Do this properly via the widget system
|
|
// TO-DO: Make a better more customisable group widget system
|
|
func socialgroups_group_widgets(headerVars *HeaderVars, sgItem SocialGroup) (success bool) {
|
|
return false // Disabled until the next commit
|
|
|
|
var b bytes.Buffer
|
|
var menu WidgetMenu = WidgetMenu{"Group Options",[]WidgetMenuItem{
|
|
WidgetMenuItem{"Join","/group/join/" + strconv.Itoa(sgItem.ID),false},
|
|
WidgetMenuItem{"Members","/group/members/" + strconv.Itoa(sgItem.ID),false},
|
|
}}
|
|
|
|
err := templates.ExecuteTemplate(&b,"widget_menu.html",menu)
|
|
if err != nil {
|
|
LogError(err)
|
|
return false
|
|
}
|
|
|
|
if themes[defaultTheme].Sidebars == "left" {
|
|
headerVars.Widgets.LeftSidebar = template.HTML(string(b.Bytes()))
|
|
} else if themes[defaultTheme].Sidebars == "right" || themes[defaultTheme].Sidebars == "both" {
|
|
headerVars.Widgets.RightSidebar = template.HTML(string(b.Bytes()))
|
|
} else {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
/*
|
|
Custom Pages
|
|
*/
|
|
|
|
func socialgroups_group_list(w http.ResponseWriter, r *http.Request, user User) {
|
|
headerVars, ok := SessionCheck(w,r,&user)
|
|
if !ok {
|
|
return
|
|
}
|
|
socialgroups_common_area_widgets(&headerVars)
|
|
|
|
rows, err := socialgroups_list_stmt.Query()
|
|
if err != nil && err != ErrNoRows {
|
|
InternalError(err,w,r)
|
|
return
|
|
}
|
|
|
|
var sgList []SocialGroup
|
|
for rows.Next() {
|
|
sgItem := SocialGroup{ID:0}
|
|
err := rows.Scan(&sgItem.ID, &sgItem.Name, &sgItem.Desc, &sgItem.Active, &sgItem.Privacy, &sgItem.Joinable, &sgItem.Owner, &sgItem.MemberCount, &sgItem.CreatedAt, &sgItem.LastUpdateTime)
|
|
if err != nil {
|
|
InternalError(err,w,r)
|
|
return
|
|
}
|
|
sgItem.Link = socialgroups_build_group_url(name_to_slug(sgItem.Name),sgItem.ID)
|
|
sgList = append(sgList,sgItem)
|
|
}
|
|
err = rows.Err()
|
|
if err != nil {
|
|
InternalError(err,w,r)
|
|
return
|
|
}
|
|
rows.Close()
|
|
|
|
pi := SocialGroupListPage{"Group List",user,headerVars,sgList,extData}
|
|
err = templates.ExecuteTemplate(w,"socialgroups_group_list.html", pi)
|
|
if err != nil {
|
|
InternalError(err,w,r)
|
|
}
|
|
}
|
|
|
|
func socialgroups_get_group(sgid int) (sgItem SocialGroup, err error) {
|
|
sgItem = SocialGroup{ID:sgid}
|
|
err = socialgroups_get_group_stmt.QueryRow(sgid).Scan(&sgItem.Name, &sgItem.Desc, &sgItem.Active, &sgItem.Privacy, &sgItem.Joinable, &sgItem.Owner, &sgItem.MemberCount, &sgItem.MainForumID, &sgItem.Backdrop, &sgItem.CreatedAt, &sgItem.LastUpdateTime)
|
|
return sgItem, err
|
|
}
|
|
|
|
func socialgroups_view_group(w http.ResponseWriter, r *http.Request, user User) {
|
|
// SEO URLs...
|
|
halves := strings.Split(r.URL.Path[len("/group/"):],".")
|
|
if len(halves) < 2 {
|
|
halves = append(halves,halves[0])
|
|
}
|
|
sgid, err := strconv.Atoi(halves[1])
|
|
if err != nil {
|
|
PreError("Not a valid group ID",w,r)
|
|
return
|
|
}
|
|
|
|
sgItem, err := socialgroups_get_group(sgid)
|
|
if err != nil {
|
|
LocalError("Bad group",w,r,user)
|
|
return
|
|
}
|
|
if !sgItem.Active {
|
|
NotFound(w,r)
|
|
}
|
|
|
|
// Re-route the request to route_forums
|
|
var ctx context.Context = context.WithValue(r.Context(),"socialgroups_current_group",sgItem)
|
|
route_forum(w,r.WithContext(ctx),user,strconv.Itoa(sgItem.MainForumID))
|
|
}
|
|
|
|
func socialgroups_create_group(w http.ResponseWriter, r *http.Request, user User) {
|
|
headerVars, ok := SessionCheck(w,r,&user)
|
|
if !ok {
|
|
return
|
|
}
|
|
// TO-DO: Add an approval queue mode for group creation
|
|
if !user.Loggedin || !user.PluginPerms["CreateSocialGroup"] {
|
|
NoPermissions(w,r,user)
|
|
return
|
|
}
|
|
socialgroups_common_area_widgets(&headerVars)
|
|
|
|
pi := Page{"Create Group",user,headerVars,tList,nil}
|
|
err := templates.ExecuteTemplate(w,"socialgroups_create_group.html", pi)
|
|
if err != nil {
|
|
InternalError(err,w,r)
|
|
}
|
|
}
|
|
|
|
func socialgroups_create_group_submit(w http.ResponseWriter, r *http.Request, user User) {
|
|
// TO-DO: Add an approval queue mode for group creation
|
|
if !user.Loggedin || !user.PluginPerms["CreateSocialGroup"] {
|
|
NoPermissions(w,r,user)
|
|
return
|
|
}
|
|
|
|
var group_active bool = true
|
|
var group_name string = html.EscapeString(r.PostFormValue("group_name"))
|
|
var group_desc string = html.EscapeString(r.PostFormValue("group_desc"))
|
|
var gprivacy string = r.PostFormValue("group_privacy")
|
|
|
|
var group_privacy int
|
|
switch(gprivacy) {
|
|
case "0": group_privacy = 0 // Public
|
|
case "1": group_privacy = 1 // Protected
|
|
case "2": group_privacy = 2 // private
|
|
default: group_privacy = 0
|
|
}
|
|
|
|
// Create the backing forum
|
|
fid, err := fstore.CreateForum(group_name,"",true,"")
|
|
if err != nil {
|
|
InternalError(err,w,r)
|
|
return
|
|
}
|
|
|
|
res, err := socialgroups_create_group_stmt.Exec(group_name, group_desc, group_active, group_privacy, user.ID, fid)
|
|
if err != nil {
|
|
InternalError(err,w,r)
|
|
return
|
|
}
|
|
lastId, err := res.LastInsertId()
|
|
if err != nil {
|
|
InternalError(err,w,r)
|
|
return
|
|
}
|
|
|
|
// Add the main backing forum to the forum list
|
|
err = socialgroups_attach_forum(int(lastId),fid)
|
|
if err != nil {
|
|
InternalError(err,w,r)
|
|
return
|
|
}
|
|
|
|
_, err = socialgroups_add_member_stmt.Exec(lastId,user.ID,2)
|
|
if err != nil {
|
|
InternalError(err,w,r)
|
|
return
|
|
}
|
|
|
|
http.Redirect(w,r,socialgroups_build_group_url(name_to_slug(group_name),int(lastId)), http.StatusSeeOther)
|
|
}
|
|
|
|
func socialgroups_member_list(w http.ResponseWriter, r *http.Request, user User) {
|
|
headerVars, ok := SessionCheck(w,r,&user)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
// SEO URLs...
|
|
halves := strings.Split(r.URL.Path[len("/group/members/"):],".")
|
|
if len(halves) < 2 {
|
|
halves = append(halves,halves[0])
|
|
}
|
|
sgid, err := strconv.Atoi(halves[1])
|
|
if err != nil {
|
|
PreError("Not a valid group ID",w,r)
|
|
return
|
|
}
|
|
|
|
var sgItem SocialGroup = SocialGroup{ID:sgid}
|
|
var mainForum int // Unused
|
|
err = socialgroups_get_group_stmt.QueryRow(sgid).Scan(&sgItem.Name, &sgItem.Desc, &sgItem.Active, &sgItem.Privacy, &sgItem.Joinable, &sgItem.Owner, &sgItem.MemberCount, &mainForum, &sgItem.Backdrop, &sgItem.CreatedAt, &sgItem.LastUpdateTime)
|
|
if err != nil {
|
|
LocalError("Bad group",w,r,user)
|
|
return
|
|
}
|
|
sgItem.Link = socialgroups_build_group_url(name_to_slug(sgItem.Name),sgItem.ID)
|
|
|
|
socialgroups_group_widgets(&headerVars, sgItem)
|
|
|
|
rows, err := socialgroups_member_list_join_stmt.Query(sgid)
|
|
if err != nil && err != ErrNoRows {
|
|
InternalError(err,w,r)
|
|
return
|
|
}
|
|
|
|
var sgMembers []SocialGroupMember
|
|
for rows.Next() {
|
|
sgMember := SocialGroupMember{PostCount:0}
|
|
err := rows.Scan(&sgMember.User.ID,&sgMember.Rank,&sgMember.PostCount,&sgMember.JoinedAt,&sgMember.User.Name, &sgMember.User.Avatar)
|
|
if err != nil {
|
|
InternalError(err,w,r)
|
|
return
|
|
}
|
|
sgMember.Link = build_profile_url(name_to_slug(sgMember.User.Name),sgMember.User.ID)
|
|
if sgMember.User.Avatar != "" {
|
|
if sgMember.User.Avatar[0] == '.' {
|
|
sgMember.User.Avatar = "/uploads/avatar_" + strconv.Itoa(sgMember.User.ID) + sgMember.User.Avatar
|
|
}
|
|
} else {
|
|
sgMember.User.Avatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(sgMember.User.ID),1)
|
|
}
|
|
sgMember.JoinedAt, _ = relative_time(sgMember.JoinedAt)
|
|
if sgItem.Owner == sgMember.User.ID {
|
|
sgMember.RankString = "Owner"
|
|
} else {
|
|
switch(sgMember.Rank) {
|
|
case 0: sgMember.RankString = "Member"
|
|
case 1: sgMember.RankString = "Mod"
|
|
case 2: sgMember.RankString = "Admin"
|
|
}
|
|
}
|
|
sgMembers = append(sgMembers,sgMember)
|
|
}
|
|
err = rows.Err()
|
|
if err != nil {
|
|
InternalError(err,w,r)
|
|
return
|
|
}
|
|
rows.Close()
|
|
|
|
pi := SocialGroupMemberListPage{"Group Member List",user,headerVars,sgMembers,sgItem,0,0,extData}
|
|
// A plugin with plugins. Pluginception!
|
|
if pre_render_hooks["pre_render_socialgroups_member_list"] != nil {
|
|
if run_pre_render_hook("pre_render_socialgroups_member_list", w, r, &user, &pi) {
|
|
return
|
|
}
|
|
}
|
|
err = templates.ExecuteTemplate(w,"socialgroups_member_list.html", pi)
|
|
if err != nil {
|
|
InternalError(err,w,r)
|
|
}
|
|
}
|
|
|
|
func socialgroups_attach_forum(sgid int, fid int) error {
|
|
_, err := socialgroups_attach_forum_stmt.Exec(sgid,fid)
|
|
return err
|
|
}
|
|
|
|
func socialgroups_unattach_forum(fid int) error {
|
|
_, err := socialgroups_attach_forum_stmt.Exec(fid)
|
|
return err
|
|
}
|
|
|
|
func socialgroups_build_group_url(slug string, id int) string {
|
|
if slug == "" {
|
|
return "/group/" + slug + "." + strconv.Itoa(id)
|
|
}
|
|
return "/group/" + strconv.Itoa(id)
|
|
}
|
|
|
|
/*
|
|
Hooks
|
|
*/
|
|
|
|
func socialgroups_pre_render_view_forum(w http.ResponseWriter, r *http.Request, user *User, data interface{}) (halt bool) {
|
|
pi := data.(*ForumPage)
|
|
if pi.Header.ExtData.items != nil {
|
|
if sgData, ok := pi.Header.ExtData.items["socialgroups_current_group"]; ok {
|
|
sgItem := sgData.(SocialGroup)
|
|
|
|
sgpi := SocialGroupPage{pi.Title,pi.CurrentUser,pi.Header,pi.ItemList,pi.Forum,sgItem,pi.Page,pi.LastPage,pi.ExtData}
|
|
err := templates.ExecuteTemplate(w,"socialgroups_view_group.html", sgpi)
|
|
if err != nil {
|
|
LogError(err)
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func socialgroups_trow_assign(args ...interface{}) interface{} {
|
|
var forum *Forum = args[1].(*Forum)
|
|
if forum.ParentType == "socialgroup" {
|
|
var topicItem *TopicsRow = args[0].(*TopicsRow)
|
|
topicItem.ForumLink = "/group/" + strings.TrimPrefix(topicItem.ForumLink,get_forum_url_prefix())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// TO-DO: It would be nice, if you could select one of the boards in the group from that drop-down rather than just the one you got linked from
|
|
func socialgroups_topic_create_pre_loop(args ...interface{}) interface{} {
|
|
var fid int = args[2].(int)
|
|
if fstore.DirtyGet(fid).ParentType == "socialgroup" {
|
|
var strictmode *bool = args[5].(*bool)
|
|
*strictmode = true
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// TO-DO: Add privacy options
|
|
// TO-DO: Add support for multiple boards and add per-board simplified permissions
|
|
// TO-DO: Take is_js into account for routes which expect JSON responses
|
|
func socialgroups_forum_check(args ...interface{}) (skip interface{}) {
|
|
var r = args[1].(*http.Request)
|
|
var fid *int = args[3].(*int)
|
|
var forum *Forum = fstore.DirtyGet(*fid)
|
|
|
|
if forum.ParentType == "socialgroup" {
|
|
var err error
|
|
var w = args[0].(http.ResponseWriter)
|
|
var success *bool = args[4].(*bool)
|
|
sgItem, ok := r.Context().Value("socialgroups_current_group").(SocialGroup)
|
|
if !ok {
|
|
sgItem, err = socialgroups_get_group(forum.ParentID)
|
|
if err != nil {
|
|
InternalError(errors.New("Unable to find the parent group for a forum"),w,r)
|
|
*success = false
|
|
return false
|
|
}
|
|
if !sgItem.Active {
|
|
NotFound(w,r)
|
|
*success = false
|
|
return false
|
|
}
|
|
r = r.WithContext(context.WithValue(r.Context(),"socialgroups_current_group",sgItem))
|
|
}
|
|
|
|
var user *User = args[2].(*User)
|
|
var rank int
|
|
var posts int
|
|
var joinedAt string
|
|
|
|
// TO-DO: Group privacy settings. For now, groups are all globally visible
|
|
|
|
// Clear the default group permissions
|
|
// TO-DO: Do this more efficiently, doing it quick and dirty for now to get this out quickly
|
|
override_forum_perms(&user.Perms, false)
|
|
user.Perms.ViewTopic = true
|
|
|
|
err = socialgroups_get_member_stmt.QueryRow(sgItem.ID,user.ID).Scan(&rank,&posts,&joinedAt)
|
|
if err != nil && err != ErrNoRows {
|
|
*success = false
|
|
InternalError(err,w,r)
|
|
return false
|
|
} else if err != nil {
|
|
return true
|
|
}
|
|
|
|
// TO-DO: Implement bans properly by adding the Local Ban API in the next commit
|
|
if rank < 0 {
|
|
return true
|
|
}
|
|
|
|
// Basic permissions for members, more complicated permissions coming in the next commit!
|
|
if sgItem.Owner == user.ID {
|
|
override_forum_perms(&user.Perms,true)
|
|
} else if rank == 0 {
|
|
user.Perms.LikeItem = true
|
|
user.Perms.CreateTopic = true
|
|
user.Perms.CreateReply = true
|
|
} else {
|
|
override_forum_perms(&user.Perms,true)
|
|
}
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// TO-DO: Override redirects? I don't think this is needed quite yet
|
|
|
|
func socialgroups_widgets(args ...interface{}) interface{} {
|
|
var zone string = args[0].(string)
|
|
var headerVars *HeaderVars = args[2].(*HeaderVars)
|
|
var request *http.Request = args[3].(*http.Request)
|
|
|
|
if zone != "view_forum" {
|
|
return false
|
|
}
|
|
|
|
var forum *Forum = args[1].(*Forum)
|
|
if forum.ParentType == "socialgroup" {
|
|
// This is why I hate using contexts, all the daisy chains and interface casts x.x
|
|
sgItem, ok := request.Context().Value("socialgroups_current_group").(SocialGroup)
|
|
if !ok {
|
|
LogError(errors.New("Unable to find a parent group in the context data"))
|
|
return false
|
|
}
|
|
|
|
if headerVars.ExtData.items == nil {
|
|
headerVars.ExtData.items = make(map[string]interface{})
|
|
}
|
|
headerVars.ExtData.items["socialgroups_current_group"] = sgItem
|
|
|
|
return socialgroups_group_widgets(headerVars,sgItem)
|
|
}
|
|
return false
|
|
}
|