;;; Copyright © 2018 swedebugia
;;;
;;; This file is part of guile-wikidata.
;;;
;;; guile-wikidata is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; guile-wikidata is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with guile-wikidata. If not, see .
(use-modules (ice-9 format)
(json)
(guix import json)
(srfi srfi-1)
(web uri)
)
;; Inspired by PYPI wikidata_suggest
(define (wbsearch-uri name)
"Build URI for the Wikidata wbsearchintities API."
(let ((url "https://www.wikidata.org/w/api.php")
(& "&")
(= "=")
(search name)
(action "wbsearchentities")
(format "json")
;; Hardcoded en for now
(language "en")
(type "item")
(continue "0")
(limit "10"))
(string->uri
(string-append url "?"
"search" = search &
"action" = action &
"format" = format &
"language" = language &
"type" = type &
"continue" = continue &
"limit" = limit
))))
;; Inspired by
;; https://opendata.stackexchange.com/questions/5248/how-to-get-the-name-of-a-wikidata-item
(define (wbget-uri qid)
"Build URI for the Wikidata wbsearchintities API."
(let ((url "https://www.wikidata.org/w/api.php")
(& "&")
(= "=")
(ids qid)
(action "wbgetentities")
(format "json")
;; Hardcoded en for now
(language "en"))
(string->uri
(string-append url "?"
"ids" = ids &
"action" = action &
"format" = format &
"language" = language &
))))
(define (wdquery uri)
"Fetch the data, return an alist"
(json-fetch-alist uri))
(define (extract-qid alist)
"Accept unnested alist and output Q-ID."
(if (list? alist)
(assoc-ref alist "id")
(error "extract-qid: Not a proper list" alist)))
(define (extract-label alist)
"Accept unnested ALIST and output label."
(if (list? alist)
(assoc-ref alist "label")
(begin
(error "extract-label: Not a proper list" )
(display alist))))
(define (extract-desc alist)
"Accept unnested ALIST and output label."
(if (list? alist)
;; TODO add error handling when no descriptions
(assoc-ref alist "description")
(begin
(error "extract-desc: Not a proper list" )
(display alist))))
(define (extract-all alist)
(if (list? alist)
`(("label" . ,(extract-label alist))
("description" . ,(extract-desc alist))
("id" . ,(extract-qid alist)))
(begin
(error "extract-all: Not a proper list" )
(display alist))))
(define (extract-result name)
"Returns list with each element being an alist of label, desc, qid"
(map extract-all (assoc-ref (wdquery (wbsearch-uri name)) "search")))
;; BROKEN for some reason
;; (define (output-field qid)
;; "Generate output field with Q-ID for the package record."
;; (if (string? qid)
;; `(wikidata ,qid)
;; ;;(error "Not a string")
;; ;; Parse as pair
;; (if (pair? qid)
;; (let ((qid (cdr qid)))
;; `(wikidata ,qid))
;; ;;Not a pair?
;; ;; debug
;; (format #t "debug qid: ~a ~%" qid)
;; )))
(define (extract-first-result alist)
"Extract first result from nested alist"
;; TODO add error if no results
(if (equal? (first (first alist)) "success")
(first (assoc-ref alist "search"))
(error "success not found"))
)
;; Broken for some reason :-/
;; (define (parse-results query num)
;; (let lp
;; ;;Variable
;; ((num))
;; ;;Bindings?
;; (if (> num 0)
;; ;;Body
;; (let (; Reverse list first so they end up in the right order.
;; (result (take (reverse (extract-result query)) num)))
;; (format #t "~a: ~a: ~a ~%" (number->string num) (extract-label result) (extract-desc result)))
;; ;; Subtract
;; (lp (- num 1))
;; ;; Tail
;; num)))
;;test
;; (parse-results "emacs" 2)
(define (show-first-result query)
;; First result which is often the right one :)
(let ((result (first (extract-result query))))
(format #t "1.: ~a: ~a: ~a ~%"
(extract-qid result) (extract-label result) (extract-desc result))
))
;;testing :)
;;(display "first result:") (newline)
(show-first-result "openssh")
;; (newline)
;; (show-first-result "xorg")
;; (newline)
;; (display "extract-label") (newline)
;; (display (extract-label (first (assoc-ref (wdquery (wbsearch-uri "xorg")) "search"))))
;; (newline)
;; (output-field (extract-qid (first (assoc-ref (wdquery (wbsearch-uri "xorg")) "search"))))
;; (format #t "parse-results: ~%")
;; (parse-results "gnome3" 1)
;; (newline)
;; (format #t "take: ~%")
;; (take (extract-result "gnome") 1)
;; (define (show-3 package-name)
;; "Correlate PACKAGE-NAME with Wikidata Q-IDs and add field to package record for all matches."
;; (let* ((q1 (take (assoc-ref (wdquery (wbsearch-uri package-name)) "search")) 2)
;; (num 2))
;; (while ((>= num 0))
;; (let (((take q1 num)
;; (l (extract-label q1))
;; (d (extract-desc q1))
;; (id (extract-qid q1))))
;; ;; descriptions are sometimes missing
;; (if (d)
;; (format #t "~a : ~a : ~a ~%" l d id)
;; (format #t "~a : ~a ~%" l id))
;; ;;debug
;; (display "debug: ")
;; (display q1) (newline)
;; ;;(format #t "~a ~%"(string-append t ":" d))
;; ;;(format #t "~a ~%"(string-append t ":" id))
;; )
;; (- num 1))))
;; (format #t "Show-3: ~%")
;; (show-3 "gnome3")
;;(assoc-ref (assoc-ref query "search") "label")
;; def _wikipedia(name, lang='en'):
;; url = "https://%s.wikipedia.org/w/api.php" % lang
;; params = {
;; "action": "query",
;; "list": "search",
;; "format": "json",
;; "srnamespace": "0",
;; "srsearch": name
;; }
;; sug = None
;; results = requests.get(url, params=params).json()
;; if len(results['query']['search']) > 0:
;; sug = results['query']['search'][0]['title']
;; elif 'suggestion' in results['query']['searchinfo'] and \
;; name != results['query']['searchinfo']['suggestion']:
;; sug = _wikipedia(results['query']['searchinfo']['suggestion'], lang)
;; return sug