1 ;;; lj-edit.el --- post editing for ljupdate
2 ;; Copyright (C) 2002, 2003, 2004, 2005 Edward O'Connor <ted@oconnor.cx>
3 ;; Copyright (C) 2006 Paul Huff <paul.huff@gmail.com>
5 ;; Author: Edward O'Connor <ted@oconnor.cx>
6 ;; Author: Paul Huff <paul.huff@gmail.com>
7 ;; Keywords: convenience
9 ;; This file is an addition to ljupdate, a LiveJournal client for Emacs.
11 ;; ljupdate is free software; you can redistribute it and/or
12 ;; modify it under the terms of the GNU General Public License as
13 ;; published by the Free Software Foundation; either version 2, or
14 ;; {at your option} any later version.
16 ;; ljupdate is distributed in the hope that it will be useful, but
17 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ;; General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING, or type `C-h C-c'. If
23 ;; not, write to the Free Software Foundation at this address:
25 ;; Free Software Foundation
26 ;; 51 Franklin Street, Fifth Floor
27 ;; Boston, MA 02110-1301
45 (require 'lj-pcomplete
)
46 (require 'lj-protocol
)
50 (defun lj-edit-post (&optional edit-itemid
)
52 (message (if edit-itemid
53 (concat "Editing id: " edit-itemid
)
54 "Editing last post."))
55 (let* ((edit-server (or lj-last-server lj-default-server
56 "www.livejournal.com"))
57 (edit-username (or lj-last-username lj-default-username
""))
58 (edit-request (list '("mode" .
"getevents")
59 '("auth_method" .
"challenge")
61 '("selecttype" .
"one")
62 (cons "itemid" (if edit-itemid
66 (edit-challenge (lj-getchallenge edit-server
)))
67 (when (string= edit-username
"")
68 (setq edit-username
(read-from-minibuffer (format "Username @%s: " edit-server
))))
69 (add-to-list 'edit-request
(cons "user" edit-username
))
70 (add-to-list 'edit-request
(cons "auth_challenge" edit-challenge
))
71 (add-to-list 'edit-request
73 (lj-md5 (concat edit-challenge
(lj-password edit-server edit-username
)))))
74 (let ((edit-response (lj-protocol-send-request edit-server edit-request
)))
75 (with-output-to-temp-buffer "lj-list"
76 (set-buffer "lj-list")
77 ;; (lj-list-props response)
78 (if (not (eq (get-buffer "*LiveJournal*") nil
))
79 (kill-buffer (get-buffer "*LiveJournal*")))
81 (goto-char (- 1 (lj-compose-find-separator)))
82 (lj-add-props edit-response edit-server edit-username
)
83 (goto-char (+ 1 (lj-compose-find-separator)))
84 (insert (replace-regexp-in-string "\r" "" (decode-coding-string (string-make-unibyte (lj-html-decode-string (gethash "events_1_event" edit-response
))) lj-coding-system
)))
85 )))(delete-windows-on "lj-list"))
87 (defun lj-add-prop (prop value
)
88 (let ((found-field (message-position-on-field prop
)))
90 (re-search-forward (concat "^" (regexp-quote prop
) ":") nil t
)
91 (kill-region (point) (line-end-position))
92 (insert (concat " " value
))))
94 (defun lj-add-props-helper (response n
)
97 (let ((prop_name (gethash (concat "prop_" (number-to-string n
) "_name") response
))
98 (prop_value (gethash (concat "prop_" (number-to-string n
) "_value") response
)))
99 (cond ((string= prop_name
"current_mood") (lj-add-prop "Mood" prop_value
))
100 ((string= prop_name
"current_music") (lj-add-prop "Music" prop_value
))
101 ((string= prop_name
"taglist") (lj-add-prop "Tags" prop_value
))
102 ((string= prop_name
"picture_keyword") (lj-add-prop "Picture" prop_value
))
103 ((and (string= prop_name
"opt_nocomments") (string= prop_value
"1"))
104 (lj-add-prop "Allow-Comments" "no"))
105 ((and (string= prop_name
"opt_noemail") (string= prop_value
"1"))
106 (lj-add-prop "Receive-Mail-Notification" "no"))
108 (lj-add-props-helper response
(- n
1)))))
110 (defun lj-add-props (response edit-server edit-username
)
111 (let ((subject (gethash "events_1_subject" response
)))
113 (lj-add-prop "Subject" subject
)))
114 (let ((time (gethash "events_1_eventtime" response
)))
116 (lj-add-prop "Time" time
)))
117 (let ((itemid (gethash "events_1_itemid" response
)))
119 (lj-add-prop "Itemid" itemid
)))
121 (let* ((access (gethash "events_1_security" response
))
122 (allowmask (gethash "events_1_allowmask" response
)))
124 (cond ((string-match "public" access
)
125 (lj-add-prop "Access" "public"))
126 ((string-match "private" access
)
127 (lj-add-prop "Access" "private"))
128 ((string-match "usemask" access
)
129 (if (eq (truncate (log (string-to-number allowmask
) 2)) 0)
130 (lj-add-prop "Access" "friends")
131 (lj-add-prop "Access" (car (rassoc (truncate (log (string-to-number allowmask
) 2)) (lj-user-get edit-server edit-username
:friends-groups
)))))))))
132 (lj-add-props-helper response
(string-to-number (gethash "prop_count" response
))))
134 ;; (defun lj-edit-submit ()
135 ;; "Submit this entry to the server."
137 ;; (let* ((buf (current-buffer))
138 ;; ;; The text of the entry.
139 ;; (event (lj-compose-prepare-body))
141 ;; ;; Some convenience variables for oft-used headers
142 ;; (server (lj-compose-fetch-field "Server"))
143 ;; (user (lj-compose-fetch-field "User"))
144 ;; (itemid (lj-compose-fetch-field "Itemid"))
145 ;; ;; The current time -- or use the specified time if it exists
146 ;; (time (lj-compose-fetch-field "Time"))
147 ;; (timestamp (if (eq nil time)
149 ;; (date-to-time (concat time " " (cadr (current-time-zone))))))
151 ;; (time (split-string (format-time-string "%Y:%m:%d:%H:%M" timestamp) "[:]"))
153 ;; (month (pop time))
156 ;; (minute (pop time))
158 ;; ;; LJ Authentication information
161 ;; ;; The actual request packet, and the response we receive from
163 ;; (request (list '("mode" . "editevent")
164 ;; '("auth_method" . "challenge")
166 ;; (cons "itemid" itemid)
167 ;; (cons "year" year)
168 ;; (cons "mon" month)
170 ;; (cons "hour" hour)
171 ;; (cons "min" minute)
172 ;; (cons "event" event))))
174 ;; ;; Build up the request packet.
175 ;; (add-to-list 'request (cons "user" user))
177 ;; (let ((subject (lj-compose-fetch-field "Subject")))
179 ;; (add-to-list 'request (cons "subject" subject))))
180 ;; ;; FIXME: use moodid if available
181 ;; (let ((mood (lj-compose-fetch-field "Mood")))
183 ;; (add-to-list 'request (cons "prop_current_mood" mood))))
185 ;; (let ((tags (lj-compose-fetch-field "Tags")))
187 ;; (add-to-list 'request (cons "prop_taglist" tags))))
189 ;; (let ((music (lj-compose-fetch-field "Music")))
191 ;; (add-to-list 'request (cons "prop_current_music" music))))
193 ;; (let ((community (lj-compose-fetch-field "Community")))
195 ;; (add-to-list 'request (cons "usejournal" community))))
197 ;; (let ((picture (lj-compose-fetch-field "Picture")))
199 ;; (add-to-list 'request (cons "prop_picture_keyword" picture))))
201 ;; (let ((comments (lj-compose-fetch-field "Allow-Comments")))
202 ;; (when (and comments (string-match "[Nn][Oo]" comments))
203 ;; (add-to-list 'request '("prop_opt_nocomments" . "1"))))
205 ;; (let ((email (lj-compose-fetch-field "Receive-Mail-Notification")))
206 ;; (when (and email (string-match "[Nn][Oo]" email))
207 ;; (add-to-list 'request '("prop_opt_noemail" . "1"))))
209 ;; (let* ((access (lj-compose-fetch-field "Access"))
210 ;; (friends-group-number
211 ;; (cdr (assoc access (lj-user-get server user :friends-groups)))))
212 ;; (if (stringp access)
213 ;; (cond ((string-match "public" access)
214 ;; (add-to-list 'request '("security" . "public")))
215 ;; ((string-match "private" access)
216 ;; (add-to-list 'request '("security" . "private")))
217 ;; ((string-match "friends" access)
218 ;; (add-to-list 'request '("allowmask" . "1"))
219 ;; (add-to-list 'request '("security" . "usemask")))
220 ;; (friends-group-number
221 ;; (add-to-list 'request (cons "allowmask"
222 ;; (lj-exp2 friends-group-number)))
223 ;; (add-to-list 'request '("security" . "usemask")))
225 ;; (warn "Unable to understand Access: %s; presuming private.")
226 ;; (add-to-list 'request '("security" . "private"))))
227 ;; (add-to-list 'request '("security" . "public"))))
229 ;; ;; Actually talk to the LJ server.
230 ;; (message "Connecting to `%s' as `%s'. Please wait." server user)
231 ;; (setq challenge (lj-getchallenge server))
233 ;; (add-to-list 'request (cons "auth_challenge" challenge))
234 ;; (add-to-list 'request
235 ;; (cons "auth_response"
236 ;; (lj-md5 (concat challenge (lj-password server user)))))
238 ;; (message "Submitting to `%s' as `%s'. Please wait." server user)
240 ;; (let ((response (lj-protocol-send-request server request)))
241 ;; (set-buffer buf) ; return to the *LiveJournal* buffer
242 ;; (if (and (hash-table-p response)
243 ;; (string= (gethash "success" response) "OK"))
245 ;; (set-buffer-modified-p nil)
246 ;; (message "Successfully posted as %s." (gethash "url" response))
248 ;; (let ((errmsg (gethash "errmsg" response)))
250 ;; (message "Posting to %s failed: %s" server errmsg)
251 ;; (message "Posting to %s failed!" server)))
254 (defun lj-html-decode-string (string)
256 (let ((string (replace-regexp-in-string "%\\([0-9A-F]\\{2\\}\\)" (lambda (match) (char-to-string (string-to-number (substring match
1) 16))) string
)))
257 (replace-regexp-in-string "+" " " string
)))
259 (defun lj-list-props (response n
)
263 (insert (gethash (concat "prop_" (number-to-string n
) "_name") response
))
265 (insert (gethash (concat "prop_" (number-to-string n
) "_value") response
))
267 (lj-list-props response
(- n
1)))))
269 (defun lj-insert-entry-into-entry-list (hash n
)
270 (lexical-let* ((event_string (concat "events_" (number-to-string n
)))
271 (event_subject (concat event_string
"_subject"))
272 (event_time (concat event_string
"_eventtime"))
273 (event_itemid_string (concat event_string
"_itemid"))
274 (event_itemid (gethash event_itemid_string hash
))
278 (if (<= n
(string-to-number (gethash "events_count" hash
)))
280 (insert-button (concat (gethash event_time hash
) " - "
281 (if (gethash event_subject hash
)
282 (gethash event_subject hash
)
283 "(no subject)")) 'action
(lambda (event) (lj-edit-post event_itemid
)))
285 (lj-insert-entry-into-entry-list hash
(+ n
1))))))
287 (defun lj-get-last-n (n)
288 (let* ((server (or lj-last-server lj-default-server
289 "www.livejournal.com"))
290 (username (or lj-last-username lj-default-username
""))
291 (request (list '("mode" .
"getevents")
292 '("auth_method" .
"challenge")
294 '("selecttype" .
"lastn")
295 (cons "howmany" (number-to-string n
))))
296 (challenge (lj-getchallenge server
)))
297 (when (string= username
"")
298 (setq username
(read-from-minibuffer (format "Username @%s: " server
))))
299 (add-to-list 'request
(cons "user" username
))
300 (add-to-list 'request
(cons "auth_challenge" challenge
))
301 (add-to-list 'request
302 (cons "auth_response"
303 (lj-md5 (concat challenge
(lj-password server username
)))))
304 (let ((response (lj-protocol-send-request server request
)))
305 (with-output-to-temp-buffer "lj-list"
306 (set-buffer "lj-list")
307 (lj-insert-entry-into-entry-list response
1)
308 (print-help-return-message)))))
311 (defun lj-browse-entries ()
316 (defalias 'lj-edit-last
'lj-edit-post
)
322 ;;; lj-edit.el ends here