The following code should not be run until you’ve backed up your Big
Brother Database and sacrificed a chicken. It goes through the list of
people in your exported LinkedIn CSV, creates BBDB records if
necessary, adds a linkedin mail alias, and notices new e-mail
addresses and job titles. Call sacha/linkedin-import from the CSV.
which you should load before running this code.
If anyone else ever finds this useful, I’ll be quite surprised.
(require 'csv) (require 'lookout) (setq lookout-bbdb-mapping-table '(("lastname" "Last Name") ("firstname" "First Name") ("company" "Company") ("job" "Job Title") ("net" "E-mail Address"))) (defun sacha/lookout-bbdb-check-linkedin (line) (let* ((lastname (lookout-bbdb-get-value "lastname" line)) (firstname (lookout-bbdb-get-value "firstname" line)) (company (lookout-bbdb-get-value "company" line)) (job (lookout-bbdb-get-value "job" line)) (net (lookout-bbdb-get-value "net" line)) (addr1 (lookout-bbdb-get-value "addr1" line)) (addr2 (lookout-bbdb-get-value "addr2" line)) (addr3 (lookout-bbdb-get-value "addr3" line)) (phones (lookout-bbdb-get-value "phones" line t)) ;; ! (notes (lookout-bbdb-get-value "notes" line )) (j (concat job ", " company)) (otherfields (lookout-bbdb-get-value "otherfields" line t)) (addrs nil) (n (concat "^" firstname " " lastname)) (record (or (bbdb-search (bbdb-records) n) (bbdb-search (bbdb-records) nil nil net))) (message "")) (unless record (if (string= company "") (setq company nil)) (if (string= notes "") (setq notes nil)) (if (and addr1 (> (length addr1) 0)) (add-to-list 'addrs (vector "Address 1" (list addr1) "" "" "" ""))) (if (and addr2 (> (length addr2) 0)) (add-to-list 'addrs (vector "Address 2" (list addr2) "" "" "" ""))) (if (and addr3 (> (length addr3) 0)) (add-to-list 'addrs (vector "Address 3" (list addr3) "" "" "" ""))) (setq record (list (lookout-bbdb-create-entry (concat firstname " " lastname) (concat job ", " company) net addrs phones notes otherfields)))) ;; Check if net has changed (when record (setq record (car record)) (let ((nets (bbdb-record-net record))) (unless (member net nets) ;; New e-mail address noticed, add to front of list (add-to-list 'nets net) (bbdb-record-set-net record nets) (message "%s %s: New e-mail address noticed: %s" firstname lastname net))) ;; Check if job title and company have changed (when (or job company) (cond ((string= (or (bbdb-record-company record) "") "") (bbdb-record-set-company record j)) ((string= (bbdb-record-company record) j) nil) (t (bbdb-record-set-notes record (concat "Noticed change from job title of " (bbdb-record-company record) "\n" (bbdb-record-notes record))) (message "%s %s: Noticed change from job title of %s to %s" firstname lastname (bbdb-record-company record) j) (bbdb-record-set-company record j)))) (let* ((propsym bbdb-define-all-aliases-field) (oldaliases (bbdb-record-getprop record propsym))) (if oldaliases (setq oldaliases (if (stringp oldaliases) (bbdb-split oldaliases ",") oldaliases))) (add-to-list 'oldaliases "linkedin") (setq oldaliases (bbdb-join oldaliases ", ")) (bbdb-record-putprop record propsym oldaliases))))) (defun lookout-bbdb-create-entry (name company net addrs phones notes &optional otherfields) (when (or t (y-or-n-p (format "Add %s to bbdb? " name))) ;;(message "Adding record to bbdb: %s" name) (let ((record (bbdb-create-internal name company net addrs phones notes))) (unless record (error "Error creating bbdb record")) (mapcar (lambda (i) (let ((field (make-symbol (aref i 0))) (value (aref i 1))) (when (and value (not (string= "" value))) (bbdb-insert-new-field record field value)))) otherfields) record))) (defun lookout-bbdb-get-value (key entry &optional as-vector-list) "Returns the value for a key from a lispified csv line, using the mapping table." (let* ((table (if (listp lookout-bbdb-mapping-table) lookout-bbdb-mapping-table (symbol-value lookout-bbdb-mapping-table))) (mapped-keys (cdr (assoc key table))) (result nil) (separator "")) (unless as-vector-list (setq result "")) (when mapped-keys (if (stringp mapped-keys) (setq mapped-keys (list mapped-keys))) (mapcar (lambda (i) ;;(message "%s...%s" i (cdr (assoc i entry))) (let ((value (cdr (assoc i entry)))) (unless (string= "" value) (if as-vector-list (add-to-list 'result (vector i value)) (setq result (concat result separator value))) (setq separator " ")))) mapped-keys)) ;;(message "%s" result) result)) (defun sacha/linkedin-import () (interactive) (mapcar 'sacha/lookout-bbdb-check-linkedin (csv-parse-buffer)))
One of the things I want in a contact management system is a quick way
to find out who I haven’t pinged in a while. The following code
filters currently-displayed contacts to show who I might want to get
back in touch with. Call it from a *BBDB* window and specify the date
(could be 2006.01.01 for annual, -7 for the last seven days, etc.).
This works incredibly well with the following hacks:
I should write a small book about how to build a contact management
system with Emacs. ;) It’s insanely powerful, you know.
(require 'planner) (require 'bbdb) (defun sacha/bbdb-show-only-no-contact-since (date) "Show only people who haven't been pinged since DATE or at all." (interactive (list (planner-read-date))) (let ((records bbdb-records) new-records last-match omit notes) (while records ;; Find the latest date mentioned in the entry (setq notes (or (bbdb-record-notes (caar records)) "")) (setq last-match nil omit nil) (while (string-match "[0-9][0-9][0-9][0-9]\\.[0-9][0-9]\\.[0-9][0-9]" notes (or last-match 0)) (unless (string> date (match-string 0 notes)) (setq omit t) (setq last-match (length notes))) (setq last-match (match-end 0))) (unless (and last-match omit) (add-to-list 'new-records (caar records) t)) (setq records (cdr records))) (bbdb-display-records new-records)))
One of the other things I’d like to smooth over is keeping track of
who owes whom e-mail… <laugh>
And because it’s good to quickly flash through records once in a while
to refresh my memory…
(defvar sacha/bbdb-rapid-serial-visualization-delay 1 "*Number of seconds to wait between records. Set to 0 to wait for input.") (defun sacha/bbdb-rapid-serial-visualization () "Breeze through everyone's name and notes." (interactive) (window-configuration-to-register ?a) ;; Copy the currently visible records (let ((records bbdb-records) (default-size (face-attribute 'default :height)) (new-size 400) (continue t)) (set-face-attribute 'default nil :height new-size) (pop-to-buffer (get-buffer-create "BBDB-Serial")) (delete-other-windows) (while (and records continue) (insert (bbdb-record-name (caar records)) "\n\n" (or (car (bbdb-record-net (caar records))) "No e-mail") "\n\n" (or (bbdb-record-notes (caar records)) "") (make-string 50 ?\n)) (goto-char (point-min)) (sit-for sacha/bbdb-rapid-serial-visualization-delay) (setq records (cdr records))) (set-face-attribute 'default nil :height default-size) (when continue (jump-to-register ?a))))
… and because this is just so endearingly old-school and crazily
Emacs, here’s what’s going to be my title “slide” for DemoCamp10.
(progn (set-face-attribute 'default nil :height 700) (delete-other-windows) (sit-for 1) (animate-sequence (list "Livin' la Vida Emacs" "DemoCamp10" "Sacha Chua") 1))
I may end up writing a presentation mode if there isn’t one yet. I’ve
seen one before, but I don’t know if it accepts arbitrary Lisp
expressions. Maybe I can mess around with eev, too..
Comment from pll:
OMG!!!!!!!!!!!!!! That’s just SOOOOOO cool, and hysterical. I’ve got
to steal^H^H^H^H^Hborrow this hack. I’ve been toying with the idea
for a while of doing a “Life with Emacs” talk for my LUG. What a
perfect opening :)
Whenever I go to a networking event and see people without nametags or
with nametags that only have their first names, I see all these missed
opportunities to help memory and enrich conversations.
Nametags are essential at networking events. Hardly anyone can be
expected to remember everyone’s names after such brief introductions.
Nametags help other people discreetly remember your name without
embarrassing them by asking you again.
Here are some tips I’ve picked up from books and from experience:
Always wear your nametag high on your right shoulder. This is where
the eye is naturally drawn to when you shake hands with someone. Make
it easy for people to read your nametag when they shake hands with
Make sure there’s enough space on your nametag for your first and last
name. This makes it easier for people to remember you when they review
all the business cards they’ve received and the notes they’ve taken.
And why stop at names? You want people to remember what you do, too. I
find that “Sacha Chua, Tech Evangelist” starts more conversations and
is remembered better than just “Sacha Chua”. Make it easy for people
to find out and remember what you’re interested in by adding a tag line
or some keywords to your nametag. Use a second nametag if necessary.
You can repeat some of these keywords on your business card or e-mail
signature to reinforce people’s memories.
For serious networking, always bring a nametag with your first and
last name and a tag line. Many events don’t provide printed nametags,
and your preparation will set you apart.
Do you have any other tips for nametag success? Please e-mail me at
firstname.lastname@example.org, and I’ll add it to this entry!