Skip to content

Instantly share code, notes, and snippets.

@egh
Last active January 3, 2018 18:08
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save egh/5f46b5d6d2061f305b46 to your computer and use it in GitHub Desktop.
Save egh/5f46b5d6d2061f305b46 to your computer and use it in GitHub Desktop.
jabber.el hipchat setup
(require 's)
(require 'request)
(require 'seq)
(require 'jabber)
(defvar hipchat--user-info-for-completion nil)
(defcustom hipchat-nickname "Full name" "Hipchat real name (see see https://hipchat.com/account/xmpp)."
:type '(string)
:group 'hipchat)
(defcustom hipchat-autojoin nil "List of rooms to autojoin."
:type '(repeat string)
:group 'hipchat)
(defcustom hipchat-api-key nil "API key for hipchat.
Used for @ mention autocompletion. Get via hipchat.com / Account
settings / API access. Must have view_group scope."
:type '(string)
:group 'hipchat)
(defun hipchat-get-jid ()
"Return the JID of the users hipchat account."
(car (seq-elt (seq-filter (lambda (acct)
(s-match "chat.hipchat.com" (car acct)))
jabber-account-list) 0)))
(defun hipchat-get-connection ()
"Return the hipchat jabber connetion."
(jabber-find-connection (hipchat-get-jid)))
(defun hipchat-list ()
"Open a list of all hipchat rooms."
(interactive)
(jabber-get-disco-items (hipchat-get-connection) "conf.hipchat.com" nil))
(defun hipchat-join-raw (groupid)
"Join the hipchat group GROUPID."
(jabber-muc-join (hipchat-get-connection) groupid hipchat-nickname t))
(defun hipchat-join ()
"Prompt for hipchat group and join it."
(interactive)
(jabber-disco-get-items
(hipchat-get-connection) "conf.hipchat.com" nil
(lambda (jc data items)
(let* ((groups (mapcar (lambda (item)
(cons (elt item 0) (elt item 1))) items))
(groupname (completing-read "Room name: " groups))
(groupid (cdr (assoc groupname groups))))
(if (y-or-n-p (format "Autojoin %s in the future? " groupname))
(customize-push-and-save 'hipchat-autojoin (list groupid)))
(hipchat-join-raw groupid)))
nil))
(defun hipchat-load-user-info ()
"Load user information from hipchat API for autocompletion."
(request
"https://api.hipchat.com/v2/user"
:params `(("auth_token" . ,hipchat-api-key)
("max-results" . "500"))
:parser 'json-read
:success (function*
(lambda (&key data &allow-other-keys)
(setq hipchat--user-info-for-completion nil)
(seq-map (lambda (user)
(push (cons (format "@%s" (cdr (assq 'mention_name user)))
(cdr (assq 'name user)))
hipchat--user-info-for-completion))
(cdr (assq 'items data)))
(setq hipchat--user-info-for-completion
(completion-table-case-fold hipchat--user-info-for-completion))))))
(defun hipchat-setup-hook (jc)
"Hook to run to setup hipchat. Add to `jabber-post-connect-hooks'."
(when (eq jc (hipchat-get-connection))
(hipchat-load-user-info)
(mapcar (lambda (id)
(hipchat-join-raw id))
hipchat-autojoin)))
(defun hipchat-setup-completion ()
"Setup hipchat @ mention completion. Add to `jabber-chat-mode-hook'."
(define-key jabber-chat-mode-map [?\t] 'completion-at-point)
(add-to-list 'completion-at-point-functions #'hipchat-complete-mention-function))
(defun hipchat-complete-mention-function (&optional start)
"Completion at point function for hipchat @ mention completion."
(let* ((end (point))
(start
(or start
(save-excursion
(re-search-backward "@")
(point)))))
(list start end hipchat--user-info-for-completion)))
(add-hook 'jabber-post-connect-hooks #'hipchat-setup-hook)
(add-hook 'jabber-chat-mode-hook #'hipchat-setup-completion)
;; use this if you don't like all those notices about people joining/leaving
(defadvice jabber-muc-process-presence
(after jabber-muc-process-presence-clear-notices)
"Remove all muc notices."
(let* ((from (jabber-xml-get-attribute presence 'from))
(group (jabber-jid-user from))
(buffer (get-buffer (jabber-muc-get-buffer group))))
(if buffer
(with-current-buffer buffer
(ewoc-filter jabber-chat-ewoc (lambda (elt) (not (eq (car elt) :muc-notice))))))))
(ad-activate #'jabber-muc-process-presence)
;; Render HTML. Especially useful for notifications.
(when (functionp #'shr-insert-document)
(defun jabber-chat-html-body (xml-data who mode)
"Render HTML content in jabber buffer."
(if (string-equal "html" (nth 2 (assq 'message_format (cdr (assq 'x (cdr xml-data))))))
(if (eq mode :printp)
t
(let ((parsed (with-temp-buffer
(insert (nth 1 (cdr (assq 'body (cdr xml-data)))))
(libxml-parse-html-region (point-min) (point-max)))))
(shr-insert-document parsed)
t))
nil))
(add-to-list 'jabber-body-printers #'jabber-chat-html-body))
@egh
Copy link
Author

egh commented Sep 11, 2015

Now with @mention completion!

@kcbanner
Copy link

kcbanner commented Oct 7, 2015

This is great!

@ispyinternet
Copy link

I cant get it to work? Should this file also have a (provide 'jabber-hipchat) at the end and then (require 'jabber-hipchat) it in the .emacs file?

I did that and then it looks like a partly getting there.

For some reason I think I need to add (require 'json) at the top as request was giving parse errors.

I also had to add type:"GET" to the request and I substituted my api key in place at this point. Should I be setting these variables in my .emacs with a setq or something? i.e.

(setq hipchat-api-key "xxxx")

Sorry Im a newbie with lisp.

I seem to be able to jabber-connect-all

But then any of the hipchat commands silently do nothing and if I try to chat it seems to be offline and I get some error traces as:

Debugger entered--Lisp error: (wrong-type-argument stringp nil)
string-match("[^/]*" nil)
jabber-jid-user(nil)
jabber-roster-ret-action-at-point()
call-interactively(jabber-roster-ret-action-at-point nil nil)
command-execute(jabber-roster-ret-action-at-point)

Any help would be appreciated although it may be im a bit out of my depth!?

@ispyinternet
Copy link

to add I have this in my .emacs:

(setq jabber-account-list
'(("xxxx@chat.hipchat.com")))

@agzam
Copy link

agzam commented Oct 24, 2015

really nice. do you guys know how to retrieve messages from server? Someone sends you a message while you're not connected. You connect and still won't see missed messages. In hipchat's client they'd appear though. Also is it possible at all to have inline images to show up right there in Emacs?

@egh
Copy link
Author

egh commented Oct 30, 2015

@ispyinternet Sorry for the late response. You might try setting your jabber-account-list using M-x customize-variable. (You will need to delete the setting in your .emacs.) This will ensure you have the right format for the variable.

@egh
Copy link
Author

egh commented Oct 30, 2015

@agzam When I login hipchat dumps a bunch of history into my channels. But I don't think there is a way to get the history further back. You can use jabber.el history, though.

@egh
Copy link
Author

egh commented Nov 3, 2015

Now with support for HTML rendering and stripping out all those presence notifications.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment