+++ /dev/null
-;;; gntp.el --- Growl Notification Protocol for Emacs -*- lexical-binding: t -*-
-
-;; Author: Engelke Eschner <tekaiNOSPAMgmx.li>
-;; Version: 0.1
-;; Package-Version: 20141024.1950
-;; Created: 2013-03-21
-
-;; LICENSE
-;; Copyright (c) 2013 Engelke Eschner
-;; All rights reserved.
-
-;; Redistribution and use in source and binary forms, with or without
-;; modification, are permitted provided that the following conditions
-;; are met:
-;; * Redistributions of source code must retain the above copyright
-;; notice, this list of conditions and the following disclaimer.
-;; * Redistributions in binary form must reproduce the above
-;; copyright notice, this list of conditions and the following
-;; disclaimer in the documentation and/or other materials provided
-;; with the distribution.
-;; * Neither the name of the gntp.el nor the names of its
-;; contributors may be used to endorse or promote products derived
-;; from this software without specific prior written permission.
-
-;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
-;; HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-;; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-;; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-;; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-;; OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-;;; Commentary:
-;; This package implements the Growl Notification Protocol GNTP
-;; described at http://www.growlforwindows.com/gfw/help/gntp.aspx
-;; It is incomplete as it only lets you send but not receive
-;; notifications.
-
-;;; Code:
-
-(defgroup gntp nil
- "GNTP, send/register growl notifications via GNTP from within emacs."
- :group 'external)
-
-(defcustom gntp-application-name "Emacs/gntp.el"
- "Name of the application gntp registers itself."
- :type '(string))
-
-(defcustom gntp-application-icon nil
- "Icon to display as the application icon.
-Either a URL or a path to a file."
- :type '(string))
-
-(defcustom gntp-server "localhost"
- "Default port of the server.
-Standard says can't be changed, but port-forwarding etc."
- :type '(string))
-
-(defcustom gntp-server-port 23053
- "Default port of the server.
-Standard says can't be changed, but port-forwarding etc."
- :type '(integer))
-
-(defcustom gntp-register-alist nil
- "Registration item list."
- :type '(choice string (const nil)))
-
-(defun gntp-register (&optional notifications server port)
- (interactive)
- "Register NOTIFICATIONS at SERVER:PORT.
-PORT defaults to `gntp-server-port'."
- (let ((message (gntp-build-message-register (if notifications notifications gntp-register-alist))))
- (gntp-send message (if server server gntp-server) port)))
-
-;;;###autoload
-(defun gntp-notify (name title text server &optional port priority icon)
- "Send notification NAME with TITLE, TEXT, PRIORITY and ICON to SERVER:PORT.
-PORT defaults to `gntp-server-port'"
- (let ((message (gntp-build-message-notify name title text priority icon)))
- (gntp-send message server port)))
-
-(defun gntp-build-message-register (notifications)
- "Build the message to register NOTIFICATIONS types."
- (let ((lines (list "GNTP/1.0 REGISTER NONE"
- (format "Application-Name: %s"
- gntp-application-name)
- (format "Notifications-Count: %d"
- (length notifications))))
- (icon-uri (gntp-app-icon-uri))
- (icon-data (gntp-app-icon-data))
- (icons (list)))
-
- ;; append icon uri
- (when icon-uri
- (nconc lines (list (format "Application-Icon: %s" icon-uri)))
- ;; and data when it exists
- (when icon-data
- (setq icons (cons icon-data icons))))
-
- (dolist (notice notifications)
- ;; "For each notification being registered:
- ;; Each notification being registered should be seperated by a
- ;; blank line, including the first notification
- (nconc lines (cons "" (gntp-notification-lines notice)))
- ;; c
- (let ((icon (gntp-notice-icon-data notice)))
- (when icon
- (nconc icons (list "" icon)))))
-
- ;; icon data must come last
- (when icons
- (nconc lines (cons "" icons)))
-
- (mapconcat 'identity (remove nil lines) "\r\n")))
-
-(defun gntp-notification-lines (notice)
- "Transform NOTICE into a list of strings."
- (let ((display-name (gntp-notice-get notice :display))
- (enabled (gntp-notice-get notice :enabled))
- (icon-uri (gntp-notice-icon-uri notice)))
- (list
- ;; Required - The name (type) of the notification being registered
- (concat "Notification-Name: " (gntp-notice-name notice))
- ;; Optional - The name of the notification that is displayed to
- ;; the user (defaults to the same value as Notification-Name)
- (when display-name
- (concat "Notification-Display-Name: " display-name))
- ;; Optional - Indicates if the notification should be enabled by
- ;; default (defaults to False)
- (when enabled
- "Notification-Enabled: True")
- ;; Optional - The default icon to use for notifications of this type
- (when icon-uri
- (concat "Notification-Icon: " icon-uri)))))
-
-(defun gntp-build-message-notify (name title text &optional priority icon)
- "Build a message of type NAME with TITLE and TEXT."
-
- (format
- "GNTP/1.0 NOTIFY NONE\r\n\
-Application-Name: %s\r\n\
-Notification-Name: %s\r\n\
-Notification-Title: %s\r\n\
-Notification-Text: %s\r\n\
-Notification-Priority: %s\r\n\
-Notification-Icon: %s\r\n\
-\r\n"
- gntp-application-name
- (if (symbolp name) (symbol-name name) name)
- title
- ;; no CRLF in the text to avoid accidentel msg end
- (replace-regexp-in-string "\r\n" "\n" text)
- (if priority priority "0")
- (if icon (gntp-icon-uri icon) "")))
-
-;; notice
-;;(list name ; everthing else is optional
-;; :display "name to display"
-;; :enabled nil
-;; :icon "url or file")
-
-
-(defun gntp-notice-icon-uri (notice)
- "Get the icon URI from NOTICE."
- (gntp-icon-uri (gntp-notice-get notice :icon)))
-
-(defun gntp-notice-icon-data (notice)
- "Get icon data from NOTICE."
- (gntp-icon-data (gntp-notice-get notice :icon)))
-
-(defun gntp-app-icon-uri ()
- "Return the value to be used in the Application-Icon header."
- (gntp-icon-uri gntp-application-icon))
-
-(defun gntp-app-icon-data ()
- "Return the value to be used in the Application-Icon header."
- (gntp-icon-data gntp-application-icon))
-
-(defun gntp-icon-uri (icon)
- "Get the URI of ICON."
- (when icon
- (cond ((string-equal (substring icon 0 7) "http://") icon)
- ((and (file-exists-p icon) (file-readable-p icon))
- (concat "x-growl-resource://" (md5 icon))))))
-
-(defun gntp-icon-data (icon)
- "Get the URI of ICON."
- (when (and icon (not (string-equal (substring icon 0 7) "http://"))
- (file-exists-p icon) (file-readable-p icon))
- (let ((id (md5 icon))
- (data (gntp-file-string icon)))
- (format "Identifier: %s\r\nLength: %d\r\n\r\n%s"
- id (length data) data))))
-
-(defun gntp-notice-name (notice)
- "Get the name of NOTICE. The name must be either a symbol or string."
- (let ((name (car notice)))
- (if (symbolp name)
- (symbol-name name)
- name)))
-
-(defun gntp-notice-get (notice property)
- "Get PROPERTY from NOTICE."
- (plist-get (cdr notice) property))
-
-(defun gntp-send (message server &optional port)
- "Send MESSAGE to SERVER:PORT. PORT defaults to `gntp-server-port'."
- (let ((proc (make-network-process
- :name "gntp"
- :host server
- :server nil
- :service (if port port gntp-server-port)
- ;;:sentinel 'gntp-sentinel
- :filter 'gntp-filter)))
- ;; hmm one CRLF too much?
- (process-send-string proc (concat message "\r\n\r\n\r\n"))))
-
-(defun gntp-filter (proc string)
- "Filter for PROC started by `gntp-send'.
-Argument STRING reply from the server."
- (when (string-equal "GNTP/1.0 -ERROR" (substring string 0 15))
- (error "GNTP: Something went wrong take a look at the reply:\n %s"
- string)))
-
-;; (defun gntp-sentinel (proc msg)
-;; (when (string= msg "connection broken by remote peer\n")
-;; (message (format "client %s has quit" proc))))
-
-
-(defun gntp-file-string (file)
- "Read the contents of a FILE and return as a string."
- (with-temp-buffer
- (insert-file-contents-literally file)
- (buffer-string)))
-
-(provide 'gntp)
-
-;;; gntp.el ends here