Last active
June 25, 2019 09:05
-
-
Save migrs/710a42062456a47bff1c59e40423a8b8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# <bitbar.title>GitHub Notifications</bitbar.title> | |
# <bitbar.version>v1.0.0</bitbar.version> | |
# <bitbar.author>mig</bitbar.author> | |
# <bitbar.author.github>migrs</bitbar.author.github> | |
# <bitbar.desc></bitbar.desc> | |
# <bitbar.image></bitbar.image> | |
# <bitbar.dependencies>ruby</bitbar.dependencies> | |
# <bitbar.abouturl>https://github.com/migrs</bitbar.abouturl> | |
require 'net/http' | |
require 'uri' | |
require 'zlib' | |
require 'base64' | |
require 'json' | |
require 'date' | |
begin | |
require 'dotenv' | |
Dotenv.load __dir__ + '/.env' | |
rescue LoadError | |
end | |
TOKEN = ENV['GITHUB_TOKEN'] || 'PUT-YOUR-GITHUB-TOKEN' | |
# icon = `curl -s https://github.com/favicon.ico | base64 -w 0` | |
# icon = Base64.strict_encode64 Zlib::Deflate.deflate icon, Zlib::BEST_COMPRESSION | |
if RUBY_PLATFORM =~ /linux/ | |
icon = 'eNrtWEtb6joU/UEMytH6CYM7SNr0ART6oEiYaQ+0PBQv3GPBX3/3TuVVaWlRPBMyqIYkKyv7nRBCKCEmYfAlhMF/ZE4dQhohdBWCXwp/SRN/ZLIG/XkyU4yTzfhH00iZRpnLbnmXrWxNDeUOC3dDalyzYdTVWgzG26/F8BxfayBet8ZWln/v4G/T1Jywp7kjSXP9vrSCHWQ/n98S9+/+QS5GRJxETp9aG/eru35Pk2oCH+b7i/gYv6kYpyF3W0TuqLPYVmOJ4nnN1PnbFPaza3t8Bb6vUc/+kLzDVGKrjiRht4LshlXQWksioanUQabqZA8Uf2So1dZiD+9QHl4V8B8CjTo9KQa8EfBbGfeqU3U78SkFVNtsMkd5vezheyxqPoJ8ujf78oF+Ny5uKij/Lj1cfxNZXc3mCX+QbU3MNEm5ZiLfVcJX4GH/NumDvjqMnNOQj5ycN8GD/m207d8JfTslzg+6NgS/cHve2wj8o2nu9AeY6nsJULQfRg70D3gd8EU5pT++WySU1kwhWeKbbC3m760XeBt/0prOxj+82EH7RGiFgn21b6npae0Q1ne58CfcynDEUcX8RJ5gCV7KqYmK9rCK0vZcqI/xR98dLd0s3G9cAk/Mz8ZLyV+VYf9OP/EPOL9t4vnXSd/qsrsAvbpCru2n2nwbRdin/OZ/604Qz5pxPDQi2S2x6klfLYOG4kzV8MKSoPzB8Ky+thp7aN81lz9oUhuMlrCi6/VO9UGLRu9axPnMjQND+UYRggwaJAD8MUH8Ck354xoSHikmJDF/P34gHpxXN01ImqWTyid9AV6/SrPjR3O9XNBiVHF+/Xj8Af3UzUc9mg9L56uIP7UQr8J3eKi/VgjyjaowPhgAvm7c9Xo9Xy1q35oU58fLCnCOlm/F8OZwtiquf97hxVynUeOrpoR4lSLxvcJRvr9zoKbgm4bQt3uwnr84H/rzCEf7ChDvjoB/zZ7Rn+nJfAH+Q80S+Q3tgQk+mf5pstR6JuzVgL0aaP+dZRof+L52TslThwLXoWXzMfI5Zu/xNPHHzfzJH+g/uq6Inxhf7Mzz1zwMAkq+P43L1Au7+JDEx0N5NpzD/WUZ5fV4zB7kSJwX+L9qKG92yv8Vc2yGKP/firYKBkOh32UxvquATxP7emmsg7aI56fqJcHPfLfeLe2r/oVBlCCeIeRTO8F3Df2FivLsnbR3EZ8uk//8nq6TAvvPMD8Opm6uPPn6TZLgTnXRfK23gly++oAB30njxHmCSxdZmE/cE/61FvUDyzlPAL7AL01V5P+j9cVWXpMQx+vZ+l//YP2KfIaZ8dX2k3osa7wt/xxT9C9rnqX/fg3ttT3NtI+6fWF/OrRXLmfqdzJA/37LsWeRT50Lk1TAVml+vNJbaK/j3ol4enNxeYK8uJvv/zOsP/wgv16wnYHuTkeXsc8l1EIW+tPiRLw0RP0u8inL59u7TKrCesvLzz/9mrdcNGO+tedZjr2CTAdWfBGq4n6SL89x/6A++6iX68fjL9T/4a8j9gX1Q8h15d/s+i+JH1jvPsMdfMjS/kkhv6xZdvwBPubnSxvyV7Lylf6QyB8fdSji35gYj1+29aKE9jbCeoLje5duId7IFfqj23zzH44/KQf6HPhRpjyV/PvzxDxWr/wCPL2J97/JsnR9fKR/j/GnifF+0j6a7xM+ufnCFO/3k8l38Dmnr3csYY+F308U+S/whf0iHrTC8vkY5JtlD9/bF/XdUf855/1HyYkPZ/Ori/uxmX1/Pq9t41kSf9nZfPE9Tm8Exe3xCy3JbyIfb+oHUe9AfbZ539ur18b7+XsBa/Xrs/K1Xdu1Xdtfb//8D4zMcxE=' | |
icon = Zlib::Inflate.inflate Base64.decode64(icon) | |
else | |
icon = nil | |
end | |
def li text = '---', args = {} | |
args = args.dup | |
fold = args.delete(:fold) ? '--' : '' | |
args_set = (alt = args.delete(:alt)) ? [args, args.merge(alt).merge(alternate: true)] : [args] | |
args_set.each do |_| | |
puts fold + _.delete(:prepend).to_s + (_.delete(:text) || text).to_s + _.delete(:append).to_s + | |
(_.empty? ? '' : ' | ' + _.select {|k,v|!v.nil?}.map {|k,v| "#{k}=#{v}"}.join(' ')) | |
end | |
end | |
def github_api path, params = {} | |
headers = { 'Authorization' => "token #{TOKEN}", 'Accept' => 'application/json' } | |
uri = URI "https://api.github.com/#{path}" | |
uri.query = URI.encode_www_form params unless params.empty? | |
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) {|_|_.get uri.request_uri, headers} | |
raise "error #{res.code} #{res.message}" if res.code != '200' | |
JSON.parse res.body, symbolize_names: true | |
end | |
def icon type | |
image = 'iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAYAAAAmlE46AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAA' | |
case type | |
when 'PullRequest' | |
image += 'TJJREFUKJG9krFOAlEQRe/MLpqHnd/ATyBWsLWF+hcLPYXibvwCE/gLC2MNVrD7AbbGnpjYboBlro2QXWATabzVy5x338ydPKBC4awTVTEA8Huz9i1FI5gZBINh6+0lnHUiEXkAUGmWMGm/c7Fues4pLU9IPv+aAABm9i2qT6Pm+BECbuoqpnZWW4lmmRLG3ZdV9VyAOEyD+1JdVO4yqX+ua7UPofRHrUlEMgaA4cVYALkEACF6e/N2k4DdJCh1Ky7nENftyVACo9akcjElox3I9yfjsdoaVfFPHbtpcG2GOUy/wjS42r0QTjs3ZpibYV7kPmkxVuuGOKfIl1MAr0WjqMRcrBqec8oCVwDwnNOFnwugezkJ4+ZnFbkPeANanpwsAQr7+2m8Qab1FKcAeYgfqR/3P4pMOYR15QAAAABJRU5ErkJggg==' | |
when 'RepositoryInvitation' | |
image += 'iVBORw0KGgoAAAANSUhEUgAAAA4AAAAKCAYAAACE2W/HAAAAAXNSR0IArs4c6QAAAM1JREFUKBWVkD0OQUEUhcdv/ASJn55SyxLoVBJq8tZjBRQsgkZiAQoqOiQ2oFc935nMvLxEXsRJPufOufe+kTHGmBeEf3Jg3i4t8IwOP6QZzeoi+3PFt1BRkKAq+Q4uEKbdUA+/wxm6LoubshPcoO8b9lp3GOMPGPomPoInqOcV/VUfyKfwhsChegJxfS3O6R5hALpFqFY2A69osUyygT3UQOpAWwVSpt4aShAt6lWXkIUk5WiswL5qiqIODdBz6+ZirM67cwFvulwfaH0AC7M1lHL62U4AAAAASUVORK5CYII='; | |
when 'Issue' | |
image += 'ZxJREFUKJGdkjFoU2EUhb97k9jNRzEFoWvJVHXoZCqIaQaH7JaUbtpi2zc4ORWJYKGTYJLBroFaiGPo0hBwyAOhU51Cd8EOOid53uugL4SnkOK3/dx7OPccfvhPZPqxHZUWc0gIUjFs6c/CJdDBtN580P36lzCM1jZ+mr9HuFKkJfgXABO9i/mmqOTd7VlztXcyEYbR2oabtFx5kx+Oa7VHn+LpS7bOV3K5UfBaTF+6WLW52juR7ai0mDEGovq2WezuJ8t7UdkBGsXu5KqdfvlQhOeeGRc0h4QIV/nhuDarkIVgft+xHxJnQwWpKNJKn/cvasvtkcCxuFTUsKWkiOsgrhcoBb2uIE1W4NKRO8DH6cF0KSnLewYDBTqGb26dr+Sm53tR2ZNmE8LTx3O4V9XpKKZ1FV24MZyf2aoH8YE5garXBWC3X1oX12NXO8zfvPWqttwepZ08iA9wXqDypFE8a09y7PZL64geCXx37IO4XiSZcK/+dso8bRTP2pD65DufH96WOBuKSwWlAGD4QJ2Oqtff3e99mxVnJr8AXSGi02ni0+YAAAAASUVORK5CYII=' | |
when 'Commit' | |
image += 'HhJREFUKJHl0LEKwkAQBNCH3yIaf05S+VUqmh8ykFoUYn8WbnEc8a7XgYVlmNkdhv/EDgNmvHDFtmXq8ETCiFvsD2xqxksI9xnXB3cqxamYceHgVOpWC6JUi/QNQxj7jDsEd6wZ83KmLOId69bXzqekOeas0eiv4g3q4SY7NY1R2gAAAABJRU5ErkJggg==' | |
when 'Release' | |
image += 'JdJREFUKJGl0DsKwkAUBdDTRgvFHbgmNyLY+QWzKxM/kK2kSKc70MIIQ0ziqBceA/dxinn8mSkKVMGUmH+CBWaNboQjdn2wqt97Pa8kNd5+C0O86YNdSZC34RLjCJxhHZYLXDCIxKuwTHGOwBNcm2WKUw9OcMCybZl6XjHpQOs30cB5gKNQiDPPP0WjV/a4aVwxNsNfUGce7P8k4XgVPSYAAAAASUVORK5CYII=' | |
end | |
end | |
def li_issues title, params, q | |
issues = github_api "search/issues?q=#{q.map {|k,v|"#{k}:#{v}"}.join('+')}" | |
return unless issues[:total_count] > 0 | |
li "#{title} (#{issues[:total_count]})", params | |
issues[:items].each do |_| | |
updated_at = DateTime.parse(_[:updated_at]).new_offset(Rational(9, 24)).strftime('%Y-%m-%d %H:%M') | |
author = "by #{_[:user][:login]}" | |
li "#{_[:title]} #{author}", href: _[:html_url], image: icon('PullRequest'), | |
fold: true, alt: { prepend: "#{updated_at} | " } | |
end | |
end | |
begin | |
now = Time.now | |
notifications = github_api 'notifications' | |
user = github_api 'user' | |
li '●', color: (notifications.empty? ? '#7d7d7d' : '#4078C0'), image: icon, imageWidth: 18 | |
li | |
li "Last updated: #{now.strftime('%Y-%m-%d %H:%M')}", color: '#aaaa99', refresh: true | |
li_issues 'Pull requests', { color: "#58BE89" }, author: user[:login], type: 'pr', state: 'open' | |
li_issues 'Awaiting reviews', { color: "#ee8888" }, :'review-requested' => user[:login], type: 'pr', state: 'open' | |
li | |
if notifications.empty? | |
li 'No Notifications', href: 'https://github.com/notifications', color: '#66aaff' | |
else | |
li "Notifications (#{notifications.count})", href: 'https://github.com/notifications', color: '#66aaff' | |
end | |
notifications.group_by { |_|_[:repository][:id] }.each do |_, notifications| | |
repo = notifications.first[:repository] | |
li repo[:full_name], color: '#888888', href: repo[:html_url] | |
notifications.group_by {|_|_[:reason]}.each do |_, notifications| | |
li "➠ #{_.capitalize.sub(/_/, ' ')}", color: '#33BFDB' | |
notifications.each do |_| | |
updated_at = DateTime.parse(_[:updated_at]).new_offset(Rational(9, 24)).strftime('%m-%d %H:%M') | |
li _[:subject][:title], image: icon(_[:subject][:type]), | |
href: _[:subject][:url].sub(/(pull|commit)s/, '\1').gsub(%r{api\.|api/v3/|repos/}, ''), refresh: true, | |
alt: { prepend: "#{updated_at} | " } | |
end | |
end | |
end | |
rescue | |
li '!', color: '#ECB935', image: icon, imageWidth: 18 | |
li | |
li "Exception: #{$!}", refresh: true | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment