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()
}
|