main.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "net/url"
  6. "os"
  7. "os/signal"
  8. "strconv"
  9. "strings"
  10. "syscall"
  11. "time"
  12. "github.com/ChimeraCoder/anaconda"
  13. "github.com/cryptix/go/logging"
  14. "github.com/jinzhu/configor"
  15. "github.com/kr/pretty"
  16. "github.com/pkg/errors"
  17. )
  18. var (
  19. log logging.Interface
  20. check = logging.CheckFatal
  21. )
  22. var cfgFile = flag.String("config", "my.cfg", "which config file to use")
  23. type Config struct {
  24. Anaconda struct {
  25. ConsumerKey string
  26. ConsumerSecret string
  27. AccessToken string
  28. AccessTokenSecret string
  29. }
  30. Config struct {
  31. Email string
  32. UpdateInterval string
  33. Debug bool
  34. Update string
  35. Lists string
  36. }
  37. }
  38. func main() {
  39. logging.SetupLogging(nil)
  40. log = logging.Logger("twitClone")
  41. // setup config
  42. var cfg Config
  43. check(configor.Load(&cfg, *cfgFile))
  44. pretty.Println(cfg)
  45. // setup anaconda
  46. anaconda.SetConsumerKey(cfg.Anaconda.ConsumerKey)
  47. anaconda.SetConsumerSecret(cfg.Anaconda.ConsumerSecret)
  48. api := anaconda.NewTwitterApi(cfg.Anaconda.AccessToken, cfg.Anaconda.AccessTokenSecret)
  49. //api.SetLogger(anaconda.BasicLogger)
  50. ok, err := api.VerifyCredentials()
  51. check(err)
  52. log.Log("event", "info", "login", ok)
  53. ud, err := time.ParseDuration(cfg.Config.Update)
  54. check(err)
  55. // Mechanical stuff
  56. //rand.Seed(time.Now().UnixNano())
  57. //root := context.Background()
  58. errc := make(chan error)
  59. go func() {
  60. errc <- interrupt()
  61. }()
  62. for _, l := range strings.Split(cfg.Config.Lists, ",") {
  63. id, err := strconv.ParseInt(l, 10, 64)
  64. check(err)
  65. list, err := api.GetList(id, url.Values{})
  66. check(err)
  67. pretty.Println(list)
  68. go func(l anaconda.List) {
  69. c := time.Tick(ud)
  70. for _ = range c {
  71. tweets, err := api.GetListTweets(list.Id, true, url.Values{})
  72. check(errors.Wrapf(err, "faild to get tweets for list %s", list.Name))
  73. log.Log("event", "new tweets", "count", len(tweets))
  74. if len(tweets) > 0 {
  75. t := tweets[0]
  76. log.Log("event", "info", "type", "tweet-onlist", "list", list.Name,
  77. "user", t.User.ScreenName,
  78. "userid", t.User.Id,
  79. "tweetid", t.Id,
  80. "text", t.Text)
  81. }
  82. }
  83. }(list)
  84. }
  85. // Pull: my feed
  86. //go func() {
  87. //dur, err := time.ParseDuration(cfg.Config.UpdateInterval)
  88. //check(err)
  89. // t := time.Tick(dur)
  90. // for now := range t {
  91. // // pulls MY timeline
  92. // tweets, err := api.GetUserTimeline(nil)
  93. // if err != nil {
  94. // errc <- err
  95. // return
  96. // }
  97. // check(err)
  98. // for _, tweet := range tweets {
  99. // log.WithFields(map[string]interface{}{
  100. // "user": tweet.User.ScreenName,
  101. // "userid": tweet.User.Id,
  102. // "tweetid": tweet.Id,
  103. // }).Infof("[tweet] %s", tweet.Text)
  104. // }
  105. // log.WithFields(map[string]interface{}{
  106. // "cnt": len(tweets),
  107. // "took": time.Since(now),
  108. // }).Info("cycle done")
  109. // }
  110. //}()
  111. // Stream: my timeline
  112. //go cloneStream("site", api.SiteStream(nil), errc)
  113. //go cloneStream("user", api.UserStream(nil), errc)
  114. check(<-errc)
  115. }
  116. func cloneStream(name string, s *anaconda.Stream, errc chan<- error) {
  117. for msg := range s.C {
  118. switch t := msg.(type) {
  119. case anaconda.FriendsList:
  120. log.Log("event", "stats", "friends", len(t))
  121. case anaconda.Tweet:
  122. log.Log("event", "info", "type", "tweet",
  123. "user", t.User.ScreenName,
  124. "userid", t.User.Id,
  125. "tweetid", t.Id,
  126. "text", t.Text)
  127. case anaconda.EventTweet:
  128. var tweet anaconda.Tweet = *t.TargetObject
  129. log.Log("event", "info", "type", "eventTweet",
  130. "user", tweet.User.ScreenName,
  131. "userid", tweet.User.Id,
  132. "tweetid", tweet.Id,
  133. "text", tweet.Text)
  134. case anaconda.StatusDeletionNotice:
  135. log.Log("event", "info", "type", "deleted tweet",
  136. "userid", t.UserId,
  137. "tweetid", t.Id)
  138. default:
  139. log.Log("event", "error", "msg", "uncased msg", "type", fmt.Sprintf("%T %+v", t, msg))
  140. }
  141. }
  142. }
  143. func interrupt() error {
  144. c := make(chan os.Signal)
  145. signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
  146. return fmt.Errorf("%s", <-c)
  147. }