diff --git a/meta/instagram.go b/meta/instagram.go new file mode 100644 index 0000000..c7fadd7 --- /dev/null +++ b/meta/instagram.go @@ -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"` +} diff --git a/meta/instagram_test.go b/meta/instagram_test.go new file mode 100644 index 0000000..c140968 --- /dev/null +++ b/meta/instagram_test.go @@ -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{}) + }) + } +} diff --git a/meta/meta.go b/meta/meta.go index 0ee976d..2b68188 100644 --- a/meta/meta.go +++ b/meta/meta.go @@ -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 {