Skip to content

Instantly share code, notes, and snippets.

@migrs
Last active April 19, 2018 05:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save migrs/d15ebcbee1cdf0c21a5efffb9f7498f3 to your computer and use it in GitHub Desktop.
Save migrs/d15ebcbee1cdf0c21a5efffb9f7498f3 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
# <bitbar.title>Redmine My Issues</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 File.dirname(__FILE__) + '/.env'
rescue LoadError
end
TOKEN = ENV["REDMINE_TOKEN"] || 'PUT-YOUR-REDMINE-TOKEN'
REDMINE_URL = ENV["REDMINE_URL"] || 'https://redmine.your-company.com'
MENU_COLOR = ENV['REDMINE_MENU_COLOR'] || '#bb2200'
ISSUES_URL = "#{REDMINE_URL}/issues.json?key=#{TOKEN}&limit=100&status_id=open&assigned_to_id=me"
# icon = `curl -s #{REDMINE_URL}/favicon.ico | base64 -w 0`
# icon = Base64.strict_encode64 Zlib::Deflate.deflate icon, Zlib::BEST_COMPRESSION
# if RUBY_PLATFORM =~ /linux/
# icon = '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'
# icon = Zlib::Inflate.inflate(Base64.decode64(icon))
# end
icon = nil
unfolded_status = ['Open', 'Ready', 'In Progress', 'Feedback']
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
begin
now = Time.now
uri = URI ISSUES_URL
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) {|_|_.get uri.request_uri }
raise "error #{res.code} #{res.message}" if res.code != '200'
result = JSON.parse res.body, symbolize_names: true
li "● #{result[:total_count]}", color: (result[:total_count] == 0 ? '#7d7d7d' : MENU_COLOR), image: icon, imageWidth: 18
li
#li "Last updated: #{now.strftime('%Y-%m-%d %H:%M')}", color: '#aaaa99', refresh: true
li "Redmine Tasks (#{result[:total_count]})", color: '#58BE89', href: "#{REDMINE_URL}/issues?utf8=%E2%9C%93&set_filter=1&f[]=status_id&op[status_id]=o&f[]=assigned_to_id&op[assigned_to_id]=%3D&v[assigned_to_id][]=me"
result[:issues].group_by {|_|_[:project][:id]}.each do |_, issues|
li
project = issues.first[:project]
li "#{project[:name]} (#{issues.count})", color: '#888888'
issues.group_by {|_|_[:status][:id]}.each do |_, issues|
status = issues.first[:status]
li "➠ #{status[:name]} (#{issues.count})", color: '#33BFDB'
fold = !unfolded_status.include?(status[:name])
issues.group_by {|_|_[:tracker][:id]}.each do |_, issues|
tracker = issues.first[:tracker]
color = nil # case tracker[:name] when 'Task' then '#ffffcc' when 'Defect' then '#ffcccc' else nil end
issues.each do |_|
priority = case _[:priority][:name] when 'High' then '#ff6666' when 'Low' then '#66ffff' else nil end
issue_id = priority ? "##{_[:id]} #{_[:priority][:name]}" : "##{_[:id]}"
title = "#{issue_id} #{_[:subject]} by #{_[:author][:name]}"
updated_on = DateTime.parse(_[:updated_on]).new_offset(Rational(9, 24)).strftime('%m-%d %H:%M')
li title, href: "#{REDMINE_URL}/issues/#{_[:id]}", color: color, fold: fold, alt: { prepend: "#{updated_on} | " }
end
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