Created
January 14, 2017 18:21
-
-
Save thebitguru/4ba790044b3202e2bc58ca0ce9123097 to your computer and use it in GitHub Desktop.
A simple go program to download all the high resolution pictures from your facebook albums.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
/* | |
* A simple go program to download all the high resolution pictures from your facebook albums. | |
* | |
* To run this: | |
* 1. Go to https://developers.facebook.com/tools/explorer/?method=GET&path=me&version=v2.8 | |
* 2. Get an Access Token: Get Token > Get User Access Token > Check "user_photos" | |
* 3. Paste in the app. | |
*/ | |
import ( | |
"encoding/json" | |
"fmt" | |
"io" | |
"log" | |
"net/http" | |
"net/url" | |
"os" | |
"path/filepath" | |
"unicode/utf8" | |
"github.com/kennygrant/sanitize" | |
fb "github.com/huandu/facebook" | |
) | |
var logger *log.Logger | |
func main() { | |
logger = log.New(os.Stdout, "LOG: ", log.Ldate) | |
// Get access token manually from https://developers.facebook.com/tools/explorer/?method=GET&path=me&version=v2.8 | |
var accessToken string | |
fmt.Println("Please go to the following URL and to get the access token") | |
fmt.Println("\thttps://developers.facebook.com/tools/explorer/?method=GET&path=me&version=v2.8") | |
fmt.Printf("\tGet Token (button) > Get User Access Token > Check 'user_photos'\n\n") | |
fmt.Print("Paste the access token: ") | |
fmt.Scanln(&accessToken) | |
var fbApp = fb.New("", "") | |
session := fbApp.Session(accessToken) | |
res, err := session.Get("/me", nil) | |
if err != nil { | |
logger.Fatal(err) | |
} | |
fmt.Println("Albums for", res["name"]) | |
res, _ = session.Get("/me/albums", nil) | |
paging, _ := res.Paging(session) | |
for { | |
items := paging.Data() | |
for _, album := range items { | |
// Create directory and process album | |
os.Mkdir(album.Get("name").(string), os.ModePerm) | |
processAlbum(session, album) | |
} | |
noMore, _ := paging.Next() | |
if noMore { | |
break | |
} | |
} | |
} | |
func processAlbum(session *fb.Session, album fb.Result) { | |
fmt.Printf("%s: %s\n", album.GetField("id"), album.GetField("name")) | |
albumName := album.GetField("name").(string) | |
// Get the photos in the album | |
res, _ := session.Get(fmt.Sprintf("/%s/photos", album.GetField("id")), fb.Params{ | |
"fields": "name,images", | |
}) | |
paging, _ := res.Paging(session) | |
for { | |
items := paging.Data() | |
for _, photo := range items { | |
// Find the largest image. | |
var largest fb.Result | |
var lastLargestHeight int64 | |
var lastLargestWidth int64 | |
var images []fb.Result | |
photo.DecodeField("images", &images) | |
for _, imageSpecs := range images { | |
height, _ := imageSpecs["height"].(json.Number).Int64() | |
width, _ := imageSpecs["width"].(json.Number).Int64() | |
// fmt.Printf("\t%d x %d\n", height, width) | |
if height > lastLargestHeight { | |
lastLargestHeight = height | |
largest = imageSpecs | |
} | |
if width > lastLargestWidth { | |
lastLargestWidth = width | |
largest = imageSpecs | |
} | |
} | |
// fmt.Printf("Final: %s\n\n", largest) | |
// Download the image | |
photoSource := largest["source"].(string) | |
photoURL, _ := url.Parse(photoSource) | |
fmt.Printf("\t\t%s: %s\n", | |
photo.GetField("id"), photo.GetField("name")) | |
extension := filepath.Ext(photoURL.Path) | |
response, err := http.Get(photoSource) | |
if err != nil { | |
logger.Panic(err) | |
} | |
defer response.Body.Close() | |
var filename string | |
if photo.Get("name") == nil { | |
filename = photo.GetField("id").(string) | |
} else { | |
filename = photo.GetField("name").(string) | |
} | |
if utf8.RuneCountInString(filename) > 100 { | |
filename = filename[:100] | |
} | |
filename = sanitize.BaseName(filename) | |
file, err := os.Create(filepath.Join(albumName, filename+extension)) | |
if err != nil { | |
logger.Panic(err) | |
} | |
_, err = io.Copy(file, response.Body) | |
if err != nil { | |
logger.Panic(err) | |
} | |
file.Close() | |
} | |
noMore, _ := paging.Next() | |
if noMore { | |
break | |
} | |
} | |
} |
It was failing for some photos on macOS, so I modified it slightly 🙌
@heathmedia you should be able to simply run go run facebook-photo-download.go
if I'm not mistaken, and it should then fetch the dependencies automatically.
I made an edit to the gist, it was failing for album names with invalid characters (e.g. '/') in it. Using the sanitize.BaseName() method on the album name, as was done on the file name, fixes this issue: https://gist.github.com/BenSchZA/e5c7acb964f5d2d7ff9f0008a1156434/revisions
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you, this is wonderful. This will help me finally delete my FB account.
One question: how does one run this locally and pull in dependencies automatically? I had to run
go get DEPENDENCY_URL
for the sanitize and facebook libraries. It would throw errors if I simply tried to rungo build facebook-photo-download.go
Disclosure: this is my first time using Go.