github_watch.tcl 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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. putserv "PRIVMSG $github_watch::channel :\[\002${committer_name}\002\]: ${msg}"
  50. }
  51. proc github_watch::get_commits {} {
  52. # Fetch updates
  53. set token [http::geturl ${github_watch::url}${github_watch::user}/${github_watch::repo}/${github_watch::branch}]
  54. set data [http::data $token]
  55. set ncode [http::ncode $token]
  56. set status [http::status $token]
  57. http::cleanup $token
  58. if {$ncode != 200} {
  59. error "HTTP fetch failure: $ncode, $data"
  60. }
  61. set json_dict [json::json2dict $data]
  62. set commits_dict [lindex $json_dict 1]
  63. set commits [list]
  64. set old_last_id $github_watch::last_id
  65. # Take the first $max_commits or up to an id we have already seen and return
  66. for {set i 0} {$i < $github_watch::max_commits} {incr i} {
  67. set commit [lindex $commits_dict $i]
  68. if {[dict get $commit id] == $old_last_id} {
  69. break
  70. }
  71. if {$i == 0} {
  72. set github_watch::last_id [dict get $commit id]
  73. }
  74. lappend commits $commit
  75. }
  76. return [lreverse $commits]
  77. }
  78. proc github_watch::update {min hour day month year} {
  79. if {[catch {github_watch::get_commits} result]} {
  80. putlog "PRIVMSG $github_watch::channel :github watch: Error: $result"
  81. return
  82. }
  83. foreach commit $result {
  84. github_watch::output $commit
  85. }
  86. }
  87. github_watch::read_state
  88. putlog "github_watch.tcl loaded"