github_watch.tcl 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #
  2. # 2011-02-04
  3. #
  4. # Fetch commits from a github repo and output to IRC
  5. #
  6. # Better way to do this is to use service hooks, but for those repos where
  7. # one doesn't have admin access, this is an option.
  8. #
  9. # Reference: http://develop.github.com/p/commits.html
  10. #
  11. package require http
  12. package require json
  13. namespace eval github_watch {
  14. variable channel "#idiotbox"
  15. # every 1 minute
  16. bind time - "* * * * *" github_watch::update
  17. variable max_commits 5
  18. # Github user/repo to watch
  19. variable user "sveinfid"
  20. variable repo "Antix"
  21. variable branch "master"
  22. variable url "http://github.com/api/v2/json/commits/list/"
  23. variable state_file "scripts/github_watch.state"
  24. variable last_id
  25. variable timeout 10000
  26. bind evnt -|- "save" github_watch::write_state
  27. }
  28. proc github_watch::write_state {args} {
  29. set fid [open $github_watch::state_file w]
  30. puts $fid $github_watch::last_id
  31. close $fid
  32. }
  33. proc github_watch::read_state {} {
  34. if {[catch {open $github_watch::state_file r} fid]} {
  35. set github_watch::last_id nt
  36. return
  37. }
  38. set data [read -nonewline $fid]
  39. close $fid
  40. set raw [split $data \n]
  41. set github_watch::last_id [lindex $raw 0]
  42. }
  43. proc github_watch::output {commit} {
  44. set committer [dict get $commit committer]
  45. set committer_name [dict get $committer name]
  46. set msg [dict get $commit message]
  47. set url "http://github.com[dict get $commit url]"
  48. putserv "PRIVMSG $github_watch::channel :${committer_name}: ${msg} - ${url}"
  49. }
  50. proc github_watch::get_commits {} {
  51. # Fetch updates
  52. set token [http::geturl ${github_watch::url}${github_watch::user}/${github_watch::repo}/${github_watch::branch}]
  53. set data [http::data $token]
  54. set ncode [http::ncode $token]
  55. set status [http::status $token]
  56. http::cleanup $token
  57. if {$ncode != 200} {
  58. error "HTTP fetch failure: $ncode, $data"
  59. }
  60. set json_dict [json::json2dict $data]
  61. set commits_dict [lindex $json_dict 1]
  62. set commits [list]
  63. set old_last_id $github_watch::last_id
  64. # Take the first $max_commits or up to an id we have already seen and return
  65. for {set i 0} {$i < $github_watch::max_commits} {incr i} {
  66. set commit [lindex $commits_dict $i]
  67. if {[dict get $commit id] == $old_last_id} {
  68. break
  69. }
  70. if {$i == 0} {
  71. set github_watch::last_id [dict get $commit id]
  72. }
  73. lappend commits $commit
  74. }
  75. return [lreverse $commits]
  76. }
  77. proc github_watch::update {min hour day month year} {
  78. if {[catch {github_watch::get_commits} result]} {
  79. putserv "PRIVMSG $github_watch::channel :github watch: Error: $result"
  80. return
  81. }
  82. foreach commit $result {
  83. github_watch::output $commit
  84. }
  85. }
  86. github_watch::read_state
  87. putlog "github_watch.tcl loaded"