Created
January 10, 2017 16:36
-
-
Save weswhet/9f87c1bbfac266653b42edff90bea0d4 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/python | |
import sys | |
import os | |
import subprocess | |
import datetime | |
from Foundation import NSDate, NSMetadataQuery, NSPredicate, NSRunLoop | |
from Foundation import CFPreferencesAppSynchronize | |
from Foundation import CFPreferencesCopyAppValue | |
from Foundation import CFPreferencesCopyKeyList | |
from Foundation import CFPreferencesSetValue | |
from Foundation import kCFPreferencesAnyUser | |
from Foundation import kCFPreferencesCurrentUser | |
from Foundation import kCFPreferencesCurrentHost | |
sys.path.append('/usr/local/munki/munkilib') | |
import FoundationPlist # nopep8 | |
import munkicommon # nopep8 | |
def current_user(): | |
return munkicommon.getconsoleuser() | |
def get_available_updates(): | |
'''Returns the number of available updates from the munki prefs''' | |
try: | |
puc = int(munkicommon.pref('PendingUpdateCount')) | |
if puc and puc > 0: | |
return puc | |
return 0 | |
except ValueError: | |
munkicommon.display_warning( | |
'PendingUpdateCount is not an integer: {}.'.format( | |
munkicommon.pref('DaysBetweenNotifications'))) | |
return 0 | |
def mscalert_running(): | |
process_list = subprocess.check_output(['ps', 'auxwww']) | |
if 'MSCalert' in process_list: | |
return True | |
else: | |
return False | |
def alertUserOfUpdates(updates, force=False): | |
"""Notify the logged-in user of available updates. | |
Args: | |
force: bool, default False, forcefully notify user regardless | |
of LastNotifiedDate. | |
Returns: | |
Boolean. True if the user was notified, False otherwise. | |
""" | |
# called when options.auto == True | |
# someone is logged in, and we have updates. | |
# if we haven't notified in a while, notify: | |
user_was_notified = False | |
lastNotifiedString = munkicommon.pref('LastAlertDate') | |
try: | |
daysBetweenNotifications = int( | |
munkicommon.pref('HoursBetweenAlerts')) | |
except TypeError: | |
munkicommon.display_warning( | |
'HoursBetweenAlerts is not an integer: %s' | |
% munkicommon.pref('HoursBetweenAlerts')) | |
# continue with the default HoursBetweenAlerts | |
daysBetweenNotifications = 4 | |
munkicommon.set_pref('HoursBetweenAlerts', daysBetweenNotifications) | |
now = NSDate.new() | |
nextNotifyDate = now | |
if lastNotifiedString: | |
lastNotifiedDate = NSDate.dateWithString_(lastNotifiedString) | |
interval = daysBetweenNotifications * (60 * 60) | |
if daysBetweenNotifications > 0: | |
# we make this adjustment so a 'daily' notification | |
# doesn't require 24 hours to elapse | |
# subtract 30 minutes | |
interval = interval - (30 * 60) | |
nextNotifyDate = lastNotifiedDate.dateByAddingTimeInterval_(interval) | |
if force or now.timeIntervalSinceDate_(nextNotifyDate) >= 0: | |
# record current notification date | |
munkicommon.set_pref('LastAlertDate', now) | |
munkicommon.display_debug1('Alerting user of available updates.') | |
munkicommon.display_debug1('LastAlertDate was {}'.format( | |
lastNotifiedString)) | |
# notify user of available updates using LaunchAgent to start | |
# Managed Software Update.app in the user context. | |
if updates == 1: | |
plural = "update" | |
else: | |
plural = "updates" | |
send_alert(current_user(), updates, plural) | |
user_was_notified = True | |
return user_was_notified | |
def send_alert(current_user, updates, plural): | |
DEVNULL = open(os.devnull, 'wb') | |
munkicommon.display_debug1('Sending Notification Center Alert...') | |
apps_util = "/Applications/Utilities/" | |
alert_app = "MSCalert.app/Contents/MacOS/MSCalert" | |
alert_path = os.path.join(apps_util, alert_app) | |
cmd = ['su', '-l', current_user, '-c', '{0} -t "Managed Software Center" \ | |
-a munki://updates -n "You have {1} available {2}." -b "Open"'.format( | |
alert_path, updates, plural)] | |
subprocess.call(cmd, stdout=DEVNULL, stderr=subprocess.STDOUT, close_fds=True) | |
def main(): | |
if mscalert_running(): | |
kill_cmd = ['/usr/bin/killall', 'MSCalert'] | |
subprocess.call(kill_cmd) | |
if len(sys.argv) > 1: | |
if sys.argv[1] != 'auto': | |
print 'Not Auto Run: Skipping!' | |
exit(0) | |
current_day = datetime.date.today().strftime("%a") | |
if current_day == "Wed": | |
print "It's Wednesday! We do full MSC pop ups today..." | |
exit(0) | |
available_updates = get_available_updates() | |
if available_updates == 0: | |
exit(0) | |
alertUserOfUpdates(available_updates) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment