added recent-changes and user-contribs functions for retrieving each of these datasets
[cl-mediawiki.git] / src / query.lisp
blob76eacd27edd46e616e29854d5e91428274025bb3
1 ;; See ../LICENSE for info
2 (in-package :cl-mediawiki)
4 (defmacro define-proxy (name &key core req based-on props doc (processor 'identity))
5 "Defines a function with NAME with REQ required parameters. The
6 symbols in the BASED-ON and PROPS lists are concatenated with pairs
7 from the CORE list and passed to the MAKE-PARAMETERS function."
9 (let ((par-sym (gensym)))
10 `(defun ,name (,@req &key ,@props ,@based-on) ,(if doc doc "no documentation given")
11 (let ((,par-sym (make-parameters
12 (list ,@(mapcar #'(lambda (x) (if (listp x)
13 `(list ',(car x) ',(cadr x))))
14 core)
15 ,@(mapcar #'(lambda (x) (if (listp x)
16 `(list ',(car x) ,(car x))
17 `(list ',x ,x)))
18 (concatenate 'list req props based-on ))))))
19 ;(print ,par-sym)
20 (funcall #',processor
21 (parse-api-response-to-sxml (make-api-request ,par-sym)))))))
24 (define-proxy list-category-members
25 :core ((action query)
26 (list categorymembers))
27 :req (cmtitle)
28 :based-on (version maxlag smaxage maxage requestid titles pageids revids prop
29 meta generator redirects indexpageids)
30 :props (cmprop cmnamespace cmcontinue cmlimit cmsort cmdir cmstart cmend cmstartsortkey cmendsortkey)
31 :processor
32 (lambda (sxml)
33 (let ((rows (find-nodes-by-name "cm" sxml)))
34 (loop for row in rows
35 collecting (loop for (attr val) in (second row)
36 collecting (list (symbolize-string attr) val) ))) )
37 :doc
38 "List all pages in a given category.
40 Parameters:
41 cmtitle - Which category to enumerate (required). Must include Category: prefix
42 cmprop - What pieces of information to include
43 Values (separate with '|'): ids, title, sortkey, timestamp
44 Default: ids|title
45 cmnamespace - Only include pages in these namespaces
46 Values (separate with '|'): 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 100, 101
47 cmcontinue - For large categories, give the value retured from previous query
48 cmlimit - The maximum number of pages to return.
49 No more than 500 (5000 for bots) allowed.
50 Default: 10
51 cmsort - Property to sort by. One value: sortkey, timestamp,Default: sortkey
52 cmdir - In which direction to sort. One value: asc, desc Default: asc
53 cmstart - Timestamp to start listing from. Can only be used with cmsort=timestamp
54 cmend - Timestamp to end listing at. Can only be used with cmsort=timestamp
55 cmstartsortkey - Sortkey to start listing from. Can only be used with cmsort=sortkey
56 cmendsortkey - Sortkey to end listing at. Can only be used with cmsort=sortkey
58 Examples:
59 Get first 10 pages in [[Category:Physics]]:
60 (list-category-members \"Category:Physics\")
62 Get page info about first 10 pages in [[Category:Physics]]:
63 (list-category-members \"Category:Physics\" :prop 'info)
65 Returns a list of alists, each representing a CategoryMember
66 alist keys are: :title :ns :pageid
71 (define-proxy get-page-content
72 :core ((action query)
73 (prop revisions)
74 (rvprop content))
75 :req (titles)
76 :processor
77 (lambda (sxml)
78 (let ((rows (find-nodes-by-name "rev" sxml)))
79 (third (first rows))))
80 :doc
81 "Get the content for a given page
83 Parameters:
84 titles - the title of the page
86 Examples: (get-page-content \"Physics\")
88 Returns: a string with the given page content
91 (define-proxy pages-that-embed
92 :core ((action query)
93 (list embeddedin))
94 :req (eititle)
95 :props (eicontinue einamespace eifilterredir eilimit)
96 :processor
97 (lambda (sxml)
98 (let* ((rows (find-nodes-by-name "ei" sxml))
99 (c-blob (first (find-nodes-by-name "embeddedin" (find-nodes-by-name "query-continue" sxml))))
100 (continuation (when c-blob
101 (destructuring-bind (_1 ((_2 continuation))) c-blob
102 (declare (ignore _1 _2))
103 continuation)))
104 titles)
105 (loop for row in rows
106 do (destructuring-bind (_1 ((_2 title) &rest _3)) row
107 (declare (ignore _1 _2 _3))
108 (push title titles)))
109 (values (nreverse titles) continuation)))
110 :doc
111 "List pages that embed a given template or other page
113 Parameters:
114 eititle - Title to search. If null, titles= parameter will be used instead, but will be obsolete soon.
115 eicontinue - When more results are available, use this to continue.
116 einamespace - The namespace to enumerate.
117 Values (separate with '|'): 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 100, 101, 102, 103
118 eifilterredir - How to filter for redirects
119 One value: all, redirects, nonredirects
120 Default: all
121 eilimit - How many total pages to return.
122 No more than 500 (5000 for bots) allowed.
123 Default: 10
125 Examples: (pages-that-embed \"Template:Client\")
127 Returns: a list of pagetitles and a continuation (if there is one)
130 (defclass token-bag ()
131 ((page-attributes :accessor page-attributes :initarg :page-attributes :initform nil
132 :documentation "An alist of page attributes returned by the api")
133 (timestamp :accessor timestamp :initarg :timestamp :initform nil)
134 (tokens :accessor tokens :initarg :tokens :initform nil
135 :documentation "either a single token, or an
136 alist mapping type to value" )))
138 (defmethod print-object ((token-bag token-bag) stream)
139 (with-accessors ((timestamp timestamp)
140 (tokens tokens)) token-bag
141 (format stream "#<Token-bag ~a ~a>" timestamp tokens)))
143 (defmethod edit-token ((token-bag token-bag))
144 (cdr (assoc :edit (tokens token-bag))))
146 (defmethod move-token ((token-bag token-bag))
147 (cdr (assoc :move (tokens token-bag))))
149 (defmethod delete-token ((token-bag token-bag))
150 (cdr (assoc :delete (tokens token-bag) )))
152 (define-proxy get-action-tokens
153 :core ((action query)
154 (prop info))
155 :req (titles)
156 :props ((intoken :edit))
157 :processor
158 (lambda (sxml)
159 (let ((pages (find-nodes-by-name "page" sxml)))
160 (let ((result (loop for (page alist) in pages
161 collecting
162 (make-instance
163 'token-bag
164 :page-attributes (convert-sxml-attribs-to-alist alist)
165 :tokens
166 (loop for token in (ensure-list intoken)
167 collecting
168 (cons token
169 (sxml-attribute-value (format nil "~atoken" token) alist)))
170 :timestamp (sxml-attribute-value "touched" alist)))))
171 (if (eq 1 (length result)) (car result) result))))
172 :doc
173 "Gets the tokens necessary for perform edits.
175 Parameters:
176 titles - the title of the page we wish to edit
177 intoken - which tokens do we want (out of :edit :move :delete :block :unblock or a list of those)
179 Examples: (get-action-tokens \"Physics\")
180 (get-action-tokens \"Physics\" :intoken '(:edit :move :delete))
181 (get-action-tokens '(\"Main Page\" \"User:Russ\") :intoken '(:move :edit :delete :protect))
183 Returns: a token bag (or list of them if you asked for multiple pages)
186 (define-proxy get-page-info
187 :core ((action query)
188 (prop info))
189 :req (titles)
190 :processor
191 (lambda (sxml)
192 (convert-sxml-attribs-to-alist
193 (second (first (find-nodes-by-name "page" sxml))
195 :doc
196 "Gets the info for a given page as an alist
198 Parameters:
199 titles - the title of the page we wish to retrieve the info of
201 Returns: an alist of attributes about the page
204 (define-proxy recent-changes
205 :core ((action query)
206 (list recentchanges))
207 :req ()
208 :props (rcstart rcend rcdir rcnamespace rctitles (rcprop "user|comment|title|timestamp|ids") rcshow rclimit rctype)
209 :processor
210 (lambda (sxml)
211 (mapcar #'(lambda (n)
212 (convert-sxml-attribs-to-alist
213 (cadr n)))
214 (cddr (first (cddr (find "query" (cddr sxml)
215 :key #'first
216 :test #'string-equal)))))
217 ;sxml
219 :doc
220 "Enumerates the recent changes
222 Parameters:
223 rcstart - The timestamp to start enumerating from.
224 rcend - The timestamp to end enumerating.
225 rcdir - In which direction to enumerate.
226 One value: newer, older
227 Default: older
228 rcnamespace - Filter log entries to only this namespace(s)
229 Values (separate with '|'): 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 100, 101, 102, 103
230 rctitles - Filter log entries to only these page titles
231 rcprop - Include additional pieces of information
232 Values (separate with '|'): user, comment, flags, timestamp, title, ids, sizes, redirect, patrolled
233 Default: title|timestamp|ids
234 rcshow - Show only items that meet this criteria.
235 For example, to see only minor edits done by logged-in users, set show=minor|!anon
236 Values (separate with '|'): minor, !minor, bot, !bot, anon, !anon, redirect, !redirect, patrolled, !patrolled
237 rclimit - How many total changes to return.
238 No more than 500 (5000 for bots) allowed.
239 Default: 10
240 rctype - Which types of changes to show.
241 Values (separate with '|'): edit, new, log
243 Returns:
246 (define-proxy user-contribs
247 :core ((action query)
248 (list usercontribs))
249 :req (ucuser)
250 :props (uclimit ucstart ucend ucuserprefix ucdir ucnamespace (ucprop "comment|title|timestamp|ids") ucshow)
251 :processor
252 (lambda (sxml)
253 (mapcar #'(lambda (n)
254 (convert-sxml-attribs-to-alist
255 (cadr n)))
256 (cddr (first (cddr (find "query" (cddr sxml)
257 :key #'first
258 :test #'string-equal)))))
259 ;sxml
261 :doc
262 " Get all edits by a user
263 Parameters:
264 uclimit - The maximum number of contributions to return.
265 No more than 500 (5000 for bots) allowed.
266 Default: 10
267 ucstart - The start timestamp to return from.
268 ucend - The end timestamp to return to.
269 ucuser - The user to retrieve contributions for.
270 ucuserprefix - Retrieve contibutions for all users whose names begin with this value. Overrides ucuser.
271 ucdir - The direction to search (older or newer).
272 One value: newer, older
273 Default: older
274 ucnamespace - Only list contributions in these namespaces
275 Values (separate with '|'): 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 100, 101, 102, 103
276 ucprop - Include additional pieces of information
277 Values (separate with '|'): ids, title, timestamp, comment, flags
278 Default: ids|title|timestamp|flags|comment
279 ucshow - Show only items that meet this criteria, e.g. non minor edits only: show=!minor
280 Values (separate with '|'): minor, !minor
287 ;; Copyright (c) 2008 Accelerated Data Works, Russ Tyndall
289 ;; Permission is hereby granted, free of charge, to any person
290 ;; obtaining a copy of this software and associated documentation files
291 ;; (the "Software"), to deal in the Software without restriction,
292 ;; including without limitation the rights to use, copy, modify, merge,
293 ;; publish, distribute, sublicense, and/or sell copies of the Software,
294 ;; and to permit persons to whom the Software is furnished to do so,
295 ;; subject to the following conditions:
297 ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
298 ;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
299 ;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
300 ;; IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
301 ;; CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
302 ;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
303 ;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.