diff options
-rw-r--r-- | activitypub/actor.go | 12 | ||||
-rw-r--r-- | activitypub/object.go | 33 | ||||
-rw-r--r-- | main.go | 11 | ||||
-rw-r--r-- | routes/actor.go | 12 | ||||
-rw-r--r-- | routes/admin.go | 142 | ||||
-rw-r--r-- | routes/follow.go | 17 | ||||
-rw-r--r-- | routes/structs.go | 1 | ||||
-rw-r--r-- | views/manage.html (renamed from static/manage.html) | 57 | ||||
-rw-r--r-- | webfinger/comm.go | 1 |
9 files changed, 225 insertions, 61 deletions
diff --git a/activitypub/actor.go b/activitypub/actor.go index 3fbcb75..757f6bf 100644 --- a/activitypub/actor.go +++ b/activitypub/actor.go @@ -339,7 +339,7 @@ func GetActorFollowTotal(id string) (int, int, error) { return following, followers, nil } -func GetActorFollowers(w http.ResponseWriter, id string) error { +func GetActorFollowers(ctx *fiber.Ctx, id string) error { var following Collection var err error @@ -356,12 +356,12 @@ func GetActorFollowers(w http.ResponseWriter, id string) error { } enc, _ := json.MarshalIndent(following, "", "\t") - w.Header().Set("Content-Type", config.ActivityStreams) - _, err = w.Write(enc) + ctx.Response().Header.Set("Content-Type", config.ActivityStreams) + _, err = ctx.Write(enc) return err } -func GetActorFollowing(w http.ResponseWriter, id string) error { +func GetActorFollowing(ctx *fiber.Ctx, id string) error { var following Collection var err error @@ -378,8 +378,8 @@ func GetActorFollowing(w http.ResponseWriter, id string) error { } enc, _ := json.MarshalIndent(following, "", "\t") - w.Header().Set("Content-Type", config.ActivityStreams) - _, err = w.Write(enc) + ctx.Response().Header.Set("Content-Type", config.ActivityStreams) + _, err = ctx.Write(enc) return err } diff --git a/activitypub/object.go b/activitypub/object.go index 1256fac..c461310 100644 --- a/activitypub/object.go +++ b/activitypub/object.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "log" "mime/multipart" "net/http" "os" @@ -1777,3 +1778,35 @@ func WriteWalletToDB(obj ObjectBase) error { } return nil } + +func GetRecentPostsDB(actorID string) []ObjectBase { + var collection []ObjectBase + + query := `select id, actor, content, published, attachment from activitystream where actor=$1 and type='Note' union select id, actor, content, published, attachment from cacheactivitystream where actor in (select follower from follower where id=$1) and type='Note' order by published desc limit 20` + + rows, err := config.DB.Query(query, actorID) + + if err != nil { + log.Println("Could not get recent posts") + } + + defer rows.Close() + for rows.Next() { + var nObj ObjectBase + var attachmentID string + rows.Scan(&nObj.Id, &nObj.Actor, &nObj.Content, &nObj.Published, &attachmentID) + + isOP, _ := CheckIfObjectOP(nObj.Id) + nObj.Attachment, _ = GetObjectAttachment(attachmentID) + + if !isOP { + var reply ObjectBase + reply.Id = nObj.Id + nObj.InReplyTo = append(nObj.InReplyTo, reply) + } + + collection = append(collection, nObj) + } + + return collection +} @@ -59,9 +59,12 @@ func main() { app.Post("/verify", routes.AdminVerify) app.Post("/auth", routes.AdminAuth) app.All("/"+config.Key+"/", routes.AdminIndex) + app.Post("/"+config.Key+"/follow", routes.AdminFollow) app.Get("/"+config.Key+"/addboard", routes.AdminAddBoard) app.Get("/"+config.Key+"/postnews", routes.AdminPostNews) app.Get("/"+config.Key+"/newsdelete", routes.AdminNewsDelete) + app.Post("/"+config.Key+"/:actor/follow", routes.AdminActorIndex) + app.Get("/"+config.Key+"/:actor", routes.AdminActorIndex) app.Get("/news", routes.NewsGet) // Board managment @@ -80,16 +83,16 @@ func main() { app.Get("/api/media", routes.Media) // Board actor - app.Get("/:actor", routes.OutboxGet) - app.Post("/:actor", routes.ActorPost) app.Get("/:actor/catalog", routes.CatalogGet) - app.Get("/:actor/:post", routes.PostGet) app.Post("/:actor/inbox", routes.ActorInbox) app.Post("/:actor/outbox", routes.ActorOutbox) app.Get("/:actor/following", routes.ActorFollowing) - app.Get("/:actor/followers", routes.ActorFollowers) + app.All("/:actor/followers", routes.ActorFollowers) app.Get("/:actor/reported", routes.ActorReported) app.Get("/:actor/archive", routes.ActorArchive) + app.Get("/:actor", routes.OutboxGet) + app.Post("/:actor", routes.ActorPost) + app.Get("/:actor/:post", routes.PostGet) //404 handler app.Use(routes.NotFound) diff --git a/routes/actor.go b/routes/actor.go index d8b6631..d564850 100644 --- a/routes/actor.go +++ b/routes/actor.go @@ -403,16 +403,12 @@ func ActorOutbox(ctx *fiber.Ctx) error { return nil } -func ActorFollowing(c *fiber.Ctx) error { - // STUB - - return c.SendString("actor following") +func ActorFollowing(ctx *fiber.Ctx) error { + return activitypub.GetActorFollowing(ctx, config.Domain+"/"+ctx.Params("actor")) } -func ActorFollowers(c *fiber.Ctx) error { - // STUB - - return c.SendString("actor followers") +func ActorFollowers(ctx *fiber.Ctx) error { + return activitypub.GetActorFollowers(ctx, config.Domain+"/"+ctx.Params("actor")) } func ActorReported(c *fiber.Ctx) error { diff --git a/routes/admin.go b/routes/admin.go index a6978f4..e80d24f 100644 --- a/routes/admin.go +++ b/routes/admin.go @@ -3,10 +3,10 @@ package routes import ( "bytes" "encoding/json" - "fmt" "io/ioutil" "log" "net/http" + "regexp" "time" "github.com/FChannel0/FChannel-Server/activitypub" @@ -96,7 +96,6 @@ func AdminAuth(ctx *fiber.Ctx) error { } func AdminIndex(ctx *fiber.Ctx) error { - fmt.Println("admin index") id, _ := db.GetPasswordFromSession(ctx) actor, _ := webfinger.GetActorFromPath(ctx.Path(), "/"+config.Key+"/") @@ -150,6 +149,77 @@ func AdminIndex(ctx *fiber.Ctx) error { }) } +func AdminFollow(ctx *fiber.Ctx) error { + actor, _ := webfinger.GetActorFromPath(ctx.Path(), "/"+config.Key+"/") + + following := regexp.MustCompile(`(.+)\/following`) + followers := regexp.MustCompile(`(.+)\/followers`) + + follow := ctx.FormValue("follow") + actorId := ctx.FormValue("actor") + + //follow all of boards following + if following.MatchString(follow) { + followingActor, _ := webfinger.FingerActor(follow) + col, _ := webfinger.GetActorCollection(followingActor.Following) + + var nObj activitypub.ObjectBase + nObj.Id = followingActor.Id + + col.Items = append(col.Items, nObj) + + for _, e := range col.Items { + if isFollowing, _ := activitypub.IsAlreadyFollowing(actorId, e.Id); isFollowing && e.Id != config.Domain && e.Id != actorId { + followActivity, _ := db.MakeFollowActivity(actorId, e.Id) + + if actor, _ := webfinger.FingerActor(e.Id); actor.Id != "" { + db.MakeActivityRequestOutbox(followActivity) + } + } + } + + //follow all of boards followers + } else if followers.MatchString(follow) { + followersActor, _ := webfinger.FingerActor(follow) + col, _ := webfinger.GetActorCollection(followersActor.Followers) + + var nObj activitypub.ObjectBase + nObj.Id = followersActor.Id + + col.Items = append(col.Items, nObj) + + for _, e := range col.Items { + if isFollowing, _ := activitypub.IsAlreadyFollowing(actorId, e.Id); isFollowing && e.Id != config.Domain && e.Id != actorId { + followActivity, _ := db.MakeFollowActivity(actorId, e.Id) + if actor, _ := webfinger.FingerActor(e.Id); actor.Id != "" { + db.MakeActivityRequestOutbox(followActivity) + } + } + } + + //do a normal follow to a single board + } else { + followActivity, _ := db.MakeFollowActivity(actorId, follow) + + if isLocal, _ := activitypub.IsActorLocal(followActivity.Object.Actor); !isLocal && followActivity.Actor.Id == config.Domain { + _, err := ctx.Write([]byte("main board can only follow local boards. Create a new board and then follow outside boards from it.")) + return err + } + + if actor, _ := webfinger.FingerActor(follow); actor.Id != "" { + db.MakeActivityRequestOutbox(followActivity) + } + } + + var redirect string + + if actor.Name != "main" { + redirect = "/" + actor.Name + } + + return ctx.Redirect("/"+config.Key+"/"+redirect, http.StatusSeeOther) +} + func AdminAddBoard(c *fiber.Ctx) error { // STUB @@ -167,3 +237,71 @@ func AdminNewsDelete(c *fiber.Ctx) error { return c.SendString("admin news delete") } + +func AdminActorIndex(ctx *fiber.Ctx) error { + actor, _ := webfinger.GetActorFromPath(ctx.Path(), "/"+config.Key+"/") + + follow, _ := webfinger.GetActorCollection(actor.Following) + follower, _ := webfinger.GetActorCollection(actor.Followers) + reported, _ := activitypub.GetActorCollectionReq(actor.Id + "/reported") + + var following []string + var followers []string + var reports []db.Report + + for _, e := range follow.Items { + following = append(following, e.Id) + } + + for _, e := range follower.Items { + followers = append(followers, e.Id) + } + + for _, e := range reported.Items { + var r db.Report + r.Count = int(e.Size) + r.ID = e.Id + r.Reason = e.Content + reports = append(reports, r) + } + + localReports, _ := db.GetLocalReportDB(actor.Name) + + for _, e := range localReports { + var r db.Report + r.Count = e.Count + r.ID = e.ID + r.Reason = e.Reason + reports = append(reports, r) + } + + var data AdminPage + data.Following = following + data.Followers = followers + data.Reported = reports + data.Domain = config.Domain + data.IsLocal, _ = activitypub.IsActorLocal(actor.Id) + + data.Title = "Manage /" + actor.Name + "/" + data.Boards = webfinger.Boards + data.Board.Name = actor.Name + data.Board.Actor = actor + data.Key = config.Key + data.Board.TP = config.TP + + data.Board.Post.Actor = actor.Id + + data.AutoSubscribe, _ = activitypub.GetActorAutoSubscribeDB(actor.Id) + + data.Themes = &config.Themes + + data.RecentPosts = activitypub.GetRecentPostsDB(actor.Id) + + if cookie := ctx.Cookies("theme"); cookie != "" { + data.ThemeCookie = cookie + } + + return ctx.Render("manage", fiber.Map{ + "page": data, + }) +} diff --git a/routes/follow.go b/routes/follow.go index 2578983..3dbf9cf 100644 --- a/routes/follow.go +++ b/routes/follow.go @@ -1,15 +1,16 @@ package routes -import "github.com/gofiber/fiber/v2" +import ( + "github.com/FChannel0/FChannel-Server/activitypub" + "github.com/FChannel0/FChannel-Server/config" + "github.com/gofiber/fiber/v2" +) -func Following(c *fiber.Ctx) error { - // STUB - - return c.SendString("main following") +func Following(ctx *fiber.Ctx) error { + return activitypub.GetActorFollowing(ctx, config.Domain) } -func Followers(c *fiber.Ctx) error { +func Followers(ctx *fiber.Ctx) error { // STUB - - return c.SendString("main followers") + return activitypub.GetActorFollowers(ctx, config.Domain) } diff --git a/routes/structs.go b/routes/structs.go index 7c6e980..1c85676 100644 --- a/routes/structs.go +++ b/routes/structs.go @@ -42,6 +42,7 @@ type AdminPage struct { IsLocal bool PostBlacklist []util.PostBlacklist AutoSubscribe bool + RecentPosts []activitypub.ObjectBase Themes *[]string ThemeCookie string diff --git a/static/manage.html b/views/manage.html index c3d818c..af887e3 100644 --- a/static/manage.html +++ b/views/manage.html @@ -1,36 +1,30 @@ -{{ define "title" }}{{ .Title }}{{ end }} -{{ define "header" }} -<script src="/static/js/posts.js"></script> -{{ end }} -{{ define "top" }}{{ end }} -{{ define "content" }} <div style="text-align: center; margin: 0 auto; width: 400px;"> - <h1>Manage /{{ .Board.Name }}/</h1> + <h1>Manage /{{ .page.Board.Name }}/</h1> <!-- <div><a href="/{{ .Key }}/deleteboard?name={{ .Board.Name }}">[Delete Board]</a></div> --> <ul style="display: inline-block; padding: 0;"> - {{ if .IsLocal }} + {{ if .page.IsLocal }} <li style="display: inline-block;">[<a href="#following"> Subscribed </a>]</li> <li style="display: inline-block;">[<a href="#followers"> Subscribers </a>]</li> {{ end }} - <li style="display: inline-block;">[<a href="#reported"> Reported </a>]</li> + <li style="display: inline-block;">[<a href="#reported"> Reported </a>]</li> </ul> -</div> -[<a href="/{{ .Board.Name }}">Return</a>] -{{ $actor := .Board.Actor.Id }} -{{ $board := .Board }} -{{ $key := .Key }} -{{ if .IsLocal }} +</div> +[<a href="/{{ .page.Board.Name }}">Return</a>] +{{ $actor := .page.Board.Actor.Id }} +{{ $board := .page.Board }} +{{ $key := .page.Key }} +{{ if .page.IsLocal }} <div id="following" class="box2" style="margin-bottom: 25px; margin-top: 5px; padding: 12px;"> <h4 style="margin: 0; margin-bottom: 5px;">Following</h4> - [{{ if .AutoSubscribe }}<a title="Auto Follow is On" href="/autosubscribe?board={{ .Board.Name }}">Toggle Auto Follow Off{{ else }}<a title="Auto Follow is Off" href="/autosubscribe?board={{ .Board.Name }}">Toggle Auto Follow On{{ end }}</a>] - <form id="follow-form" action="/{{ .Key }}/{{ .Board.Name }}/follow" method="post" enctype="application/x-www-form-urlencoded" style="margin-top: 5px;"> + [{{ if .page.AutoSubscribe }}<a title="Auto Follow is On" href="/autosubscribe?board={{ .page.Board.Name }}">Toggle Auto Follow Off{{ else }}<a title="Auto Follow is Off" href="/autosubscribe?board={{ .page.Board.Name }}">Toggle Auto Follow On{{ end }}</a>] + <form id="follow-form" action="/{{ .page.Key }}/{{ .page.Board.Name }}/follow" method="post" enctype="application/x-www-form-urlencoded" style="margin-top: 5px;"> <input id="follow" name="follow" style="margin-bottom: 5px;" size="35" placeholder="https://fchan.xyz/g"></input> <input type="submit" value="Follow"><br> - <input type="hidden" name="actor" value="{{ $board.Actor.Id }}"> + <input type="hidden" name="actor" value="{{ $board.Actor.Id }}"> </form> <div style="margin-bottom: 12px; color: grey;">also https://fchan.xyz/g/following or https://fchan.xyz/g/followers</div> <ul style="display: inline-block; padding: 0; margin: 0; list-style-type: none;"> - {{ range .Following }} + {{ range .page.Following }} <li>[<a href="/{{ $key }}/{{ $board.Name }}/follow?follow={{ . }}&actor={{ $actor }}">Unsubscribe</a>]<a href="{{ . }}">{{ . }}</a></li> {{ end }} </ul> @@ -39,34 +33,33 @@ <div id="followers" class="box2" style="margin-bottom: 25px; padding: 12px;"> <h4 style="margin: 0; margin-bottom: 5px;">Followers</h4> <ul style="display: inline-block; padding: 0; margin: 0; list-style-type: none;"> - {{ range .Followers }} + {{ range .page.Followers }} <li><a href="{{ . }}">{{ . }}</a></li> - {{ end }} - </ul> + {{ end }} + </ul> </div> {{ end }} <div id="reported" class="box2" style="margin-bottom: 25px; padding: 12px;"> <h4 style="margin: 0; margin-bottom: 5px;">Reported</h4> <ul style="display: inline-block; padding: 0; margin: 0; list-style-type: none;"> - {{ $domain := .Domain }} - {{ range .Reported }} + {{ $domain := .page.Domain }} + {{ range .page.Reported }} <li><a id="rpost" post="{{ .ID }}" href=""></a> - <b>{{ .Count }}</b><span> "{{ .Reason }}" </span> [<a href="/delete?id={{ .ID }}&board={{ $board.Name }}&manage=t">Remove Post</a>] [<a href="/deleteattach?id={{ .ID }}&board={{ $board.Name }}&manage=t">Remove Attachment</a>] [<a href="/report?id={{ .ID }}&close=1&board={{ $board.Name }}">Close</a>]</li> {{ end }} - </ul> + </ul> </div> -{{ end }} -{{ define "bottom" }}{{ end }} -{{ define "script" }} +{{ template "partials/footer" .page }} +{{ template "partials/general_scripts" .page }} + <script> var reported = document.querySelectorAll('#rpost'); var reportedArray = [].slice.call(reported); reportedArray.forEach(function(r, i){ var id = r.getAttribute("post") - r.innerText = "/" + {{ .Board.Name }} + "/" + shortURL("{{ .Board.Actor.Id }}", id) - r.href = {{ .Domain }} + "/" + {{ .Board.Name }} + "/" + shortURL("{{ .Board.Actor.Id }}", id) - }) + r.innerText = "/" + {{ .page.Board.Name }} + "/" + shortURL("{{ .page.Board.Actor.Id }}", id) + r.href = {{ .page.Domain }} + "/" + {{ .page.Board.Name }} + "/" + shortURL("{{ .page.Board.Actor.Id }}", id) + }) </script> -{{ end }} diff --git a/webfinger/comm.go b/webfinger/comm.go index 35ad335..ed20779 100644 --- a/webfinger/comm.go +++ b/webfinger/comm.go @@ -37,7 +37,6 @@ func GetActorCollection(collection string) (activitypub.Collection, error) { if resp.StatusCode == 200 { body, _ := ioutil.ReadAll(resp.Body) - if len(body) > 0 { if err := json.Unmarshal(body, &nCollection); err != nil { return nCollection, err |