def get_user_icon(user): """Get icon location for user. Args: user (tweepy.models.User): Tweet user reference Returns: str: Location of the icon file """ if 'icon-static' not in Notify.get_server_caps(): return None cache_dir = '{}/bleeter'.format(GLib.get_user_cache_dir()) utils.mkdir(cache_dir) md5 = hashlib.md5(user.profile_image_url) # pylint: disable-msg=E1101 filename = '{}/{}'.format(cache_dir, md5.hexdigest()) if not os.path.exists(filename): try: # twitter results can be Unicode strings, urlretrieve won’t work # with them. urllib.urlretrieve(user.profile_image_url.encode('utf-8'), filename) except IOError: # Fallback to application icon if not os.path.exists('{}/bleeter.png'.format(cache_dir)): shutil.copy(utils.find_app_icon(uri=False), cache_dir) filename = '{}/bleeter.png'.format(cache_dir) icon = GdkPixbuf.Pixbuf.new_from_file(filename) if not (icon.get_width(), icon.get_height()) == (48, 48): icon = icon.scale_simple(48, 48, GdkPixbuf.InterpType.BILINEAR) icon.save(filename, 'png') return 'file://{}'.format(filename)
def prepare_notify(self): try: from gi.repository import Notify self.has_notifications = True except ImportError: logging.warning ("libnotify not found.") return "libnotify not found" # Work-around Ubuntu's incompatible workaround for Gnome's API breaking mistake. # https://bugzilla.gnome.org/show_bug.cgi?id=702390 old_add_action = Notify.Notification.add_action def new_add_action(*args): try: old_add_action(*args) except TypeError: old_add_action(*(args + (None,))) Notify.Notification.add_action = new_add_action Notify.init('Pithos') self.notification = Notify.Notification() self.notification.set_category('x-gnome.music') self.notification.set_hint_string('desktop-icon', 'pithos') caps = Notify.get_server_caps() if 'actions' in caps: logging.info('Notify supports actions') self.supports_actions = True if 'body-markup' in caps: self.escape_markup = True if 'action-icons' in caps: self.notification.set_hint('action-icons', GLib.Variant.new_boolean(True))
def notify(title, text, icon = None, timeout = None, iconsize = 48): if icon is None: icon = resources.get_ui_asset("icons/hicolor/scalable/apps/gwibber.svg") if icon is None: return caps = Notify.get_server_caps() notification = Notify.Notification.new(title, text, "gwibber") pixbuf = None try: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(icon, iconsize, iconsize) except GLib.Error as e: logger.error("Avatar failure - %s - %s", icon, e.message) resources.del_avatar(icon) if pixbuf: try: notification.set_icon_from_pixbuf(pixbuf) except GLib.Error as e: logger.error("Notification failure - %s", e.message) if timeout: notification.set_timeout(timeout) if "x-canonical-append" in caps: notification.set_hint_string('x-canonical-append', 'allowed') try: notification.show () except: logger.error("Notification failed") return
def init_notify_cb(self): self.notifycaps = Notify.get_server_caps () self.notify = Notify.Notification() self.notify.set_property('icon-name', os.path.join(self.m.get_prefix(),'monajat.svg')) self.notify.set_property('summary', _("Monajat") ) if 'actions' in self.notifycaps: self.notify.add_action("previous", _("Back"), self.notify_cb, None) self.notify.add_action("next", _("Forward"), self.notify_cb, None) self.notify.add_action("copy", _("copy"), self.notify_cb, None)
def init_notify_cb(self): self.notifycaps = Notify.get_server_caps() self.notify = Notify.Notification() self.notify.set_property( 'icon-name', os.path.join(self.m.get_prefix(), 'monajat.svg')) self.notify.set_property('summary', _("Monajat")) if 'actions' in self.notifycaps: self.notify.add_action("previous", _("Back"), self.notify_cb, None) self.notify.add_action("next", _("Forward"), self.notify_cb, None) self.notify.add_action("copy", _("copy"), self.notify_cb, None)
def format_tweet(text, expand=False, mobile=False): """Format tweet for display. Args: api (str): Tweet content expand (bool): Expand links in tweet text mobile (bool): Open links in twitter’s mobile site Returns: str: Tweet content with pretty formatting """ # Sanitize entity escaping for input text = GLib.markup_escape_text(saxutils.unescape(text)) # re is smart enough to use pre-cached versions url_match = re.compile(r'(https?://[\w\.?=\+/_-]+)') user_match = re.compile(r'@(\w+(/\w+)?)') hashtag_match = re.compile(r'(#\w+)') if mobile: base = 'https://mobile.twitter.com' else: base = 'https://twitter.com' if 'body-markup' in Notify.get_server_caps(): if 'body-hyperlinks' in Notify.get_server_caps(): if expand: text = url_match.sub(utils.url_expand, text) else: text = url_match.sub(r'<a href="\1">\1</a>', text) text = user_match.sub(r'@<a href="{}/\1">\1</a>'.format(base), text) text = hashtag_match.sub( r'<a href="{}/search?q=\1">\1</a>'.format(base), text) else: text = url_match.sub(r'<u>\1</u>', text) text = user_match.sub(r'@<u>\1</u>', text) text = hashtag_match.sub(r'<i>\1</i>', text) if text.startswith('RT '): text = '<b>RT</b> ' + text[3:] return text
def __init__(self): self._caps = Notify.get_server_caps() self._notification = Notify.Notification() self._notification.set_category('x-gnome.music') self._notification.set_hint('desktop-entry', GLib.Variant('s', 'lollypop')) self._set_actions() Lp.player.connect('current-changed', self._on_current_changed)
def __init__(self): """ Init notification object with lollypop infos """ self._caps = Notify.get_server_caps() self._notification = Notify.Notification() self._notification.set_category("x-gnome.music") self._notification.set_hint("desktop-entry", GLib.Variant("s", "lollypop")) self._set_actions() Lp.player.connect("current-changed", self._on_current_changed)
def __init__(self): """ Init notification object with lollypop infos """ self._caps = Notify.get_server_caps() self._inhibitor = False self._notification = Notify.Notification() self._notification.set_category('x-gnome.music') self._notification.set_hint('desktop-entry', GLib.Variant('s', 'lollypop')) self._set_actions() Lp().player.connect('current-changed', self._on_current_changed)
def on_prepare(self): Notify.init('Pithos') self.notification = Notify.Notification() self.notification.set_category('x-gnome.music') self.notification.set_hint_string('desktop-icon', 'pithos') caps = Notify.get_server_caps() if 'actions' in caps: logging.info('Notify supports actions') self.supports_actions = True if 'action-icons' in caps: self.notification.set_hint('action-icons', GLib.Variant.new_boolean(True))
def __init__(self): caps = Notify.get_server_caps() self._notification = Notify.Notification() self._notification.set_category('x-gnome.music') if "action-icons" in caps: self._notification.set_hint('action-icons', GLib.Variant('b', True)) if "persistence" in caps: self._notification.set_hint('resident', GLib.Variant('b', True)) self._notification.set_hint('desktop-entry', GLib.Variant('s', 'lollypop')) if "actions" in caps: self._notification.add_action('media-skip-backward', _("Previous"), self._go_previous, None) self._notification.add_action('media-skip-forward', _("Next"), self._go_next, None) Objects["player"].connect('current-changed', self._update_track)
def on_prepare(self): try: from gi.repository import Notify self.has_notify = True except ImportError: logging.warning ("libnotify not found.") return Notify.init('Pithos') self.notification = Notify.Notification() self.notification.set_category('x-gnome.music') self.notification.set_hint_string('desktop-icon', 'pithos') caps = Notify.get_server_caps() if 'actions' in caps: logging.info('Notify supports actions') self.supports_actions = True if 'action-icons' in caps: self.notification.set_hint('action-icons', GLib.Variant.new_boolean(True))
def show_msg(parent, title, msg, notify_type="document-save"): if "body" in Notify.get_server_caps(): # happens on Windows for instance notification = Notify.Notification.new( title, msg, notify_type ) notification.show() return # fallback on classical ugly popups popup = Gtk.MessageDialog(parent=parent, flags=Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, message_type=Gtk.MessageType.INFO, buttons=Gtk.ButtonsType.OK, text=msg) popup.connect( "response", lambda dialog, response: GLib.idle_add(dialog.destroy) ) popup.show_all()
def send(self): # see: https://developer.gnome.org/libnotify/0.7/libnotify-notify.html # see: https://developer.gnome.org/libnotify/0.7/NotifyNotification.html LibNotify.init('com.westernx.uitools.notifications') self._notification = notification = LibNotify.Notification.new( self.title, self.message, 'dialog-information' ) if DEV: # Can check LibNotify.get_server_caps() for a list of capabilities. print 'capabilities', LibNotify.get_server_caps() # If this is "default", then it is the default action for clicking the notification. notification.add_action('default', 'Default Action', _on_action, 'on_action_payload') notification.add_action('not_default', 'Another Action', _on_action, 'another_payload') notification.connect('closed', _on_action) notification.set_timeout(5000) # 5s notification.show()
def __init__(self, window): self._window = window caps = Notify.get_server_caps() self._notification = Notify.Notification() self._notification.set_category('x-gnome.music') if "action-icons" in caps: self._notification.set_hint('action-icons', GLib.Variant('b', True)) self._notification.set_hint('desktop-entry', GLib.Variant('s', 'lollypop')) if "actions" in caps: self._notification.add_action('media-skip-backward', _("Previous"), self._go_previous, None) self._notification.add_action('media-skip-forward', _("Next"), self._go_next, None) Objects.player.connect('current-changed', self._on_current_changed)
def __init_notify(self): can_continue = True caps = None if not Notify.is_initted(): can_continue = Notify.init('Exaile') if not can_continue: LOGGER.error("Notify.init() returned false.") if can_continue: # This is the first synchronous call to the Notify server. # This call might fail if no server is present or it is broken. # Test it on window manager sessions (e.g. Weston) without # libnotify support, not on a Desktop Environment (such as # GNOME, KDE) to reproduce. available, name, vendor, version, spec_version = Notify.get_server_info() if available: LOGGER.info( "Connected with notify server %s (version %s) by %s", name, version, vendor, ) LOGGER.info("Supported spec version: %s", spec_version) # This is another synchronous, blocking call: caps = Notify.get_server_caps() # Example from Fedora 26 Linux with GNOME on Wayland: # ['actions', 'body', 'body-markup', 'icon-static', 'persistence', 'sound'] LOGGER.debug("Notify server caps: %s", caps) if not caps or not isinstance(caps, list): can_continue = False else: LOGGER.error( "Failed to retrieve capabilities from notify server. " "This may happen if the desktop environment does not support " "the org.freedesktop.Notifications DBus interface." ) can_continue = False self.__handle_init(can_continue, caps)
def usage_note(message, title=None, level=warn, icon=None): """Display a usage notification. Args: message (str): Message to display title (str): Title for notification popup level (func): Function to display text message with icon (str): Icon to use for notification popup """ message = message.replace('%prog', sys.argv[0]) if not title: title = '%prog {}'.format(_version.dotted) title = title.replace('%prog', os.path.basename(sys.argv[0])) print(level(message)) if 'icon-static' in Notify.get_server_caps(): if not icon: if level == success: icon = find_app_icon() elif level == warn: icon = 'stock_dialog-warning' elif level == fail: icon = 'error' else: icon = None # pylint: disable-msg=E1101 note = Notify.Notification.new(title, message, icon) if level == warn: note.set_urgency(Notify.Urgency.LOW) elif level == fail: note.set_urgency(Notify.Urgency.CRITICAL) note.set_timeout(Notify.EXPIRES_NEVER) # pylint: enable-msg=E1101 if not note.show(): raise OSError('Notification failed to display!') return errno.EPERM
def on_prepare(self): try: from gi.repository import Notify self.has_notify = True except ImportError: logging.warning ("libnotify not found.") return if (Notify.VERSION_MAJOR, Notify.VERSION_MINOR, Notify.VERSION_MICRO) < (0, 7, 6): old_add_action = Notify.Notification.add_action Notify.Notification.add_action = lambda *args: old_add_action(*(args + (None,))) Notify.init('Pithos') self.notification = Notify.Notification() self.notification.set_category('x-gnome.music') self.notification.set_hint_string('desktop-icon', 'pithos') caps = Notify.get_server_caps() if 'actions' in caps: logging.info('Notify supports actions') self.supports_actions = True if 'action-icons' in caps: self.notification.set_hint('action-icons', GLib.Variant.new_boolean(True))
def body_supported(): return "body" in Notify.get_server_caps()
def popup(event_type, jid, account, msg_type='', path_to_image=None, title=None, text=None, timeout=-1): """ Notify a user of an event. It first tries to a valid implementation of the Desktop Notification Specification. If that fails, then we fall back to the older style PopupNotificationWindow method """ # default image if not path_to_image: path_to_image = gtkgui_helpers.get_icon_path('gajim-chat_msg_recv', 48) if timeout < 0: timeout = gajim.config.get('notification_timeout') # Try to show our popup via D-Bus and notification daemon if gajim.config.get('use_notif_daemon') and dbus_support.supported: try: DesktopNotification(event_type, jid, account, msg_type, path_to_image, title, GLib.markup_escape_text(text), timeout) return # sucessfully did D-Bus Notification procedure! except dbus.DBusException as e: # Connection to D-Bus failed gajim.log.debug(str(e)) except TypeError as e: # This means that we sent the message incorrectly gajim.log.debug(str(e)) # Ok, that failed. Let's try pynotify, which also uses notification daemon if gajim.config.get('use_notif_daemon') and USER_HAS_PYNOTIFY: if not text and event_type == 'new_message': # empty text for new_message means do_preview = False # -> default value for text _text = GLib.markup_escape_text(gajim.get_name_from_jid(account, jid)) else: _text = GLib.markup_escape_text(text) if not title: _title = '' else: _title = title notification = Notify.Notification(_title, _text) notification.set_timeout(timeout*1000) notification.set_category(event_type) notification.set_data('event_type', event_type) notification.set_data('jid', jid) notification.set_data('account', account) notification.set_data('msg_type', msg_type) notification.set_property('icon-name', path_to_image) if 'actions' in Notify.get_server_caps(): notification.add_action('default', 'Default Action', on_pynotify_notification_clicked) try: notification.show() return except GObject.GError as e: # Connection to notification-daemon failed, see #2893 gajim.log.debug(str(e)) # Either nothing succeeded or the user wants old-style notifications instance = PopupNotificationWindow(event_type, jid, account, msg_type, path_to_image, title, text, timeout) gajim.interface.roster.popup_notification_windows.append(instance)
# Boston, MA 02111-1307, USA. import os # use our local typelib os.environ['GI_TYPELIB_PATH'] = 'libnotify:' + os.environ.get( 'GI_TYPELIB_PATH', '') from gi.repository import Notify assert Notify.is_initted() == False Notify.init('test') assert Notify.is_initted() == True print 'server info:', Notify.get_server_info() print 'server capabilities:', Notify.get_server_caps() n = Notify.Notification.new('title', None, None) n.show() n = Notify.Notification.new('title', 'text', None) n.show() n = Notify.Notification.new('title', 'text', 'gtk-ok') n.show() n.update('New Title', None, None) n.show() n.update('Newer Title', 'New Body', None) n.show() def callback():
def __new__(cls, summary, message, timeout=-1, actions=None, actions_cb=None, pixbuf=None, status_icon=None): if not "actions" in Notify.get_server_caps(): if actions is not None: return NotificationDialog(summary, message, timeout, actions, actions_cb, pixbuf, status_icon) return NotificationBubble(summary, message, timeout, actions, actions_cb, pixbuf, status_icon)
def NewPrinter (self, status, name, mfg, mdl, des, cmd): if name.find("/") >= 0: # name is a URI, no queue was generated, because no suitable # driver was found title = _("Missing printer driver") devid = "MFG:%s;MDL:%s;DES:%s;CMD:%s;" % (mfg, mdl, des, cmd) if (mfg and mdl) or des: if (mfg and mdl): device = "%s %s" % (mfg, mdl) else: device = des text = _("No printer driver for %s.") % device else: text = _("No driver for this printer.") n = Notify.Notification.new (title, text, 'printer') if "actions" in Notify.get_server_caps(): n.set_urgency (Notify.Urgency.CRITICAL) n.set_timeout (Notify.EXPIRES_NEVER) n.add_action ("setup-printer", _("Search"), lambda x, y: self.setup_printer (x, y, name, devid)) else: self.setup_printer (None, None, name, devid) else: # name is the name of the queue which hal_lpadmin has set up # automatically. c = cups.Connection () try: printer = c.getPrinters ()[name] except KeyError: return try: filename = c.getPPD (name) except cups.IPPError: return del c # Check for missing packages cups.ppdSetConformance (cups.PPD_CONFORM_RELAXED) ppd = cups.PPD (filename) import os os.unlink (filename) import sys sys.path.append (APPDIR) import cupshelpers (missing_pkgs, missing_exes) = cupshelpers.missingPackagesAndExecutables (ppd) from cupshelpers.ppds import ppdMakeModelSplit (make, model) = ppdMakeModelSplit (printer['printer-make-and-model']) driver = make + " " + model if status < self.STATUS_GENERIC_DRIVER: title = _("Printer added") else: title = _("Missing printer driver") if len (missing_pkgs) > 0: pkgs = reduce (lambda x,y: x + ", " + y, missing_pkgs) title = _("Install printer driver") text = (_("`%s' requires driver installation: %s.") % (name, pkgs)) n = Notify.Notification.new (title, text, 'printer') import installpackage if "actions" in Notify.get_server_caps(): try: self.packagekit = installpackage.PackageKit () n.set_timeout (Notify.EXPIRES_NEVER) n.add_action ("install-driver", _("Install"), lambda x, y: self.install_driver (x, y, missing_pkgs)) except: pass else: try: self.packagekit = installpackage.PackageKit () self.packagekit.InstallPackageName (0, 0, missing_pkgs[0]) except: pass elif status == self.STATUS_SUCCESS: devid = "MFG:%s;MDL:%s;DES:%s;CMD:%s;" % (mfg, mdl, des, cmd) text = _("`%s' is ready for printing.") % name n = Notify.Notification.new (title, text, 'printer') if "actions" in Notify.get_server_caps(): n.set_urgency (Notify.Urgency.NORMAL) n.add_action ("test-page", _("Print test page"), lambda x, y: self.print_test_page (x, y, name)) n.add_action ("configure", _("Configure"), lambda x, y: self.configure (x, y, name)) else: # Model mismatch devid = "MFG:%s;MDL:%s;DES:%s;CMD:%s;" % (mfg, mdl, des, cmd) text = (_("`%s' has been added, using the `%s' driver.") % (name, driver)) n = Notify.Notification.new (title, text, 'printer') if "actions" in Notify.get_server_caps(): n.set_urgency (Notify.Urgency.CRITICAL) n.add_action ("test-page", _("Print test page"), lambda x, y: self.print_test_page (x, y, name, devid)) n.add_action ("find-driver", _("Find driver"), lambda x, y: self.find_driver (x, y, name, devid)) n.set_timeout (Notify.EXPIRES_NEVER) else: self.configure (None, None, name) self.timeout_ready () n.show () self.notification = n
def __init__(self): from gi.repository import Notify Notify.init(_("Hotot Notification")) caps = Notify.get_server_caps() self.markup = caps and 'body-markup' in caps self.notification = Notify.Notification
# Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. import os # use our local typelib os.environ['GI_TYPELIB_PATH'] = 'libnotify:' + os.environ.get('GI_TYPELIB_PATH', '') from gi.repository import Notify assert Notify.is_initted() == False Notify.init('test') assert Notify.is_initted() == True print 'server info:', Notify.get_server_info() print 'server capabilities:', Notify.get_server_caps() n = Notify.Notification.new('title', None, None) n.show() n = Notify.Notification.new('title', 'text', None) n.show() n = Notify.Notification.new('title', 'text', 'gtk-ok') n.show() n.update('New Title', None, None) n.show() n.update('Newer Title', 'New Body', None) n.show() def callback(): print 'Do it! Callback'
def display(api, tweets, state, timeout, expand, mobile, map_provider): """Display notifications for new tweets. Args: api (tweepy.api.API): Authenticated ``tweepy.api.API`` object tweets (Tweets): Tweets awaiting display seen (State): Application state timeout (int): Timeout for notifications in seconds expand (bool): Whether to expand links in tweet text mobile (bool): Links open in lighter mobile versions map_provider (str): Map provider to open geo links in, if ``mobile`` is ``False` Returns: True: Timers must return a ``True`` value for timer to continue """ try: tweet = tweets.popitem() except KeyError: # No tweets awaiting display return True if tweet.from_type == 'direct': title = 'From {} {}'.format(tweet.sender.name, utils.relative_time(tweet.created_at)) icon = get_user_icon(tweet.sender) elif tweet.from_type == 'search': title = 'From {} {}'.format(tweet.from_user, utils.relative_time(tweet.created_at)) icon = get_user_icon(tweet) else: # Don’t re-display already seen tweets if tweet.id <= state.displayed[tweet.user.screen_name.lower()]: return True title = 'From {} {}'.format(tweet.user.name, utils.relative_time(tweet.created_at)) icon = get_user_icon(tweet.user) if tweet.from_type == 'list': title += ' on {} list'.format(tweet.from_arg) elif tweet.from_type == 'direct': title += ' in direct message' elif tweet.from_type == 'search': title += ' in {} search'.format(tweet.from_arg) # pylint: disable-msg=E1101 note = Notify.Notification.new(title, format_tweet(tweet.text, expand, mobile), icon) # pylint: enable-msg=E1101 if not tweet.from_type == 'direct': if 'actions' in Notify.get_server_caps(): note.add_action('default', ' ', open_tweet(tweet, mobile)) if tweet.from_type == 'search' or not tweet.user.protected: note.add_action('mail-forward', 'retweet', lambda n, a: api.retweet(tweet.id)) # In case this has been seen in another client if tweet.from_type == 'search' or not tweet.favorited: note.add_action('bookmark', 'Fave', lambda n, a: api.create_favorite(tweet.id)) if tweet.geo: note.add_action('find', 'Geo', open_tweet(tweet, mobile, map_provider)) # Keep a reference for handling the action. NOTIFICATIONS[hash(note)] = note note.connect_object('closed', NOTIFICATIONS.pop, hash(note)) note.set_timeout(timeout * 1000) note.set_category('im.received') # pylint: disable-msg=E1101 # For lists: If we cared about these users they’d be followed, not listed # For searches: These are always low priority if tweet.from_type in ('list', 'search'): note.set_urgency(Notify.Urgency.LOW) if api.me().screen_name.lower() in tweet.text.lower(): note.set_urgency(Notify.Urgency.CRITICAL) if tweet.text.lower().startswith(( '@{}'.format(api.me().screen_name.lower()), '.@{}'.format(api.me().screen_name.lower()))): note.set_timeout(Notify.EXPIRES_NEVER) if tweet.from_type == 'direct': note.set_urgency(Notify.Urgency.CRITICAL) note.set_timeout(Notify.EXPIRES_NEVER) # pylint: enable-msg=E1101 if not note.show(): # Fail hard at this point, recovery has little value. raise OSError('Notification failed to display!') if tweet.from_type not in ('direct', 'search'): state.displayed[tweet.user.screen_name.lower()] = tweet.id if tweet.from_type == 'user': state.displayed['self-status'] = tweet.id elif tweet.from_type == 'direct': state.displayed['self-direct'] = tweet.id elif tweet.from_type == 'list': state.displayed['list-{}'.format(tweet.from_arg)] = tweet.id elif tweet.from_type == 'search': state.displayed['search-{}'.format(tweet.from_arg)] = tweet.id return True
def actions_supported(): return "actions" in Notify.get_server_caps()
def parse_and_validate_args(): parser = optparse.OptionParser() parser.add_option('-i', '--update-interval', action='store', type='int', dest='interval', default=300, help='set the feed update interval (in seconds)') parser.add_option('-m', '--max-items', action='store', type='int', dest='max_items', default=3, help='maximum number of items to be displayed per update') parser.add_option('-t', '--display-timeout', action='store', type='int', dest='timeout', help='set the notification display timeout (in seconds)') parser.add_option('-b', '--blog', action='store_true', dest='blog', default=False, help='enable notifications from GitHub\'s blog') parser.add_option('-a', '--important_authors', action='store_true', dest='important_authors', default=False, help='only consider notifications from important authors') parser.add_option('-o', '--organizations', action='store_true', dest='organizations', default=True, help='consider notifications of all user\'s organizations') parser.add_option('-k', '--blacklist_organizations', action='store_true', dest='blacklist_organizations', default=False, help='filter out blacklisted organizations') parser.add_option('-p', '--important_projects', action='store_true', dest='important_projects', default=False, help='only consider notifications from important projects') parser.add_option('-u', '--blacklist_authors', action='store_true', dest='blacklist_authors', default=False, help='filter out blacklisted authors') parser.add_option('-r', '--blacklist_projects', action='store_true', dest='blacklist_projects', default=False, help='filter out blacklisted projects') parser.add_option('-n', '--new-config', action='store_true', dest='new_config', default=False, help='create a new config.cfg at ~/.githubnotifier/') parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False, help='enable verbose logging') (options, args) = parser.parse_args() # Create logger logger = logging.getLogger('github-notifier') handler = logging.StreamHandler() if options.verbose: logger.setLevel(logging.INFO) else: logger.setLevel(logging.WARNING) formatter = logging.Formatter( '[%(levelname)s] %(asctime)s\n%(message)s', datefmt='%d %b %H:%M:%S' ) handler.setFormatter(formatter) logger.addHandler(handler) if options.interval <= 0: logger.error('The update interval must be > 0') sys.exit(1) if options.max_items <= 0: logger.error('The maximum number of items must be > 0') sys.exit(1) if not os.path.isdir(CACHE_DIR): logger.warning('Making the cache directory {0}'.format(CACHE_DIR)) os.makedirs(CACHE_DIR) if not os.path.isfile(CONFIG_FILE) or options.new_config: logger.warning('Making the config file {0}'.format(CONFIG_FILE)) config_file = open(CONFIG_FILE, 'w') config_file.write('[important] # Separated by commas, projects (can be either <user>/<project> or <project>)\n') config_file.write('authors=\nprojects=') config_file.write('\n[blacklist] # Separated by commas, projects (can be either <user>/<project> or <project>)\n') config_file.write('authors=\nprojects=') config_file.write('\norganizations=') config_file.close() if not Notify.init('github-notifier'): logger.error('Couldn\'t initialize notify') sys.exit(1) server_caps = Notify.get_server_caps() if 'body-hyperlinks' in server_caps: logger.info('github-notifier is capable of using hyperlinks') hyperlinks = True else: logger.info('github-notifier is not capable of using hyperlinks') hyperlinks = False (user, token) = UserConfig.get_github_config() if not user or not token: logger.error( '''Could not get GitHub username and token from git config you can run $git config --global github.user <username> and $git config --global github.token <token> to configure it.\n for more information about token check the link https://help.github.com/articles/creating-an-access-token-for-command-line-use''') sys.exit(1) return { 'user': user, 'token': token, 'hyperlinks': hyperlinks, 'options': options }