feat(strava): sync all activity photos instead of only primary photo (#1015)
Co-authored-by: Flomp <Flomp@users.noreply.github.com>
This commit is contained in:
@@ -351,6 +351,11 @@ type Photos struct {
|
|||||||
Count int `json:"count"`
|
Count int `json:"count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StravaActivityPhoto struct {
|
||||||
|
UniqueID string `json:"unique_id"`
|
||||||
|
Urls Urls `json:"urls"`
|
||||||
|
}
|
||||||
|
|
||||||
type HighlightedKudosers struct {
|
type HighlightedKudosers struct {
|
||||||
DestinationURL string `json:"destination_url"`
|
DestinationURL string `json:"destination_url"`
|
||||||
DisplayName string `json:"display_name"`
|
DisplayName string `json:"display_name"`
|
||||||
|
|||||||
@@ -452,7 +452,7 @@ func syncTrailsWithActivities(app core.App, client meilisearch.ServiceManager, c
|
|||||||
app.Logger().Warn(fmt.Sprintf("Unable to fetch GPX for activity '%s': %v", activity.Name, err))
|
app.Logger().Warn(fmt.Sprintf("Unable to fetch GPX for activity '%s': %v", activity.Name, err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
trailID, err := createTrailFromActivity(app, detailedActivity, gpx, user, actor.Id, i.Privacy)
|
trailID, err := createTrailFromActivity(app, detailedActivity, gpx, user, actor.Id, i.Privacy, accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
app.Logger().Warn(fmt.Sprintf("Unable to create trail from activity '%s': %v", activity.Name, err))
|
app.Logger().Warn(fmt.Sprintf("Unable to create trail from activity '%s': %v", activity.Name, err))
|
||||||
continue
|
continue
|
||||||
@@ -492,7 +492,7 @@ func fetchDetailedActivity(activity StravaActivity, accessToken string) (*Detail
|
|||||||
return &detailedActivity, nil
|
return &detailedActivity, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTrailFromActivity(app core.App, activity *DetailedStravaActivity, gpx *filesystem.File, user string, actor string, privacy string) (string, error) {
|
func createTrailFromActivity(app core.App, activity *DetailedStravaActivity, gpx *filesystem.File, user string, actor string, privacy string, accessToken string) (string, error) {
|
||||||
if len(activity.StartLatlng) < 2 {
|
if len(activity.StartLatlng) < 2 {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
@@ -502,11 +502,19 @@ func createTrailFromActivity(app core.App, activity *DetailedStravaActivity, gpx
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var photo *filesystem.File
|
var photos []*filesystem.File
|
||||||
if len(activity.Photos.Primary.Urls.Num600) > 0 {
|
if activity.Photos.Count > 0 {
|
||||||
photo, err = fetchActivityPhoto(activity)
|
photos, err = fetchActivityPhotos(activity.ID, accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
app.Logger().Warn(fmt.Sprintf("Failed to fetch activity photos for activity %d: %v", activity.ID, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to primary photo if no photos were fetched but primary URL is available
|
||||||
|
if len(photos) == 0 && len(activity.Photos.Primary.Urls.Num600) > 0 {
|
||||||
|
photo, err := fetchPhotoFromURL(activity.Photos.Primary.Urls.Num600)
|
||||||
|
if err == nil {
|
||||||
|
photos = []*filesystem.File{photo}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,8 +597,8 @@ func createTrailFromActivity(app core.App, activity *DetailedStravaActivity, gpx
|
|||||||
"author": actor,
|
"author": actor,
|
||||||
})
|
})
|
||||||
|
|
||||||
if photo != nil {
|
if len(photos) > 0 {
|
||||||
record.Set("photos", photo)
|
record.Set("photos", photos)
|
||||||
}
|
}
|
||||||
|
|
||||||
if gpx != nil {
|
if gpx != nil {
|
||||||
@@ -607,8 +615,8 @@ func createTrailFromActivity(app core.App, activity *DetailedStravaActivity, gpx
|
|||||||
return record.Id, nil
|
return record.Id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchActivityPhoto(activity *DetailedStravaActivity) (*filesystem.File, error) {
|
func fetchPhotoFromURL(url string) (*filesystem.File, error) {
|
||||||
req, err := http.NewRequest("GET", activity.Photos.Primary.Urls.Num600, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -638,6 +646,50 @@ func fetchActivityPhoto(activity *DetailedStravaActivity) (*filesystem.File, err
|
|||||||
return photo, nil
|
return photo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fetchActivityPhotos(activityID int64, accessToken string) ([]*filesystem.File, error) {
|
||||||
|
url := fmt.Sprintf("https://www.strava.com/api/v3/activities/%d/photos?size=600", activityID)
|
||||||
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Authorization", "Bearer "+accessToken)
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return nil, fmt.Errorf("failed to fetch activity photos: received status %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
var apiPhotos []StravaActivityPhoto
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&apiPhotos); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
photos := make([]*filesystem.File, 0, len(apiPhotos))
|
||||||
|
for _, apiPhoto := range apiPhotos {
|
||||||
|
photoURL := apiPhoto.Urls.Num600
|
||||||
|
if photoURL == "" {
|
||||||
|
photoURL = apiPhoto.Urls.Num100
|
||||||
|
}
|
||||||
|
if photoURL == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
photo, err := fetchPhotoFromURL(photoURL)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
photos = append(photos, photo)
|
||||||
|
}
|
||||||
|
|
||||||
|
return photos, nil
|
||||||
|
}
|
||||||
|
|
||||||
func generateActivityGPX(activity *DetailedStravaActivity, accessToken string) (*filesystem.File, error) {
|
func generateActivityGPX(activity *DetailedStravaActivity, accessToken string) (*filesystem.File, error) {
|
||||||
url := fmt.Sprintf("https://www.strava.com/api/v3/activities/%d/streams?keys=latlng,time,altitude&key_by_type=true", activity.ID)
|
url := fmt.Sprintf("https://www.strava.com/api/v3/activities/%d/streams?keys=latlng,time,altitude&key_by_type=true", activity.ID)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user