local InputContainer = require("ui/widget/container/inputcontainer") local GoodReaderBook = require("goodreaderbook") local InfoMessage = require("ui/widget/infomessage") local UIManager = require("ui/uimanager") local url = require('socket.url') local socket = require('socket') local http = require('socket.http') local https = require('ssl.https') local ltn12 = require('ltn12') local _ = require("gettext") local GoodReadsApi = InputContainer:new { goodreaders_key = "", goodreaders_secret = "", total_result = 0, } function GoodReadsApi:init() end local function genSearchURL(text_search, userApi, search_type, npage) if (text_search) then text_search = string.gsub (text_search, "\n", "\r\n") text_search = string.gsub (text_search, "([^%w %-%_%.%~])", function (c) return string.format ("%%%02X", string.byte(c)) end) text_search = string.gsub (text_search, " ", "+") end return (string.format( "http://www.goodreads.com/search?q=%s&search[field]=%s&format=xml&key=%s&page=%s", text_search, search_type, userApi, npage )) end local function genIdUrl(id, userApi) return (string.format( "https://www.goodreads.com/book/show/%s?format=xml&key=%s", id, userApi )) end function GoodReadsApi:fetchXml(s_url) local request, sink = {}, {} local parsed = url.parse(s_url) request['url'] = s_url request['method'] = 'GET' request['sink'] = ltn12.sink.table(sink) http.TIMEOUT = 5 https.TIMEOUT = 5 local httpRequest = parsed.scheme == 'http' and http.request or https.request local headers = socket.skip(1, httpRequest(request)) if headers == nil then return nil end local xml = table.concat(sink) if xml ~= "" then return xml end end function GoodReadsApi:showSearchTable(data) local books = {} if data == nil then UIManager:show(InfoMessage:new{text =_("Network problem.\nCheck connection.")}) return books end self.total_result = data:match("(.*)") for work in data:gmatch("(.-)") do local book = work:match("]+>(.*)") local id = book:match("]+>([^<]+)") local title = book:match("([^<]+)"):gsub(" %(.*#%d+%)$", "") local author = book:match("([^<]+)") table.insert(books, { author = author, title = title, id = id, }) end if #books == 0 then UIManager:show(InfoMessage:new{text =_("Search not found!")}) end return books end function GoodReadsApi:getTotalResults() return self.total_result end local function cleanHTMLTags(str_html) local cleaner = { { "&", "&" }, { "—", "-" }, { "’", "'" }, { " ", " " }, { "", "%1" }, { "", "\n" }, { "%-%-", "%-" }, { "

", "\n" }, { "(%b<>)", "" }, { "\n\n*", "\n" }, { "\n*$", "" }, { "^\n*", "" }, } for i=1, #cleaner do local cleans = cleaner[i] str_html = string.gsub(str_html, cleans[1], cleans[2]) end return str_html end local function showIdTable(data) if data == nil then UIManager:show(InfoMessage:new{text =_("Network problem.\nCheck connection.")}) return {} end local data1 = data:match("(.*)") local title_all = data1:match("(.*)"):gsub("$", "") local title = title_all:gsub(" %(.*#%d+%)$", "") local average_rating = data1:match("([^<]+)") local series = title_all:match("%(.*#%d+%)$") if series ~= nil then series = series:match("[(](.*)[)]") else series = _("N/A") end local num_pages = data1:match("(.*)"):gsub("$", "") if num_pages == nil or num_pages =="" then num_pages = _("N/A") end local id = data1:match("([^<]+)"):gsub("$", "") local author = data1:match("([^<]+)") local description = data1:match("(.*)") description = cleanHTMLTags(description) --change format from medium to large local image = data1:match("([^<]+)"):gsub("([0-9]+)m/", "%1l/") local day = data1:match("]+>([^<]+)") local month = data1:match("]+>([^<]+)") local year = data1:match("]+>([^<]+)") local release = {} if (year) then table.insert(release, year) end if (month) then table.insert(release, string.format("%02d", month)) end if (day) then table.insert(release, string.format("%02d", day)) end release = table.concat(release, "-") if release == "" then release = _("N/A") end local book_info = { title = title, author = author, series = series, rating = average_rating, pages = num_pages, release = release, description = description, image = image, id = id, } if id == nil then UIManager:show(InfoMessage:new{text = _("Search not found!")}) end return book_info end -- search_type = all - search all -- search_type = author - serch book by author -- search_type = title - search book by title function GoodReadsApi:showData(search_text, search_type, page, goodreaders_key) local stats = {} local gen_url = genSearchURL(search_text, goodreaders_key, search_type, page) local gen_xml = self:fetchXml(gen_url) local tbl = self:showSearchTable(gen_xml) if #tbl == 0 then return nil end for _, v in pairs(tbl) do local author = v.author local title = v.title local id = v.id table.insert(stats, { author, title, callback = function() local dates = self:showIdData(id, goodreaders_key) if dates.id ~= nil then UIManager:show(GoodReaderBook:new{ dates = dates, }) end end, }) end return stats end function GoodReadsApi:showIdData(id, goodreaders_key) local gen_url = genIdUrl(id, goodreaders_key) local gen_xml = self:fetchXml(gen_url) local tbl = showIdTable(gen_xml) return tbl end return GoodReadsApi