Skip to content
82 changes: 82 additions & 0 deletions meta/instagram.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package meta

import "time"

// InstagramPostType defines the type of post.
type InstagramPostType string

// InstagramMediaType defines the type of media in the post.
type InstagramMediaType string

// Types of Instagram posts.
const (
InstagramImagePost InstagramPostType = "image"
InstagramVideoPost = "video"
InstagramCarouselPost = "carousel"
)

// Types of Instagram media.
const (
InstagramImageMedia InstagramMediaType = "image"
InstagramVideoMedia = "video"
)

// InstagramPost is the full set of data available for media on Instagram.
// https://www.instagram.com/developer/
type InstagramPost struct {

// Media ID
ID string `json:"id"`
Type InstagramPostType `json:"type,omitempty"`

// Public URL
URL string `json:"url,omitempty"`

// Describe an individual piece of media within a multi-media post.
Multiple bool `json:"multiple,omitempty"`
MediaType InstagramMediaType `json:"media_type,omitempty"`
Position int `json:"position"`

// User that posted it.
UserID string `json:"user_id,omitempty"`
Username string `json:"username,omitempty"`
UserFullName string `json:"user_full_name,omitempty"`

// Basic information when posted.
Caption string `json:"caption,omitempty"`
PostedAt *time.Time `json:"posted_at,omitempty"`

// Additional information when posted.
Filter string `json:"filter,omitempty"`
Tags []string `json:"tags,omitempty"`
TaggedUsers []InstagramTaggedUser `json:"tagged_users,omitempty"`
Location *InstagramLocation `json:"location,omitempty"`

// User activity.
LikesCount int `json:"likes_count,omitempty"`
CommentsCount int `json:"comments_count,omitempty"`
Comments []InstagramComment `json:"comments,omitempty"`
}

// InstagramLocation describes geo location of an Instagram post.
type InstagramLocation struct {
ID string `json:"id"`
Name string `json:"name"`
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
}

// InstagramComment is a comment on an Instagram post.
type InstagramComment struct {
ID string `json:"id"`
Text string `json:"text"`
Username string `json:"username,omitempty"`
Date *time.Time `json:"date,omitempty"`
}

// InstagramTaggedUser is a user tagged in media.
type InstagramTaggedUser struct {
Username string `json:"username"`
X float64 `json:"x"`
Y float64 `json:"y"`
}
201 changes: 201 additions & 0 deletions meta/instagram_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
package meta

import (
"testing"
"time"
)

