Federation (#327)

* initial commit federation

* more federation

* more federation

* more federation

* completes follow, accept, undo

* add trail create activity

* process trail create activity

* more trail create activity

* adds missing endpoints

* adds update and delete activity

* adds comment activities

* adds activities back

* adds summit logs activities

* deletes follow counts table

* fixes migrations

* fixes migrations

* fixes migrations

* fixes migrations

* adds remote profiles

* ctd

* ctd

* we are getting closer...

* adds public summit logs

* fixes federated trails in lists

* adds remote lists

* adds list activites

* fixes lists

* adds notifications

* adds iri redirect

* fixes comments and summitlogs

* fixes follows and profiles

* adds asynchronous send

* fixes list search

* adds encryption key

* bug fixes

* fixes activity signing

* removes custon activity object types

* adds html editor

* fixes html editor

* fixes display issues on mastodon

* adds federated sharing

* finishes announcements

* fixes small summit log issues

* adds trail likes

* finalizes likes

* fixes images for komoot

* add disable federation option

* adds private profiles

* updates docs

* adds federated comments

* adds trail and comments actvitiypub routes

* adds mentions to editor

* adds mentions to trails, comments, summit logs

* updates theme

* updates theme

* update docs

* update docs

* updates docs

* fixes various frontend problems

* fixes activitypub follows api

* updates docs

* updates docs

---------

Co-authored-by: Christian Beutel <>
This commit is contained in:
Flomp
2025-06-21 10:09:22 +02:00
committed by GitHub
parent 742a6d9d30
commit 9276690d60
356 changed files with 57150 additions and 35470 deletions

View File

@@ -33,6 +33,15 @@ func SyncKomoot(app core.App) error {
}
userId := i.GetString("user")
actor, err := app.FindFirstRecordByData("activitypub_actors", "user", userId)
if err != nil {
warning := fmt.Sprintf("no actor found for user: %s\n", userId)
fmt.Print(warning)
app.Logger().Warn(warning)
continue
}
actorId := actor.Id
komootString := i.GetString("komoot")
komootIntegration := KomootIntegration{
Planned: true,
@@ -71,7 +80,7 @@ func SyncKomoot(app core.App) error {
continue
}
hasNewTours, err = syncTrailWithTours(app, k, komootIntegration, userId, tours)
hasNewTours, err = syncTrailWithTours(app, k, komootIntegration, userId, actorId, tours)
if err != nil {
warning := fmt.Sprintf("error syncing komoot tours with trails: %v\n", err)
fmt.Print(warning)
@@ -165,7 +174,7 @@ func (k *KomootApi) fetchTours(page int) ([]KomootTour, error) {
}
func (k *KomootApi) fetchDetailedTour(tour KomootTour) (*DetailedKomootTour, error) {
url := fmt.Sprintf("https://api.komoot.de/v007/tours/%d?_embedded=coordinates,way_types,surfaces,directions,participants,timeline,cover_images&directions=v2&fields=timeline&format=coordinate_array&timeline_highlights_fields=tips,recommenders", tour.ID)
url := fmt.Sprintf("https://api.komoot.de/v007/tours/%d?_embedded=coordinates,way_types,surfaces,directions,participants,timeline,cover_images&directions=v2&fields=timeline&format=coordinate_array&timeline_highlights_fields=tips,recommenders&page=2", tour.ID)
body, err := sendRequest(url, k.buildHeader())
if err != nil {
return nil, err
@@ -176,7 +185,7 @@ func (k *KomootApi) fetchDetailedTour(tour KomootTour) (*DetailedKomootTour, err
return data, nil
}
func syncTrailWithTours(app core.App, k *KomootApi, i KomootIntegration, user string, tours []KomootTour) (bool, error) {
func syncTrailWithTours(app core.App, k *KomootApi, i KomootIntegration, user string, actor string, tours []KomootTour) (bool, error) {
hasNewTours := false
for _, tour := range tours {
trails, err := app.FindRecordsByFilter("trails", "external_id = {:id}", "", 1, 0, dbx.Params{"id": strconv.Itoa(int(tour.ID))})
@@ -202,7 +211,7 @@ func syncTrailWithTours(app core.App, k *KomootApi, i KomootIntegration, user st
app.Logger().Warn(fmt.Sprintf("Unable to create waypoints for tour '%s': %v", tour.Name, err))
continue
}
err = createTrailFromTour(app, detailedTour, gpx, user, wpIds)
err = createTrailFromTour(app, k, detailedTour, gpx, actor, wpIds)
if err != nil {
app.Logger().Warn(fmt.Sprintf("Unable to create trail for tour '%s': %v", tour.Name, err))
continue
@@ -212,27 +221,9 @@ func syncTrailWithTours(app core.App, k *KomootApi, i KomootIntegration, user st
return hasNewTours, nil
}
func createTrailFromTour(app core.App, detailedTour *DetailedKomootTour, gpx *filesystem.File, user string, wpIds []string) error {
var summitLogRecord *core.Record
if detailedTour.Type == "tour_recorded" {
collection, err := app.FindCollectionByNameOrId("summit_logs")
if err != nil {
return err
}
func createTrailFromTour(app core.App, k *KomootApi, detailedTour *DetailedKomootTour, gpx *filesystem.File, actor string, wpIds []string) error {
trailid := security.RandomStringWithAlphabet(core.DefaultIdLength, core.DefaultIdAlphabet)
summitLogRecord = core.NewRecord(collection)
summitLogRecord.Load(map[string]any{
"distance": detailedTour.Distance,
"elevation_gain": detailedTour.ElevationUp,
"elevation_loss": detailedTour.ElevationDown,
"duration": detailedTour.Duration,
"date": detailedTour.Date,
"author": user,
})
if err := app.Save(summitLogRecord); err != nil {
return err
}
}
collection, err := app.FindCollectionByNameOrId("trails")
if err != nil {
return err
@@ -259,7 +250,7 @@ func createTrailFromTour(app core.App, detailedTour *DetailedKomootTour, gpx *fi
var photos []*filesystem.File
if len(detailedTour.Embedded.CoverImages.Embedded.Items) > 0 {
photos, err = fetchRoutePhotos(detailedTour)
photos, err = fetchRoutePhotos(k, detailedTour)
if err != nil {
return err
}
@@ -277,6 +268,7 @@ func createTrailFromTour(app core.App, detailedTour *DetailedKomootTour, gpx *fi
}
record.Load(map[string]any{
"id": trailid,
"name": detailedTour.Name,
"public": detailedTour.Status == "public",
"distance": detailedTour.Distance,
@@ -291,12 +283,9 @@ func createTrailFromTour(app core.App, detailedTour *DetailedKomootTour, gpx *fi
"difficulty": diffculty,
"category": categoryId,
"waypoints": wpIds,
"author": user,
"author": actor,
})
if summitLogRecord != nil {
record.Set("summit_logs", summitLogRecord.Id)
}
if photos != nil {
record.Set("photos", photos)
}
@@ -308,6 +297,27 @@ func createTrailFromTour(app core.App, detailedTour *DetailedKomootTour, gpx *fi
return err
}
if detailedTour.Type == "tour_recorded" {
collection, err := app.FindCollectionByNameOrId("summit_logs")
if err != nil {
return err
}
summitLogRecord := core.NewRecord(collection)
summitLogRecord.Load(map[string]any{
"distance": detailedTour.Distance,
"elevation_gain": detailedTour.ElevationUp,
"elevation_loss": detailedTour.ElevationDown,
"duration": detailedTour.Duration,
"date": detailedTour.Date,
"author": actor,
"trail": trailid,
})
if err := app.Save(summitLogRecord); err != nil {
return err
}
}
return nil
}
@@ -365,11 +375,22 @@ func createWaypointsFromTour(app core.App, tour *DetailedKomootTour, user string
return wpIds, nil
}
func fetchRoutePhotos(tour *DetailedKomootTour) ([]*filesystem.File, error) {
func fetchRoutePhotos(k *KomootApi, tour *DetailedKomootTour) ([]*filesystem.File, error) {
url := fmt.Sprintf("https://api.komoot.de/v007/tours/%d/cover_images/", tour.ID)
body, err := sendRequest(url, k.buildHeader())
if err != nil {
return nil, err
}
photos := make([]*filesystem.File, len(tour.Embedded.CoverImages.Embedded.Items))
var data *CoverImages
err = json.Unmarshal(body, &data)
if err != nil {
return nil, err
}
for i, img := range tour.Embedded.CoverImages.Embedded.Items {
photos := make([]*filesystem.File, data.Page.TotalElements)
for i, img := range data.Embedded.Items {
photo, err := fetchPhoto(img.Src, "", "")
if err != nil {
return nil, err