File: tsg.go

package info (click to toggle)
golang-github-ajstarks-svgo 2012-01-27-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 2,720 kB
  • sloc: xml: 80; makefile: 31; sh: 29
file content (124 lines) | stat: -rw-r--r-- 2,485 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// tsg -- twitter search grid
//
// Anthony Starks (ajstarks@gmail.com)
//

package main

import (
	"encoding/xml"
	"flag"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"

	"github.com/ajstarks/svgo"
)

var canvas = svg.New(os.Stdout)

// Atom feed structure
type Feed struct {
	XMLName xml.Name `xml:"http://www.w3.org/2005/Atom feed"`
	Entry   []Entry
}

type Entry struct {
	Link   []Link
	Title  string
	Author Person
}

type Link struct {
	Rel  string `xml:"attr"`
	Href string `xml:"attr"`
}

type Person struct {
	Name string
}

type Text struct {
	Type string `xml:"attr"`
	Body string `xml:"chardata"`
}

var (
	nresults = flag.Int("n", 100, "Maximum results (up to 100)")
	since    = flag.String("d", "", "Search since this date (YYYY-MM-DD)")
)

const (
	queryURI = "http://search.twitter.com/search.atom?q=%s&since=%s&rpp=%d"
	textfmt  = "font-family:Calibri,Lucida,sans;fill:gray;text-anchor:middle;font-size:48px"
	imw      = 48
	imh      = 48
)

// ts dereferences the twitter search URL and reads the XML (Atom) response
func ts(s string, date string, n int) {

	r, err := http.Get(fmt.Sprintf(queryURI, url.QueryEscape(s), date, n))
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		return
	}
	if r.StatusCode == http.StatusOK {
		readatom(r.Body)
	} else {
		fmt.Fprintf(os.Stderr,
			"Twitter is unable to search for %s (%s)\n", s, r.Status)
	}
	r.Body.Close()
}

// readatom unmarshals the twitter search response and formats the results into a grid
func readatom(r io.Reader) {
	var twitter Feed
	err := xml.NewDecoder(r).Decode(&twitter)
	if err == nil {
		tgrid(twitter, 25, 25, 50, 50, 10)
	} else {
		fmt.Fprintf(os.Stderr, "Unable to parse the Atom feed (%v)\n", err)
	}
}

// tgrid makes a clickable grid of tweets from the Atom feed
func tgrid(t Feed, x, y, w, h, nc int) {
	var slink, imlink string
	xp := x
	for i, entry := range t.Entry {
		for _, link := range entry.Link {
			switch link.Rel {
			case "alternate":
				slink = link.Href
			case "image":
				imlink = link.Href
			}
		}
		if i%nc == 0 && i > 0 {
			xp = x
			y += h
		}
		canvas.Link(slink, slink)
		canvas.Image(xp, y, imw, imh, imlink)
		canvas.LinkEnd()
		xp += w
	}
}

// for every non-flag argument, make a twitter search grid
func main() {
	flag.Parse()
	width := 550
	height := 700
	canvas.Start(width, height)
	for _, s := range flag.Args() {
		canvas.Title("Twitter search for " + s)
		ts(s, *since, *nresults)
		canvas.Text(width/2, height-50, s, textfmt)
	}
	canvas.End()
}