mirror of
https://github.com/writefreely/writefreely
synced 2024-11-10 11:24:13 +00:00
Handles are saved in remoteusers
while the links take you to an
intermediate page (WIP) that shows the user profile page url
This commit is contained in:
parent
e5bbd45b49
commit
99bb77153e
5 changed files with 82 additions and 17 deletions
|
@ -26,7 +26,6 @@ import (
|
|||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/writeas/activity/streams"
|
||||
"github.com/writeas/activityserve"
|
||||
"github.com/writeas/httpsig"
|
||||
"github.com/writeas/impart"
|
||||
"github.com/writeas/nerds/store"
|
||||
|
@ -45,6 +44,7 @@ type RemoteUser struct {
|
|||
ActorID string
|
||||
Inbox string
|
||||
SharedInbox string
|
||||
Handle string
|
||||
}
|
||||
|
||||
func (ru *RemoteUser) AsPerson() *activitystreams.Person {
|
||||
|
@ -133,7 +133,7 @@ func handleFetchCollectionOutbox(app *App, w http.ResponseWriter, r *http.Reques
|
|||
posts, err := app.db.GetPosts(app.cfg, c, p, false, true, false)
|
||||
for _, pp := range *posts {
|
||||
pp.Collection = res
|
||||
o := pp.ActivityObject(app.cfg)
|
||||
o := pp.ActivityObject(app)
|
||||
a := activitystreams.NewCreateActivity(o)
|
||||
ocp.OrderedItems = append(ocp.OrderedItems, *a)
|
||||
}
|
||||
|
@ -525,7 +525,7 @@ func deleteFederatedPost(app *App, p *PublicPost, collID int64) error {
|
|||
}
|
||||
p.Collection.hostName = app.cfg.App.Host
|
||||
actor := p.Collection.PersonObject(collID)
|
||||
na := p.ActivityObject(app.cfg)
|
||||
na := p.ActivityObject(app)
|
||||
|
||||
// Add followers
|
||||
p.Collection.ID = collID
|
||||
|
@ -571,7 +571,7 @@ func federatePost(app *App, p *PublicPost, collID int64, isUpdate bool) error {
|
|||
}
|
||||
}
|
||||
actor := p.Collection.PersonObject(collID)
|
||||
na := p.ActivityObject(app.cfg)
|
||||
na := p.ActivityObject(app)
|
||||
|
||||
// Add followers
|
||||
p.Collection.ID = collID
|
||||
|
@ -626,8 +626,7 @@ func federatePost(app *App, p *PublicPost, collID int64, isUpdate bool) error {
|
|||
// the mentioned users. This might seem wasteful but the code is
|
||||
// cleaner than adding the mentioned users to CC here instead of
|
||||
// in p.ActivityObject()
|
||||
na = p.ActivityObject(app.cfg)
|
||||
|
||||
na = p.ActivityObject(app)
|
||||
for _, tag := range na.Tag {
|
||||
if tag.Type == "Mention" {
|
||||
activity = activitystreams.NewCreateActivity(na)
|
||||
|
@ -638,11 +637,11 @@ func federatePost(app *App, p *PublicPost, collID int64, isUpdate bool) error {
|
|||
// much logic to catch this at the expense of the odd extra request.
|
||||
// I don't believe we'd ever have too many mentions in a single post that this
|
||||
// could become a burden.
|
||||
remoteActor, err := activityserve.NewRemoteActor(tag.HRef)
|
||||
if err != nil {
|
||||
log.Error("Couldn't fetch remote actor", err)
|
||||
}
|
||||
err = makeActivityPost(app.cfg.App.Host, actor, remoteActor.GetInbox(), activity)
|
||||
|
||||
fmt.Println(tag.HRef)
|
||||
fmt.Println("aaa")
|
||||
remoteUser, err := getRemoteUser(app, tag.HRef)
|
||||
err = makeActivityPost(app.cfg.App.Host, actor, remoteUser.Inbox, activity)
|
||||
if err != nil {
|
||||
log.Error("Couldn't post! %v", err)
|
||||
}
|
||||
|
@ -656,7 +655,7 @@ func federatePost(app *App, p *PublicPost, collID int64, isUpdate bool) error {
|
|||
|
||||
func getRemoteUser(app *App, actorID string) (*RemoteUser, error) {
|
||||
u := RemoteUser{ActorID: actorID}
|
||||
err := app.db.QueryRow("SELECT id, inbox, shared_inbox FROM remoteusers WHERE actor_id = ?", actorID).Scan(&u.ID, &u.Inbox, &u.SharedInbox)
|
||||
err := app.db.QueryRow("SELECT id, inbox, shared_inbox, handle FROM remoteusers WHERE actor_id = ?", actorID).Scan(&u.ID, &u.Inbox, &u.SharedInbox, &u.Handle)
|
||||
switch {
|
||||
case err == sql.ErrNoRows:
|
||||
return nil, impart.HTTPError{http.StatusNotFound, "No remote user with that ID."}
|
||||
|
@ -668,6 +667,21 @@ func getRemoteUser(app *App, actorID string) (*RemoteUser, error) {
|
|||
return &u, nil
|
||||
}
|
||||
|
||||
// getRemoteUserFromHandle retrieves the profile page of a remote user
|
||||
// from the @user@server.tld handle
|
||||
func getRemoteUserFromHandle(app *App, handle string) (*RemoteUser, error) {
|
||||
u := RemoteUser{Handle: handle}
|
||||
err := app.db.QueryRow("SELECT id, actor_id, inbox, shared_inbox FROM remoteusers WHERE handle = ?", handle).Scan(&u.ID, &u.ActorID, &u.Inbox, &u.SharedInbox)
|
||||
switch {
|
||||
case err == sql.ErrNoRows:
|
||||
return nil, impart.HTTPError{http.StatusNotFound, "No remote user with that handle."}
|
||||
case err != nil:
|
||||
log.Error("Couldn't get remote user %s: %v", handle, err)
|
||||
return nil, err
|
||||
}
|
||||
return &u, nil
|
||||
}
|
||||
|
||||
func getActor(app *App, actorIRI string) (*activitystreams.Person, *RemoteUser, error) {
|
||||
log.Info("Fetching actor %s locally", actorIRI)
|
||||
actor := &activitystreams.Person{}
|
||||
|
|
|
@ -820,6 +820,21 @@ func handleViewCollection(app *App, w http.ResponseWriter, r *http.Request) erro
|
|||
return err
|
||||
}
|
||||
|
||||
func handleViewMention(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||
vars := mux.Vars(r)
|
||||
handle := vars["handle"]
|
||||
|
||||
remoteUser, err := getRemoteUserFromHandle(app, handle)
|
||||
if err != nil {
|
||||
log.Error("Couldn't find this user in our database "+handle, err)
|
||||
return err
|
||||
}
|
||||
|
||||
w.Write([]byte("go to " + remoteUser.ActorID))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleViewCollectionTag(app *App, w http.ResponseWriter, r *http.Request) error {
|
||||
vars := mux.Vars(r)
|
||||
tag := vars["tag"]
|
||||
|
|
|
@ -34,6 +34,7 @@ var (
|
|||
titleElementReg = regexp.MustCompile("</?h[1-6]>")
|
||||
hashtagReg = regexp.MustCompile(`{{\[\[\|\|([^|]+)\|\|\]\]}}`)
|
||||
markeddownReg = regexp.MustCompile("<p>(.+)</p>")
|
||||
mentionReg = regexp.MustCompile(`@[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+\b`)
|
||||
)
|
||||
|
||||
func (p *Post) formatContent(cfg *config.Config, c *Collection, isOwner bool) {
|
||||
|
@ -82,6 +83,8 @@ func applyMarkdownSpecial(data []byte, skipNoFollow bool, baseURL string, cfg *c
|
|||
tagPrefix = "/read/t/"
|
||||
}
|
||||
md = []byte(hashtagReg.ReplaceAll(md, []byte("<a href=\""+tagPrefix+"$1\" class=\"hashtag\"><span>#</span><span class=\"p-category\">$1</span></a>")))
|
||||
handlePrefix := baseURL + "mention:"
|
||||
md = []byte(mentionReg.ReplaceAll(md, []byte("<a href=\""+handlePrefix+"$0\" class=\"mention\">$0</a>")))
|
||||
}
|
||||
// Strip out bad HTML
|
||||
policy := getSanitizationPolicy()
|
||||
|
|
42
posts.go
42
posts.go
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/guregu/null/zero"
|
||||
"github.com/kylemcc/twitter-text-go/extract"
|
||||
"github.com/microcosm-cc/bluemonday"
|
||||
"github.com/writeas/activityserve"
|
||||
stripmd "github.com/writeas/go-strip-markdown"
|
||||
"github.com/writeas/impart"
|
||||
"github.com/writeas/monday"
|
||||
|
@ -35,7 +36,6 @@ import (
|
|||
"github.com/writeas/web-core/i18n"
|
||||
"github.com/writeas/web-core/log"
|
||||
"github.com/writeas/web-core/tags"
|
||||
"github.com/writeas/writefreely/config"
|
||||
"github.com/writeas/writefreely/page"
|
||||
"github.com/writeas/writefreely/parse"
|
||||
)
|
||||
|
@ -1033,7 +1033,7 @@ func fetchPost(app *App, w http.ResponseWriter, r *http.Request) error {
|
|||
}
|
||||
|
||||
p.Collection = &CollectionObj{Collection: *coll}
|
||||
po := p.ActivityObject(app.cfg)
|
||||
po := p.ActivityObject(app)
|
||||
po.Context = []interface{}{activitystreams.Namespace}
|
||||
return impart.RenderActivityJSON(w, po, http.StatusOK)
|
||||
}
|
||||
|
@ -1068,7 +1068,8 @@ func (p *PublicPost) CanonicalURL() string {
|
|||
return p.Collection.CanonicalURL() + p.Slug.String
|
||||
}
|
||||
|
||||
func (p *PublicPost) ActivityObject(cfg *config.Config) *activitystreams.Object {
|
||||
func (p *PublicPost) ActivityObject(app *App) *activitystreams.Object {
|
||||
cfg := app.cfg
|
||||
o := activitystreams.NewArticleObject()
|
||||
o.ID = p.Collection.FederatedAPIBase() + "api/posts/" + p.ID
|
||||
o.Published = p.Created
|
||||
|
@ -1117,7 +1118,38 @@ func (p *PublicPost) ActivityObject(cfg *config.Config) *activitystreams.Object
|
|||
mentions := mentionRegex.FindAllString(content, -1)
|
||||
|
||||
for _, handle := range mentions {
|
||||
actorIRI := RemoteLookup(handle)
|
||||
var actorIRI string
|
||||
remoteuser, errRemoteUser := getRemoteUserFromHandle(app, handle)
|
||||
if errRemoteUser != nil {
|
||||
// can't find using handle in the table but the table may already have this user without
|
||||
// handle from a previous version
|
||||
actorIRI = RemoteLookup(handle)
|
||||
_, errRemoteUser := getRemoteUser(app, actorIRI)
|
||||
// if it exists then we need to update the handle
|
||||
if errRemoteUser == nil {
|
||||
// query := "UPDATE remoteusers SET handle='" + handle + "' WHERE actor_id='" + iri + "';"
|
||||
// log.Info(query)
|
||||
_, err := app.db.Exec("UPDATE remoteusers SET handle=? WHERE actor_id=?;", handle, actorIRI)
|
||||
if err != nil {
|
||||
log.Error("Can't update handle (" + handle + ") in database for user " + actorIRI)
|
||||
}
|
||||
} else {
|
||||
// this probably means we don't have the user in the table so let's try to insert it
|
||||
// here we need to ask the server for the inboxes
|
||||
remoteActor, err := activityserve.NewRemoteActor(actorIRI)
|
||||
if err != nil {
|
||||
log.Error("Couldn't fetch remote actor", err)
|
||||
}
|
||||
fmt.Println(actorIRI, remoteActor.GetInbox(), remoteActor.GetSharedInbox(), handle)
|
||||
_, err = app.db.Exec("INSERT INTO remoteusers (actor_id, inbox, shared_inbox, handle) VALUES( ?, ?, ?, ?)", actorIRI, remoteActor.GetInbox(), remoteActor.GetSharedInbox(), handle)
|
||||
if err != nil {
|
||||
log.Error("Can't insert remote user in database", err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
actorIRI = remoteuser.ActorID
|
||||
}
|
||||
mentionedUsers[handle] = actorIRI
|
||||
}
|
||||
|
||||
|
@ -1379,7 +1411,7 @@ Are you sure it was ever here?`,
|
|||
return ErrCollectionPageNotFound
|
||||
}
|
||||
p.extractData()
|
||||
ap := p.ActivityObject(app.cfg)
|
||||
ap := p.ActivityObject(app)
|
||||
ap.Context = []interface{}{activitystreams.Namespace}
|
||||
return impart.RenderActivityJSON(w, ap, http.StatusOK)
|
||||
} else {
|
||||
|
|
|
@ -184,6 +184,7 @@ func InitRoutes(apper Apper, r *mux.Router) *mux.Router {
|
|||
|
||||
func RouteCollections(handler *Handler, r *mux.Router) {
|
||||
r.HandleFunc("/page/{page:[0-9]+}", handler.Web(handleViewCollection, UserLevelReader))
|
||||
r.HandleFunc("/mention:{handle}", handler.Web(handleViewMention, UserLevelReader))
|
||||
r.HandleFunc("/tag:{tag}", handler.Web(handleViewCollectionTag, UserLevelReader))
|
||||
r.HandleFunc("/tag:{tag}/feed/", handler.Web(ViewFeed, UserLevelReader))
|
||||
r.HandleFunc("/tags/{tag}", handler.Web(handleViewCollectionTag, UserLevelReader))
|
||||
|
|
Loading…
Reference in a new issue