twimgarc/main.go

166 lines
3.8 KiB
Go

package main
import (
"fmt"
"io"
"log"
"net/http"
"os"
"strings"
"time"
"github.com/dghubble/go-twitter/twitter"
"github.com/dghubble/oauth1"
)
const AppName = "twimgarc"
var appConfig *AppConfig
func main() {
var err error
appConfig, err = NewAppConfig(os.Args)
if err != nil {
log.Fatal(err)
}
config := oauth1.NewConfig(appConfig.ApiToken, appConfig.ApiSecret)
token := oauth1.NewToken(appConfig.AppToken, appConfig.AppSecret)
httpClient := config.Client(oauth1.NoContext, token)
sleepTime := time.Minute
for {
PrintIfVerbose(time.Now().Format("20060102T150405"), ": Start\n")
err = ProcessTimeline(httpClient)
if err != nil {
// Backoff
sleepTime = sleepTime * 2
}
PrintIfVerbose(time.Now().Format("20060102T150405"), ": Done\n")
time.Sleep(sleepTime)
if appConfig.ForceDownload {
PrintIfVerbose("'Force' flag set. Exiting.\n")
break
}
}
}
// Doesn't work yet...
func WatchStream(httpClient *http.Client) {
// Twitter client
client := twitter.NewClient(httpClient)
params := &twitter.StreamUserParams{
With: "followings",
StallWarnings: twitter.Bool(false),
}
stream, err := client.Streams.User(params)
if err != nil {
log.Fatal(err)
}
for message := range stream.Messages {
fmt.Println(message)
}
fmt.Println("Message Channel Closed")
}
func ProcessTimeline(httpClient *http.Client) error {
// Twitter client
client := twitter.NewClient(httpClient)
// Home Timeline (last 5 entries)
tweets, _, err := client.Timelines.HomeTimeline(&twitter.HomeTimelineParams{Count: 5})
if err != nil {
return err
}
for _, t := range tweets {
for _, m := range t.Entities.Media {
var filenamePts []string
txtPts := strings.Fields(t.Text)
var subFolder string
for _, v := range txtPts {
if strings.HasPrefix(v, "http") {
break
}
if v[0] == '#' {
if subFolder == "" {
subFolder = v[1:]
}
} else {
filenamePts = append(filenamePts, v)
}
}
filename := strings.Join(filenamePts, "_") + ".jpg"
create, err := t.CreatedAtTime()
if err != nil {
create = time.Now()
}
filename = subFolder + "/" + create.Format("20060102T150405") + "_" + filename
if ImageNeedsDownload(filename) || appConfig.ForceDownload {
err = DownloadImage(httpClient, m.MediaURLHttps, filename)
if err != nil {
PrintIfVerbose("Error downloading image (", m.MediaURLHttps, ")", err.Error(), "\n")
}
}
}
}
return nil
}
func ImageNeedsDownload(filename string) bool {
exist, err := FileExists(appConfig.GetFilePath(filename))
if err != nil {
return false
}
return !exist
}
func DownloadImage(httpClient *http.Client, url, filename string) error {
pts := strings.FieldsFunc(filename, func(c rune) bool { return c == '/' })
if len(pts) > 1 {
err := CreateDirIfNotExist(appConfig.GetFilePath(pts[0]))
if err != nil {
fmt.Println(err.Error())
return err
}
}
fmt.Println("Downloading ", url, " -> ", filename, "...")
imgResp, err := httpClient.Get(url)
if err != nil {
PrintIfVerbose(err.Error(), "\n")
return err
}
defer imgResp.Body.Close()
file, err := os.Create(appConfig.GetFilePath(filename))
if err != nil {
PrintIfVerbose(err.Error(), "\n")
return err
}
defer file.Close()
_, err = io.Copy(file, imgResp.Body)
if err != nil {
fmt.Println(err.Error(), "\n")
} else {
fmt.Println("Done\n")
}
return err
}
func PrintIfVerbose(val ...string) {
if appConfig.Verbose {
for _, v := range val {
fmt.Print(v)
}
}
}
func PrintUsageAndExit() {
fmt.Println(AppName + " - Download Images from a Twitter Stream")
fmt.Println(" -count,-c=<num> Pull the last <num> tweets")
fmt.Println(" -force,-f Download images even if the file already exists")
fmt.Println(" -help ,-h View this message")
fmt.Println(" -verbose ,-v Be chatty")
fmt.Println()
os.Exit(0)
}