func TestInstagramPostJSON(t *testing.T) {
tests := []struct {
desc string
data *InstagramPost
json string
}{
{
desc: "zero value",
data: &InstagramPost{},
json: `{"id":"","position":0}`,
},
{
desc: "all data",
// {
// "id": "1979320569926821011_11073382793",
// "user": {
// "id": "11073382793",
// "full_name": "Golang Client",
// "profile_picture": "https://scontent-sjc3-1.cdninstagram.com/vp/504ac2fa79adb1d412b31cab19be8d36/5CDDD9F1/t51.2885-19/44884218_345707102882519_2446069589734326272_n.jpg?_nc_ht=scontent-sjc3-1.cdninstagram.com",
// "username": "go_ig_test_0219"
// },
// "images": {
// "thumbnail": {
// "width": 150,
// "height": 150,
// "url": "https://scontent.cdninstagram.com/vp/fd0f484647ad37dc3caf0a2cdf37ca16/5CE59582/t51.2885-15/e35/c0.135.1080.1080/s150x150/50552544_116846169429307_872782777322498633_n.jpg?_nc_ht=scontent.cdninstagram.com"
// },
// "low_resolution": {
// "width": 320,
// "height": 400,
// "url": "https://scontent.cdninstagram.com/vp/0eda6589295b6fa43fd5cf2731afd691/5CF9331A/t51.2885-15/e35/p320x320/50552544_116846169429307_872782777322498633_n.jpg?_nc_ht=scontent.cdninstagram.com"
// },
// "standard_resolution": {
// "width": 640,
// "height": 800,
// "url": "https://scontent.cdninstagram.com/vp/bd6167c8e4469e16f2f6c900a62c51b9/5CF7EFF6/t51.2885-15/sh0.08/e35/p640x640/50552544_116846169429307_872782777322498633_n.jpg?_nc_ht=scontent.cdninstagram.com"
// }
// },
// "created_time": "1550173420",
// "caption": {
// "id": "18002756710177046",
// "text": "Photo post #0219test",
// "created_time": "1550173420",
// "from": {
// "id": "11073382793",
// "full_name": "Golang Client",
// "profile_picture": "https://scontent-sjc3-1.cdninstagram.com/vp/504ac2fa79adb1d412b31cab19be8d36/5CDDD9F1/t51.2885-19/44884218_345707102882519_2446069589734326272_n.jpg?_nc_ht=scontent-sjc3-1.cdninstagram.com",
// "username": "go_ig_test_0219"
// }
// },
// "user_has_liked": false,
// "likes": {
// "count": 1
// },
// "tags": [
// "0219test"
// ],
// "filter": "Crema",
// "comments": {
// "count": 2
// },
// "type": "image",
// "link": "https://www.instagram.com/p/Bt39ZJLHKSTFwXShw402xx8W9loUPHTyH5BsqY0/",
// "location": {
// "latitude": 37.8029,
// "longitude": -122.2721,
// "name": "Oakland, California",
// "id": 213051194
// },
// "attribution": null,
// "users_in_photo": [
// {
// "user": {
// "username": "rcarver"
// },
// "position": {
// "x": 0.57568438,
// "y": 0.7938808374
// }
// }
// ]
// }
data: &InstagramPost{
ID: "1979320569926821011_11073382793",
Type: InstagramImagePost,
URL: "https://www.instagram.com/p/Bt39ZJLHKSTFwXShw402xx8W9loUPHTyH5BsqY0/",
Multiple: true,
MediaType: InstagramImageMedia,
Position: 0,
UserID: "11073382793",
Username: "go_ig_test_0219",
UserFullName: "Golang Client",
Caption: "Photo post #0219test",
PostedAt: datePtr(2019, 2, 14, 7, 3, 32, 0, time.UTC),
Filter: "Crema",
Tags: []string{"0219test"},
Location: &InstagramLocation{
ID: "213051194",
Name: "Oakland, California",
Latitude: 37.8029,
Longitude: -122.2721,
},
TaggedUsers: []InstagramTaggedUser{
{
Username: "rcarver",
X: 0.57568438,
Y: 0.7938808374,
},
},
LikesCount: 1,
CommentsCount: 3,
},
json: `{
"id": "1979320569926821011_11073382793",
"type": "image",
"url": "https://www.instagram.com/p/Bt39ZJLHKSTFwXShw402xx8W9loUPHTyH5BsqY0/",
"multiple": true,
"media_type": "image",
"position": 0,
"user_id": "11073382793",
"username": "go_ig_test_0219",
"user_full_name": "Golang Client",
"caption": "Photo post #0219test",
"filter": "Crema",
"posted_at": "2019-02-14T07:03:32Z",
"tags": [
"0219test"
],
"location": {
"id": "213051194",
"name": "Oakland, California",
"latitude": 37.8029,
"longitude": -122.2721
},
"tagged_users": [
{
"username": "rcarver",
"x": 0.57568438,
"y": 0.7938808374
}
],
"likes_count": 1,
"comments_count": 3
}`,
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
assertJSONRoundtrip(t, tt.data, tt.json, &InstagramPost{})
})
}
}

func TestInstagramCommentJSON(t *testing.T) {
tests := []struct {
desc string
data *InstagramComment
json string
}{
{
desc: "zero value",
data: &InstagramComment{},
json: `{"id":"","text":""}`,
},
{
desc: "all data",
// {
// "id": "18034730665003447",
// "from": {
// "username": "rcarver"
// },
// "text": "That’s about right.",
// "created_time": "1550177777"
// },
data: &InstagramComment{
ID: "18034730665003447",
Username: "rcarver",
Text: "That’s about right.",
Date: datePtr(2019, 2, 14, 20, 56, 17, 0, time.UTC),
},
json: `{
"id": "18034730665003447",
"username": "rcarver",
"text": "That’s about right.",
"date": "2019-02-14T20:56:17Z"
}`,
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
assertJSONRoundtrip(t, tt.data, tt.json, &InstagramComment{})
})
}
}
3 changes: 2 additions & 1 deletion meta/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ type Image struct {

// SrcSpecific contains source-specific metadata.
type SrcSpecific struct {
Flickr *FlickrMedia `json:"flickr,omitempty"`
Flickr *FlickrMedia `json:"flickr,omitempty"`
Instagram *InstagramPost `json:"instagram,omitempty"`
}

func (m Content) isZero() bool {
Expand Down