Created
December 9, 2020 17:11
-
-
Save crcastle/a97a7cbe84ba8f84e16952bc0a153b1d to your computer and use it in GitHub Desktop.
My BitBar enabled plugins - heroku, homebrew, github, and googlecal
This file contains hidden or 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
#!/bin/bash | |
# <bitbar.title>Homebrew Updates</bitbar.title> | |
# <bitbar.author>killercup</bitbar.author> | |
# <bitbar.author.github>killercup</bitbar.author.github> | |
# <bitbar.desc>List available updates from Homebrew (OS X)</bitbar.desc> | |
exit_with_error() { | |
echo "err | color=red"; | |
exit 1; | |
} | |
/usr/local/bin/brew update > /dev/null || exit_with_error; | |
PINNED=$(/usr/local/bin/brew list --pinned); | |
OUTDATED=$(/usr/local/bin/brew outdated --quiet); | |
UPDATES=$(comm -13 <(for X in "${PINNED[@]}"; do echo "${X}"; done) <(for X in "${OUTDATED[@]}"; do echo "${X}"; done)) | |
UPDATE_COUNT=$(echo "$UPDATES" | grep -c '[^[:space:]]'); | |
echo "🍺$UPDATE_COUNT | dropdown=false" | |
echo "---"; | |
if [ -n "$UPDATES" ]; then | |
echo "Upgrade all | bash=/usr/local/bin/brew param1=upgrade terminal=false refresh=true" | |
echo "$UPDATES" | awk '{print $0 " | terminal=false refresh=true bash=/usr/local/bin/brew param1=upgrade param2=" $1}' | |
fi |
This file contains hidden or 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 python | |
# -*- coding: utf-8 -*- | |
# <bitbar.title>GitHub Notifications</bitbar.title> | |
# <bitbar.version>v3.0.2</bitbar.version> | |
# <bitbar.author>Matt Sephton, Keith Cirkel, John Flesch</bitbar.author> | |
# <bitbar.author.github>flesch</bitbar.author.github> | |
# <bitbar.desc>GitHub (and GitHub:Enterprise) notifications in your menu bar!</bitbar.desc> | |
# <bitbar.image>https://i.imgur.com/hW7dw9E.png</bitbar.image> | |
# <bitbar.dependencies>python</bitbar.dependencies> | |
import json | |
import urllib2 | |
import os | |
import sys | |
import re | |
from itertools import groupby | |
# GitHub.com | |
github_api_key = os.getenv( 'GITHUB_TOKEN', 'Enter your GitHub Personal Access Token here...' ) | |
# GitHub:Enterprise (optional) | |
enterprise_api_key = os.getenv( 'GITHUB_ENTERPRISE_TOKEN', 'Enter your GitHub:Enterprise Personal Access Token here...' ) | |
enterprise_api_url = os.getenv( 'GITHUB_ENTERPRISE_API', 'https://github.example.com/api/v3' ) | |
active = '#4078C0' | |
inactive = '#7d7d7d' | |
# Utility Functions | |
def plural( word, n ): | |
return str(n) + ' ' + (word + 's' if n > 1 else word) | |
def get_dict_subset( thedict, *keys ): | |
return dict([ (key, thedict[key]) for key in keys if key in thedict ]) | |
def print_bitbar_line( title, **kwargs ): | |
print title + ' | ' + ( ' '.join( [ '{}={}'.format( k, v ) for k, v in kwargs.items() ] ) ) | |
def make_github_request( url, method='GET', data=None, enterprise = False ): | |
try: | |
api_key = enterprise_api_key if enterprise else github_api_key | |
headers = { | |
'Authorization': 'token ' + api_key, | |
'Accept': 'application/json', | |
} | |
if data is not None: | |
data = json.dumps(data) | |
headers['Content-Type'] = 'application/json' | |
headers['Contnet-Length'] = len(data) | |
request = urllib2.Request( url, headers=headers ) | |
request.get_method = lambda: method | |
response = urllib2.urlopen( request, data ) | |
return json.load( response ) if response.headers.get('content-length', 0) > 0 else {} | |
except Exception: | |
return None | |
def get_notifications( enterprise ): | |
url = '%s/notifications' % (enterprise_api_url if enterprise else 'https://api.github.com') | |
return make_github_request( url, enterprise=enterprise ) or [] | |
def print_notifications( notifications, enterprise=False ): | |
notifications = sorted( notifications, key=lambda notification: notification['repository']['full_name'] ) | |
for repo, repo_notifications in groupby( notifications, key=lambda notification: notification['repository']['full_name'] ): | |
if repo: | |
repo_notifications = list( repo_notifications ) | |
print_bitbar_line( title=repo ) | |
print_bitbar_line( | |
title='{title} - Mark {count} As Read'.format( title=repo, count=len( repo_notifications ) ), | |
alternate='true', | |
refresh='true', | |
bash=__file__, | |
terminal='false', | |
param1='readrepo', | |
param2=repo, | |
param3='--enterprise' if enterprise else None | |
) | |
for notification in repo_notifications: | |
formatted_notification = format_notification( notification ) | |
print_bitbar_line( refresh='true', **get_dict_subset( formatted_notification, 'title', 'href', 'image', 'templateImage' ) ) | |
print_bitbar_line( | |
refresh='true', | |
title='%s - Mark As Read' % formatted_notification['title'], | |
alternate='true', | |
bash=__file__, | |
terminal='false', | |
param1='readthread', | |
param2=formatted_notification['thread'], | |
param3='--enterprise' if enterprise else None, | |
**get_dict_subset( formatted_notification, 'image', 'templateImage' ) | |
) | |
def format_notification( notification ): | |
type = notification['subject']['type'] | |
formatted = { | |
'thread': notification['url'], | |
'title': notification['subject']['title'].encode('utf-8'), | |
'href': notification['subject']['url'], | |
'image': 'iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAYAAAAmlE46AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAA', | |
} | |
if len(formatted['title']) > 90: | |
formatted['title'] = formatted['title'][:79] + '…' | |
formatted['title'] = formatted['title'].replace('|','-') | |
latest_comment_url = notification.get( 'subject', {} ).get( 'latest_comment_url', None ) | |
typejson = make_github_request( formatted['href'] ) | |
if latest_comment_url: | |
formatted['href'] = ( make_github_request( latest_comment_url ) or {} ).get( 'html_url', formatted['href'] ) | |
# Try to hack a web-viewable URL if the last check failed | |
if formatted['href']: | |
formatted['href'] = re.sub( 'api\.|api/v3/|repos/', '', re.sub( '(pull|commit)s', ur'\1', formatted['href'] ) ) | |
if (type == 'PullRequest'): | |
if typejson and typejson['merged']: | |
formatted['image'] += 'SpJREFUKJG9kkFOwmAQhb+ZQiVx5xm4hIlncEF7jLZuWSjSeAJsvQUY4xkMHsCtcU9MXBmwJsy4EWgFEt34VpP55mX+eflhj9KoGO5jAK00LmOwoZiaYIPRbXaXRsVQRC6BvWZJ4uLJRI6DcKlUMsVl/G0CwIw3UR8V4+QKxFd9BbfDqiP6buo1sB5QjgTJ07i8aPTFgvNFa/7i7fYzaL+YpEN3zwGux4mY2QmAm6db783i0rO4bGyrh7OL66a0Bigm6d5gGkYz3brvV8a/SjeF/dPGJLrpmTMDXs/i4vTnQNYrInNm5szqvIVYbiJdCV1Z6ANwXze6em4i3SBcqi+CNVeAIFxq9dkR0+07HfHVz6rzlsLAK5keUCEu/R0hDD7C+SME6A7+Z30BqF2G+GPLjSUAAAAASUVORK5CYII=' | |
elif typejson and typejson['state'] == 'closed': | |
formatted['image'] += 'Q9JREFUKJG9kjFOw0AQRd9sbAiiQOIMqWJfAInOPULANehTQIjFCbgHFS1eKhR6cDpEbyHRmljyDpWVTWJbSsOvRvvm72i+BjpkI2ZdDIBszNVzTG7HvGcx543JxmifT7KIj4FyUlaYcMjcKI8Id17Pj8JDknMvrD4zoriwRg4OMaKtU44FUhtz6z8aFW7KkC9X82mESbJghpICJDkiyimAwvV2EDG6uZMfThs3TeFYB8miP1XjFb0pdhp31cro/muijbjAUTjDtx1zttnwEnGJo8BR+DxQSAcwWv5i9vd4BZ58Yy2kgTIqq3VuAMoKEx4htCQrijaX5fMAYRoOmbMEJ0y2lhGmZcgbNdDGd9Uf3M1iNlKZZGMAAAAASUVORK5CYII=' | |
else: | |
formatted['image'] += 'TJJREFUKJG9krFOAlEQRe/MLpqHnd/ATyBWsLWF+hcLPYXibvwCE/gLC2MNVrD7AbbGnpjYboBlro2QXWATabzVy5x338ydPKBC4awTVTEA8Huz9i1FI5gZBINh6+0lnHUiEXkAUGmWMGm/c7Fues4pLU9IPv+aAABm9i2qT6Pm+BECbuoqpnZWW4lmmRLG3ZdV9VyAOEyD+1JdVO4yqX+ua7UPofRHrUlEMgaA4cVYALkEACF6e/N2k4DdJCh1Ky7nENftyVACo9akcjElox3I9yfjsdoaVfFPHbtpcG2GOUy/wjS42r0QTjs3ZpibYV7kPmkxVuuGOKfIl1MAr0WjqMRcrBqec8oCVwDwnNOFnwugezkJ4+ZnFbkPeANanpwsAQr7+2m8Qab1FKcAeYgfqR/3P4pMOYR15QAAAABJRU5ErkJggg==' | |
if typejson and typejson.get( 'user', {} ).get( 'login', None ): | |
formatted['title'] += ' (by @{})'.format(typejson['user']['login']) | |
elif (type == 'RepositoryInvitation'): | |
formatted['image'] = 'iVBORw0KGgoAAAANSUhEUgAAAA4AAAAKCAYAAACE2W/HAAAAAXNSR0IArs4c6QAAAM1JREFUKBWVkD0OQUEUhcdv/ASJn55SyxLoVBJq8tZjBRQsgkZiAQoqOiQ2oFc935nMvLxEXsRJPufOufe+kTHGmBeEf3Jg3i4t8IwOP6QZzeoi+3PFt1BRkKAq+Q4uEKbdUA+/wxm6LoubshPcoO8b9lp3GOMPGPomPoInqOcV/VUfyKfwhsChegJxfS3O6R5hALpFqFY2A69osUyygT3UQOpAWwVSpt4aShAt6lWXkIUk5WiswL5qiqIODdBz6+ZirM67cwFvulwfaH0AC7M1lHL62U4AAAAASUVORK5CYII='; | |
formatted['templateImage'] = formatted.pop('image'); | |
formatted['href'] = 'https://github.com/{}/invitations'.format(notification['repository']['full_name']) | |
elif (type == 'Issue'): | |
if typejson and typejson['state'] == 'closed': | |
formatted['image'] += 'YpJREFUKJGdkj9I23EQxT93SZrJQYNQ6Bo65BtQcHRpSeyUuQqNWx2ti7qJRpqhUxGX0lGhlXQ0uJhfU7cOLm3+QKCzoIjoJpp8z0HT/BpJBd90HO/dvTsePBLS36iM8Uw6vANyQNJ7RJU/wG7nmo1XLY7uCStp8uL5BJwgbJtRU8E8jImR98qoGHPZBjsSFhlsCRQjCQovD2iHhx5OEDu/ZF2E5Y4wLn/tXdMy5WO2zkqXHKQxgEy95+y7Y1KMXwogbeaBk0iCwqBn7DteAJym+NmBnSiAF3IK2/32wiIVqoGjYE1GRMlGARSSZtQGbZtq8CNwFBBWDUxgJjqI3I9Mg7XAgRoXmSYlACqOWuAG39ePimNB7+oyxuzhBLEwIUhj3c92sZckLsaSAvg2m14ZPb98eGs8ThFlqBcAx4wJX8T4cGasvm5yFRaUUjwZUd4bLKow/W/kbsWfgTMxvorxmwhtjHEPbxSGEd5many7F/JqiqdemceT88rzu3ZLoWywma1z/NA5/8UNNkSJCdaYQF4AAAAASUVORK5CYII=' | |
else: | |
formatted['image'] += 'ZxJREFUKJGdkjFoU2EUhb97k9jNRzEFoWvJVHXoZCqIaQaH7JaUbtpi2zc4ORWJYKGTYJLBroFaiGPo0hBwyAOhU51Cd8EOOid53uugL4SnkOK3/dx7OPccfvhPZPqxHZUWc0gIUjFs6c/CJdDBtN580P36lzCM1jZ+mr9HuFKkJfgXABO9i/mmqOTd7VlztXcyEYbR2oabtFx5kx+Oa7VHn+LpS7bOV3K5UfBaTF+6WLW52juR7ai0mDEGovq2WezuJ8t7UdkBGsXu5KqdfvlQhOeeGRc0h4QIV/nhuDarkIVgft+xHxJnQwWpKNJKn/cvasvtkcCxuFTUsKWkiOsgrhcoBb2uIE1W4NKRO8DH6cF0KSnLewYDBTqGb26dr+Sm53tR2ZNmE8LTx3O4V9XpKKZ1FV24MZyf2aoH8YE5garXBWC3X1oX12NXO8zfvPWqttwepZ08iA9wXqDypFE8a09y7PZL64geCXx37IO4XiSZcK/+dso8bRTP2pD65DufH96WOBuKSwWlAGD4QJ2Oqtff3e99mxVnJr8AXSGi02ni0+YAAAAASUVORK5CYII=' | |
elif (type == 'Commit'): | |
formatted['image'] += 'HhJREFUKJHl0LEKwkAQBNCH3yIaf05S+VUqmh8ykFoUYn8WbnEc8a7XgYVlmNkdhv/EDgNmvHDFtmXq8ETCiFvsD2xqxksI9xnXB3cqxamYceHgVOpWC6JUi/QNQxj7jDsEd6wZ83KmLOId69bXzqekOeas0eiv4g3q4SY7NY1R2gAAAABJRU5ErkJggg==' | |
formatted['templateImage'] = formatted.pop('image') | |
elif (type == 'Release'): | |
formatted['image'] += 'JdJREFUKJGl0DsKwkAUBdDTRgvFHbgmNyLY+QWzKxM/kK2kSKc70MIIQ0ziqBceA/dxinn8mSkKVMGUmH+CBWaNboQjdn2wqt97Pa8kNd5+C0O86YNdSZC34RLjCJxhHZYLXDCIxKuwTHGOwBNcm2WKUw9OcMCybZl6XjHpQOs30cB5gKNQiDPPP0WjV/a4aVwxNsNfUGce7P8k4XgVPSYAAAAASUVORK5CYII=' | |
formatted['templateImage'] = formatted.pop('image') | |
return formatted | |
if len(sys.argv) > 1: | |
command = sys.argv[1] | |
args = sys.argv[2:] | |
enterprise=False | |
if ('--enterprise' in args): | |
enterprise=True | |
args.remove( '--enterprise' ) | |
if command == 'readrepo': | |
url = '%s/repos/%s/notifications' % (enterprise_api_url if enterprise else 'https://api.github.com', args[0]) | |
print 'Marking %s as read' % url | |
make_github_request( url=url, method='PUT', data={}, enterprise=enterprise ) | |
elif command == 'readthread': | |
url = args[0] | |
print 'Marking %s as read' % url | |
make_github_request( url=url, method='PATCH', data={}, enterprise=enterprise ) | |
else: | |
is_github_defined = len( github_api_key ) == 40 | |
is_github_enterprise_defined = len( enterprise_api_key ) == 40 | |
github_notifications = get_notifications( enterprise=False ) if is_github_defined else [] | |
enterprise_notifications = get_notifications( enterprise=True ) if is_github_enterprise_defined else [] | |
has_notifications = len( github_notifications ) + len( enterprise_notifications ) | |
color = active if has_notifications else inactive | |
if (has_notifications): | |
print_bitbar_line( | |
title=u'\u25CF'.encode( 'utf-8' ), | |
color=color | |
) | |
print '---' | |
else: | |
print '' | |
exit(0) | |
print_bitbar_line( title='Refresh', refresh='true' ) | |
if is_github_defined: | |
if len( github_notifications ): | |
print_bitbar_line( | |
title=( u'GitHub \u2014 %s' % plural( 'notification', len( github_notifications ) ) ).encode( 'utf-8' ), | |
color=active, | |
href='https://github.com/notifications', | |
) | |
print_notifications( github_notifications ) | |
else: | |
print_bitbar_line( | |
title=u'GitHub \u2014 No new notifications'.encode( 'utf-8' ), | |
color=inactive, | |
href='https://github.com', | |
) | |
if is_github_enterprise_defined: | |
if len( enterprise_notifications ): | |
if is_github_defined: | |
print '---' | |
print_bitbar_line( | |
title=( u'GitHub:Enterprise \u2014 %s' % plural( 'notification', len( enterprise_notifications ) ) ).encode( 'utf-8' ), | |
color=active, | |
href='%s/notifications' % re.sub( '/api/v3', '', enterprise_api_url ), | |
) | |
print_notifications( enterprise_notifications, enterprise=True ) | |
else: | |
print '---' | |
print_bitbar_line( | |
title=u'GitHub:Enterprise \u2014 No new notifications', | |
color=inactive, | |
) |
This file contains hidden or 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 /usr/local/bin/node | |
/* jshint esversion: 6, loopfunc: true */ | |
/* | |
<bitbar.title>Google Calendar</bitbar.title> | |
<bitbar.version>v1.2.0</bitbar.version> | |
<bitbar.author>Kodie Grantham</bitbar.author> | |
<bitbar.author.github>kodie</bitbar.author.github> | |
<bitbar.desc>Shows upcoming events from your Google Calendar - Be sure to read the installation instructions here: https://github.com/kodie/bitbar-googlecal</bitbar.desc> | |
<bitbar.image>https://raw.githubusercontent.com/kodie/bitbar-googlecal/master/screenshot.png</bitbar.image> | |
<bitbar.dependencies>node, npm</bitbar.dependencies> | |
<bitbar.dependencies.npm>npm/home-config, npm/googleapis, npm/google-auth-library, npm/hapi, npm/moment, npm/open</bitbar.dependencies.npm> | |
<bitbar.abouturl>https://github.com/kodie/bitbar-googlecal</bitbar.abouturl> | |
*/ | |
var ver = '1.2.0'; | |
var defaults = { | |
clientId: 'clientid', | |
clientSecret: 'clientsecret', | |
clientRedirect: 'http://localhost:3000', | |
calendarId: 'primary', | |
dateColor: false, | |
dateFont: false, | |
dateFormat: 'dddd M/D', | |
dateSize: 12, | |
days: 1, | |
eventColor: false, | |
eventFont: false, | |
eventLength: 80, | |
eventSize: false, | |
expandEvents: false, | |
limit: 25, | |
showAllOfFirstDay: true, | |
showEmptyDays: false, | |
serverHost: 'localhost', | |
serverPort: 3000, | |
startDate: Date.now(), | |
textToday: ' (Today)', | |
textTomorrow: ' (Tomorrow)', | |
timeFormat: 'h:mma', | |
tokenFile: '.googlecal.json' | |
}; | |
if (process.env.BitBar) { | |
var icon = 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAABYlAAAWJQFJUiTwAABD/WlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxMTEgNzkuMTU4MzI1LCAyMDE1LzA5LzEwLTAxOjEw' + | |
'OjIwICAgICAgICAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1s' + | |
'bnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIgogICAgICAgICAgICB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhv' + | |
'dG9zaG9wLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIgogICAgICAgICAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyI+CiAgICAgICAgIDx4bXA6Q3JlYXRlRGF0ZT4yMDE2LTAyLTI3VDA4OjQ1OjQwWjwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDE3LTAyLTIxVDE0OjQ4OjQ4LTA2OjAwPC94bXA6' + | |
'TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcDpNZXRhZGF0YURhdGU+MjAxNy0wMi0yMVQxNDo0ODo0OC0wNjowMDwveG1wOk1ldGFkYXRhRGF0ZT4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNSAoTWFjaW50b3NoKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3BuZzwvZGM6Zm9ybWF0PgogICAgICAgICA8eG1wTU06SGlzdG9yeT4KICAgICAgICAgICAg' + | |
'PHJkZjpTZXE+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPmNvbnZlcnRlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6cGFyYW1ldGVycz5mcm9tIGltYWdlL3BuZyB0byBhcHBsaWNhdGlvbi92bmQuYWRvYmUucGhvdG9zaG9wPC9zdEV2dDpwYXJhbWV0ZXJzPgogICAgICAgICAgICAgICA8L3JkZjps' + | |
'aT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+c2F2ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDozRTNFRTE5RTBCMjA2ODExODIyQUM1MTg3MTkxRkQ2Qzwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxNi0wMi0yN1Qx' + | |
'MzoxNTo1NiswNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPmNvbnZlcnRlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6cGFyYW1ldGVy' + | |
'cz5mcm9tIGltYWdlL3BuZyB0byBhcHBsaWNhdGlvbi92bmQuYWRvYmUucGhvdG9zaG9wPC9zdEV2dDpwYXJhbWV0ZXJzPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+c2F2ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDoz' + | |
'RjNFRTE5RTBCMjA2ODExODIyQUM1MTg3MTkxRkQ2Qzwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxNi0wMi0yN1QxMzoxNTo1NiswNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2Ui' + | |
'PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPnNhdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6ZDVlNDdmMzItMTk5YS00Mzc5LWEwMDEtMjYzODFlMTEzOWI3PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE2LTAyLTI3VDEzOjMxOjIxKzA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8' + | |
'c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNCAoTWFjaW50b3NoKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPmNvbnZlcnRl' + | |
'ZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6cGFyYW1ldGVycz5mcm9tIGFwcGxpY2F0aW9uL3ZuZC5hZG9iZS5waG90b3Nob3AgdG8gaW1hZ2UvcG5nPC9zdEV2dDpwYXJhbWV0ZXJzPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+ZGVyaXZlZDwvc3RFdnQ6' + | |
'YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6cGFyYW1ldGVycz5jb252ZXJ0ZWQgZnJvbSBhcHBsaWNhdGlvbi92bmQuYWRvYmUucGhvdG9zaG9wIHRvIGltYWdlL3BuZzwvc3RFdnQ6cGFyYW1ldGVycz4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPnNhdmVkPC9zdEV2dDph' + | |
'Y3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6ZDAyY2E5NTUtM2IyYy00MTIyLTkzZTAtOTJmZDI2YzY4ZTdlPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE2LTAyLTI3VDEzOjMxOjIxKzA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNCAoTWFj' + | |
'aW50b3NoKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPnNhdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlE' + | |
'PnhtcC5paWQ6MDU2OTA0MWQtNzJmNy00MjFkLTgyZGMtMTAzNGIxZWE4NjE4PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE3LTAyLTIxVDE0OjQ4OjQ4LTA2OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNSAoTWFjaW50b3NoKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAg' + | |
'ICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC94bXBNTTpIaXN0b3J5PgogICAgICAgICA8eG1wTU06RGVyaXZlZEZyb20gcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICA8c3RSZWY6aW5zdGFuY2VJRD54bXAuaWlkOmQ1ZTQ3ZjMyLTE5OWEtNDM3OS1hMDAxLTI2MzgxZTExMzliNzwv' + | |
'c3RSZWY6aW5zdGFuY2VJRD4KICAgICAgICAgICAgPHN0UmVmOmRvY3VtZW50SUQ+eG1wLmRpZDozRTNFRTE5RTBCMjA2ODExODIyQUM1MTg3MTkxRkQ2Qzwvc3RSZWY6ZG9jdW1lbnRJRD4KICAgICAgICAgICAgPHN0UmVmOm9yaWdpbmFsRG9jdW1lbnRJRD54bXAuZGlkOjNFM0VFMTlFMEIyMDY4MTE4MjJBQzUxODcxOTFGRDZDPC9zdFJlZjpvcmlnaW5hbERvY3VtZW50SUQ+CiAgICAgICAgIDwveG1wTU06RGVyaXZlZEZyb20+' + | |
'CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDo4NzMxODkyMC0zOTA1LTExN2EtOTlkNS1kZjA0MGM5YWI5NTg8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpJbnN0YW5jZUlEPnhtcC5paWQ6MDU2OTA0MWQtNzJmNy00MjFkLTgyZGMtMTAzNGIxZWE4NjE4PC94bXBNTTpJbnN0YW5jZUlEPgogICAgICAgICA8eG1wTU06T3JpZ2luYWxEb2N1bWVudElEPnhtcC5kaWQ6M0Uz' + | |
'RUUxOUUwQjIwNjgxMTgyMkFDNTE4NzE5MUZENkM8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHBob3Rvc2hvcDpDb2xvck1vZGU+MzwvcGhvdG9zaG9wOkNvbG9yTW9kZT4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WFJlc29sdXRpb24+MTQ0MDAwMC8xMDAwMDwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRp' + | |
'b24+MTQ0MDAwMC8xMDAwMDwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT42NTUzNTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+MzI8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+MzI8L2V4aWY6UGl4ZWxZ' + | |
'RGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAK' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAg' + | |
'ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PlQH85QAAAAgY0hSTQAAeiUAAICD' + | |
'AAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAc5JREFUeNrsl7FOAkEQhr9biSaEi5hYaaUliYWND2DrS/gCVlZ21iTSUVvyBD4EsTDB0GostAUPQpREzmYuGZbdYyV3WOifbPaY2X93bvef2QPy0QBepDUIx6q8BTSBVFqzDF5F+jpwDBj5/Qw8AVM1Nns+BA4884XyZsADMAQ4BQYq4hRoycBrZbsWW8sauypvAJwaoCM7oDHO2bWifHWgY4Bdx+AP6beVbdvyUQBv1wATh2NL+p6y9SwfBfAmAInjLPtq0IW0DP0cDfyUl/gCSIG2' + | |
'I+J2zuKr8JJIAog9W/oI3MnzGXAUWAdCeaNlAZSNkeGXUbEq1o1VxcrAJnApPVqEwzW++DATod4BI1oYARFQ81SzVHJ60/JNgc8AbqzunLkd0GKsAa9iy9qrmvjK8iViC+HGes2KZ4sMsGfZdOQ7jszZCeQuLORCKkcxlzJix1O+J4HcoAAixxvGYgeoOjjVQK43DTVmwJs10UjsyF1uv+UgkLsAlwjLxJwIf70S+gIoMw2DNPCfhn8zDd/XKP53fRcYSzzZeY092RHJeX9Zvg05hmVcLUgTKXGkS/5YFIma1kQ34Eu3rNaNgH3gFjjJyYqi' + | |
'MQPugfPvAQDFEQJT9lX76gAAAABJRU5ErkJggg=='; | |
console.log(` | dropdown=false templateImage=${icon}`); | |
console.log('---'); | |
} | |
var npmDeps = 'home-config googleapis google-auth-library hapi moment open'; | |
var dirHome = (process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE); | |
var dirPlugins = process.argv[1].split('/').slice(0, -1).join('/'); | |
try { | |
var cfg = Object.assign({}, defaults, require('home-config').load('.bitbarrc').googlecal); | |
var fs = require('fs'); | |
var { google } = require('googleapis'); | |
var Hapi = require('@hapi/hapi'); | |
var moment = require('moment'); | |
var open = require('open'); | |
var oauth2Client = new google.auth.OAuth2(cfg.clientId, cfg.clientSecret, cfg.clientRedirect); | |
} catch(e) { | |
if (process.env.BitBar) { | |
console.log(`Run Installation | bash="cd ${dirPlugins} && npm install ${npmDeps} && rm package-lock.json || true && node ${process.argv[1]} getNewToken"`); | |
footer(); | |
} else { | |
console.log(e); | |
} | |
process.exit(1); | |
} | |
cfg.tokenFile = cfg.tokenFile.replace('~', dirHome); | |
if (cfg.tokenFile.indexOf('/') < 0) { cfg.tokenFile = dirPlugins + '/' + cfg.tokenFile; } | |
function refresh() { | |
open('bitbar://refreshPlugin?name=googlecal.*?.js'); | |
} | |
function getNewToken() { | |
var authUrl = oauth2Client.generateAuthUrl({ | |
access_type: 'offline', | |
scope: ['https://www.googleapis.com/auth/calendar.readonly'] | |
}); | |
open(authUrl); | |
console.log(''); | |
console.log('If your browser did not do so automatically, please visit the following URL:'); | |
console.log(authUrl); | |
console.log(''); | |
var server = new Hapi.Server({ port: cfg.serverPort, host: cfg.serverHost }); | |
server.route({ | |
method: 'GET', | |
path: '/', | |
handler: function(request, h) { | |
var code = request.query.code; | |
return new Promise((resolve, reject) => { | |
oauth2Client.getToken(code, function(error, token) { | |
if (!error) { | |
fs.writeFileSync(cfg.tokenFile, JSON.stringify(token)); | |
refresh(); | |
console.log(JSON.stringify(token)); | |
msg = 'We\'re all done here! You may now close this window.'; | |
} else { | |
msg = 'An error occured while trying to get your authorization code: ' + error.message; | |
reject(); | |
} | |
console.log(msg); | |
server.stop({ timeout: 2000 }); | |
resolve(msg); | |
}); | |
}); | |
} | |
}); | |
server.start(function(error) { | |
if (error) { | |
console.log('An error occured while trying to start the server: ' + error.message); | |
process.exit(1); | |
} else { | |
console.log('Server running at ' + server.info.uri); | |
console.log('Waiting for authorization...'); | |
} | |
}); | |
} | |
function refreshToken(oauth2Client, cb) { | |
oauth2Client.refreshAccessToken(function(error, token) { | |
if (!error) { | |
oauth2Client.credentials = Object.assign({}, oauth2Client.credentials, token); | |
fs.writeFile(cfg.tokenFile, JSON.stringify(oauth2Client.credentials), function(error, data) { | |
if (!error) { | |
cb(oauth2Client); | |
} else { | |
footer([error.message]); | |
process.exit(1); | |
} | |
}); | |
} else { | |
footer([error.message]); | |
process.exit(1); | |
} | |
}); | |
} | |
function listEvents(oauth2Client) { | |
var calendar = google.calendar({ version: 'v3', auth: oauth2Client }); | |
var processedCalendars = 0; | |
var today = moment().format('L'); | |
var tomorrow = moment().add(1, 'days').format('L'); | |
var start = moment(new Date(cfg.startDate)); | |
var dateLimit, evnts = {}, errors = []; | |
if (!(cfg.calendarId instanceof Array)) { | |
cfg.calendarId = cfg.calendarId.split(','); | |
} | |
if (cfg.days) { | |
dateLimit = moment(start).add((cfg.days - 1), 'days').format('L'); | |
if (cfg.showEmptyDays) { | |
for (var x = 0; x < cfg.days; x++) { | |
evnts[moment(start).add(x, 'days').format('L')] = []; | |
} | |
} | |
} | |
for (var i = 0; i < cfg.calendarId.length; i++) { | |
calendar.events.list({ | |
calendarId: cfg.calendarId[i], | |
timeMin: (cfg.showAllOfFirstDay ? (new Date(moment(start).format('L'))) : (new Date(moment(start)))).toISOString(), | |
maxResults: cfg.limit, | |
singleEvents: true, | |
orderBy: 'startTime' | |
}, function(error, response) { | |
processedCalendars++; | |
if (!error) { | |
fs.writeFileSync('/Users/chris.castle/google-out-temp.json', JSON.stringify(response)); | |
var events = response.data.items; | |
if (events.length) { | |
for (var j = 0; j < events.length; j++) { | |
var event = events[j]; | |
var eventStart = moment(event.start.dateTime || event.start.date).format('L'); | |
var eventEnd = moment(event.end.dateTime || event.end.date).format('L'); | |
if (cfg.days && eventStart > dateLimit) { break; } | |
if (!evnts[eventStart]) { evnts[eventStart] = []; } | |
event.date = eventStart; | |
event.time = moment(event.start.dateTime || event.start.date).format(cfg.timeFormat); | |
evnts[eventStart].push(event); | |
if (cfg.expandEvents && eventStart != eventEnd) { | |
var day = new Date(eventStart); | |
while (new Date(day) <= new Date(eventEnd)) { | |
var me = JSON.parse(JSON.stringify(event)); | |
day.setDate(day.getDate() + 1); | |
me.date = moment(day).format('L'); | |
me.time = moment(day).format(cfg.timeFormat); | |
if ((cfg.days && day > dateLimit) || (event.end.date && me.date == moment(event.end.date).format('L'))) { break; } | |
if (!evnts[me.date]) { evnts[me.date] = []; } | |
evnts[me.date].push(me); | |
} | |
} | |
} | |
} | |
if (processedCalendars >= cfg.calendarId.length) { | |
var dates = Object.keys(evnts); | |
var date, d, l, e = 0; | |
dates.sort(); | |
for (var di = 0; di < dates.length; di++) { | |
d = dates[di]; | |
if (!evnts.hasOwnProperty(d)) { continue; } | |
if (e >= cfg.limit) { break; } | |
if (date != d) { | |
if (date) { console.log('---'); } | |
date = moment(new Date(d).toISOString()).format(cfg.dateFormat); | |
if (d == today) { date += cfg.textToday; } | |
if (d == tomorrow) { date += cfg.textTomorrow; } | |
if (process.env.BitBar) { | |
date += ' |'; | |
if (cfg.dateColor) { date += ` color=${cfg.dateColor}`; } | |
if (cfg.dateFont) { date += ` font=${cfg.dateFont}`; } | |
if (cfg.dateSize) { date += ` size=${cfg.dateSize}`; } | |
} | |
console.log(date); | |
} | |
if (evnts[d].length) { | |
evnts[d].sort(function(a, b) { | |
return moment(`${a.date} ${a.time}`, `MM/DD/YYYY ${cfg.timeFormat}`) - moment(`${b.date} ${b.time}`, `MM/DD/YYYY ${cfg.timeFormat}`); | |
}); | |
for (var s = 0; (s < evnts[d].length && s < cfg.limit); s++) { | |
var str = `${evnts[d][s].time} - ${evnts[d][s].summary}`; | |
if (process.env.BitBar) { | |
str += ' |'; | |
if (cfg.eventColor) { str += ` color=${cfg.eventColor}`; } | |
if (cfg.eventFont) { str += ` font=${cfg.eventFont}`; } | |
if (cfg.eventLength) { str += ` length=${cfg.eventLength}`; } | |
if (cfg.eventSize) { str += ` size=${cfg.eventSize}`; } | |
altStr = str; | |
str += ` href=${evnts[d][s].htmlLink}`; | |
altStr += evnts[d][s].hangoutLink ? ` href=${evnts[d][s].hangoutLink}` : ''; | |
altStr += ' alternate=true'; | |
} | |
console.log(str); | |
console.log(altStr); | |
e++; | |
} | |
} | |
} | |
if (Object.keys(evnts).length === 0) { | |
console.log('No upcoming events found.'); | |
} | |
} | |
} else { | |
errors.push(error.message + ' (calendar: ' + cfg.calendarId[i] +')'); | |
} | |
if (processedCalendars >= cfg.calendarId.length) { | |
footer(errors); | |
} | |
}); | |
} | |
} | |
function run() { | |
if (fs.existsSync(cfg.tokenFile)) { | |
var token = fs.readFileSync(cfg.tokenFile, 'utf8'); | |
if (token) { oauth2Client.credentials = JSON.parse(token); } | |
if (!oauth2Client.credentials.refresh_token) { | |
fs.unlinkSync(cfg.tokenFile); | |
console.log('No refresh token set'); | |
console.log('You need to re-authorize this plugin with Google'); | |
if (process.env.BitBar) { | |
console.log('Click here to view your currently authorized apps | href=https://myaccount.google.com/permissions'); | |
} else { | |
console.log('Visit this URL to view your currently authorized apps: https://myaccount.google.com/permissions'); | |
} | |
console.log('You will want to find this plugin and click \'Remove\''); | |
if (process.env.BitBar) { | |
console.log(`After you have done that, click here to re-authorize this plugin | bash=${process.argv[1]} param1=getNewToken refresh=false terminal=true`); | |
} else { | |
console.log('After you have done that, refresh this plugin and run the setup process again'); | |
} | |
footer(); | |
process.exit(1); | |
} else if (new Date(Date.now()) > oauth2Client.credentials.expiry_date) { | |
refreshToken(oauth2Client, listEvents); | |
} else { | |
listEvents(oauth2Client); | |
} | |
} else { | |
if (process.env.BitBar) { | |
console.log(`Login To Google | bash=${process.argv[1]} param1=getNewToken refresh=false terminal=true`); | |
footer(); | |
} else { | |
console.log('Google login required.'); | |
getNewToken(); | |
} | |
} | |
} | |
function footer(errors) { | |
if (errors && errors.length) { | |
console.log('---'); | |
console.log('Errors:'); | |
for (var e = 0; e < errors.length; e++) { | |
console.log(errors[e]); | |
} | |
} | |
if (process.env.BitBar) { | |
console.log('---'); | |
console.log(`BitBar Google Calendar Plugin v${ver}`); | |
console.log('--by Kodie Grantham | href=http://kodieg.com'); | |
console.log('-----'); | |
console.log('--GitHub Page | href=https://github.com/kodie/bitbar-googlecal'); | |
console.log('--Changelog | href=https://github.com/kodie/bitbar-googlecal/blob/master/CHANGELOG.md'); | |
console.log('-----'); | |
console.log('--Refresh | refresh=true terminal=false'); | |
} | |
} | |
if (process.argv[2] == 'getNewToken') { | |
getNewToken(); | |
} else if (process.argv[2] == 'refresh') { | |
refresh(); | |
} else { | |
run(); | |
} |
This file contains hidden or 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 /usr/bin/ruby | |
# <bitbar.title>Heroku</bitbar.title> | |
# <bitbar.version>v0.2</bitbar.version> | |
# <bitbar.author>Deluan Quintao</bitbar.author> | |
# <bitbar.author.github>deluan</bitbar.author.github> | |
# <bitbar.desc>Currently this plugin displays Heroku service status and open issues</bitbar.desc> | |
# <bitbar.image>http://i.imgur.com/B7A1wvm.png</bitbar.image> | |
# <bitbar.dependencies>ruby</bitbar.dependencies> | |
require 'json' | |
require 'open-uri' | |
HEROKU_CMD="/usr/local/bin/heroku" | |
ICON="iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAAlwSFlzAAAWJQAAFiUBSVIk8AAABCRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjE0NDwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+MTQ0PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+MzI8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjMyPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxNi0xMi0yNlQyMzoxMjoyODwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjY8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+Cm0tugEAAAUiSURBVFjDjZfLb1R1FMc/v8dMW0qFysNWUAtCCCVEukFXQHRhZEVcyMaFiXThwkdY8QewQIzoxhADiQtdCCYSF+jKHXaBAglEY5sWebY82o5lpo+Ze+/vuLgz9z0jdzNzb373fM/je875XkXz+vbTSzt6Sj1HA+dGxYlyIiCCiBD+FYTWs+a9ZO6Jz8fvNu8RcIhodabh/FOfnHxrHEABnP/8ymGjzWmF6q97K4UGisBDB/4fPHYerCkROFcJvMYHH546eE59f/KPl7Xmmlamz/MbhM7mvZdOkUcOdAKP77UyBM6vohmxCnfMmq6+urdSCC4iBL6LjCitClNPdDaIgTQJm7GzvvMomXKf560cswJH6l49PFkAXu42rO7vBRGCQKg8rOFcE5A48jAyWPfCGlRYcf59XGNlySP0IV22hldHhCOWXNSxQd8L2LStn9cP7wRgZdHjx69+x68FNAsTpd1vBGzdvZE3330FpcBrBJz7Yoylaj3KWpYzADbN9hi8ebIZS3xFhhSpmisFw3s3oVR47u7ELPMPa2ijOhLWFrZLlNaWM6QijonZjN4LGNzSz+Zt6yInr1+6nQ4oVbL4XVsUebr1IJOC2KnE/5EDQ2gThn/zz0fcmZiNou/UqrpT5MlapUpAXDbfc2zfM8DQzg0hT5Y8xi6OP+WcAFsYeYaxKQdakYc/KA0Lc0tc/OYqIlBbWGb+QQ2l1VMNKVsETgFbW+gigrjwqQscToR7k/M451AKlFEYraISdpyQCLYIPL5vES52wG8ECLCqr0zP6jJdPSW0UTTqPtXKMguzi/i+S7G/2HbonM2PWFKzP+mBKWleO7id9YN9rFm/iq5uG6a6eTVWfKZvzjP28zjTtyoYq6LIye6V1m7IgyfTlqZguduy69XNtLvK3Zah4Y0MvLSWC19f5t7UHKYoE4ms6xx4pgTpGqSvIHAsVesszC2xVKtHz7t7y+w/NIwxClcQebLTbA6c7JZLt+Dcgxr3J+eY/qfC/MMai09W8D2H0oodI4Psf3sXxmgGhvp5dmA1j+4uxKO4YKXbPLikFpNW4HuOiWvT/HX5Ho/vPaG+7CEISqmmohBcIFwfu83Iga30b+hFa0Xf2h5mblcwSrfVEzYCJp32cJ0qZmeqXDh9mZlbFQC0VpiSznCGaAc430UZU1qFLWvaixmb7dMkW9FQebRIEDiM1TmOkCGsyrFECvVAvOuSo7hIiHgBg1vW8tyLa/C9oI1KSpDKZcc2xZETl1xLm3UsIjgn9D7TzRvv7Karx+ICFxt1BTIsu7wLdEa21XU2NfH4lUiUrH++j32HhnEuQdYceBxdcm+ka56ZMQL6qaQ3MLx3M3v2DSVKkd5qqTWdFS/R4MvPGJsTIynw2JjvBVQry5napg2qgplV9M2QLLuWAoYmU9Yy8uv5G4xfvR+KjjacaZeBZNqznWbjZskba704dvFvrv92C1MybXV/i4TG6HgOKFXcugnSWueKwRHQRnNn4jGTN2YwJd3xowPABcIv312h3GUR4P7UbHMZkeNMi6BWkLMlUz4S6vSEGGlmpbHiR6mVwpWadn7yxkzULcYoUCqvBRCMLhF49bPaiTvh+Y2q1iZ1ILuMsuDtOKONxlqNLekCcIk+zfygUZVATuiPPjs4JYEbRaRSMuXONcsIlTx58+M5m3ZrSohIRURGj597byoa319+/NMOpUtHRdyoSPh5XiSj2onXvKBJtxuAE0TBGak3Th3/4f1xgP8A6fG25jZNOt0AAAAASUVORK5CYII=" | |
def status_icon(icon="", ok=true) | |
if icon.respond_to?('each') | |
msg = "" | |
icon.each do |i| | |
msg += "#{i} | image=#{ICON} dropdown=false\n" | |
end | |
else | |
msg = "#{icon} | image=#{ICON} dropdown=false\n" | |
msg += "#{icon} | image=#{ICON} dropdown=false color=red\n" unless ok | |
end | |
msg + "---" | |
end | |
def status | |
begin | |
@status ||= (content = URI("https://status.heroku.com/api/v3/current-status").read; JSON.parse(content)) | |
rescue => e | |
puts status_icon ":interrobang:", false | |
puts "Error: #{e} | color=red" | |
puts "---" | |
puts "Refresh... | refresh=true" | |
exit | |
end | |
end | |
def issues | |
@issues ||= [].tap do |resp| | |
status["issues"].each do |issue| | |
href = issue["full_url"] | |
title = issue["title"] | |
color = issue["status_prod"] | |
resp << "#{title} | color=#{color} href=#{href}" | |
end | |
end | |
end | |
if status["status"]["Production"] != "green" | |
puts status_icon [":grey_exclamation:", ":exclamation:"], false | |
else | |
puts status_icon | |
end | |
puts "---" | |
if issues.size > 0 | |
issues.each do |issue| | |
puts issue | |
end | |
else | |
puts "All good. Relax | href=https://status.heroku.com/ color=green" | |
end | |
puts "---" | |
puts "Refresh... | refresh=true" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment