Skip to content

Commit

Permalink
Merge pull request #8 from cpwood/main
Browse files Browse the repository at this point in the history
Versioning, Tests, fixes and updates
  • Loading branch information
DaveBathnes authored May 23, 2022
2 parents 28459ec + f6233cc commit 2b5b1bd
Show file tree
Hide file tree
Showing 22 changed files with 588 additions and 206 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,5 @@ dist

# TernJS port file
.tern-port

output.txt
83 changes: 56 additions & 27 deletions connectors/arena.js → connectors/arena/v6.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
// HTTP Header:
// Liferay-Portal: Liferay Portal Community Edition 6.2 CE GA6 (Newton / Build 6205 / January 6, 2016)

const xml2js = require('xml2js')
const cheerio = require('cheerio')
const querystring = require('querystring')
const request = require('superagent')

const common = require('../connectors/common')
const common = require('../../connectors/common')

console.log('arena connector loading...')

const LIBRARIES_URL_PORTLET = '?p_p_id=extendedSearch_WAR_arenaportlet&p_p_lifecycle=2&p_p_state=normal&p_p_mode=view&p_p_resource_id=/extendedSearch/?wicket:interface=:0:extendedSearchPanel:extendedSearchForm:organisationHierarchyPanel:organisationContainer:organisationChoice::IBehaviorListener:0:&p_p_cacheability=cacheLevelPage&random=0.08709241788681465extended-search?p_p_id=extendedSearch_WAR_arenaportlet&p_p_lifecycle=2&p_p_state=normal&p_p_mode=view&p_p_resource_id=/extendedSearch/?wicket:interface=:0:extendedSearchPanel:extendedSearchForm:organisationHierarchyPanel:organisationContainer:organisationChoice::IBehaviorListener:0:&p_p_cacheability=cacheLevelPage&random=0.08709241788681465'
const LIBRARIES_URL_PORTLETS = '?p_p_id=extendedSearch_WAR_arenaportlets&p_p_lifecycle=2&p_p_state=normal&p_p_mode=view&p_p_resource_id=/extendedSearch/?wicket:interface=:0:extendedSearchPanel:extendedSearchForm:organisationHierarchyPanel:organisationContainer:organisationChoice::IBehaviorListener:0:&p_p_cacheability=cacheLevelPage&random=0.08709241788681465extended-search?p_p_id=extendedSearch_WAR_arenaportlet&p_p_lifecycle=2&p_p_state=normal&p_p_mode=view&p_p_resource_id=/extendedSearch/?wicket:interface=:0:extendedSearchPanel:extendedSearchForm:organisationHierarchyPanel:organisationContainer:organisationChoice::IBehaviorListener:0:&p_p_cacheability=cacheLevelPage&random=0.08709241788681465'
const SEARCH_URL_PORTLET = 'search?p_p_id=searchResult_WAR_arenaportlet&p_p_lifecycle=1&p_p_state=normal&p_r_p_arena_urn:arena_facet_queries=&p_r_p_arena_urn:arena_search_type=solr&p_r_p_arena_urn:arena_search_query=[BOOKQUERY]'
const SEARCH_URL_PORTLETS = 'search?p_p_id=searchResult_WAR_arenaportlets&p_p_lifecycle=1&p_p_state=normal&p_p_mode=view&p_r_p_687834046_facet_queries=&p_r_p_687834046_search_type=solr&p_r_p_687834046_search_query=[BOOKQUERY]'
const ITEM_URL_PORTLET = 'results?p_p_id=crDetailWicket_WAR_arenaportlet&p_p_lifecycle=1&p_p_state=normal&p_r_p_arena_urn:arena_search_item_id=[ITEMID]&p_r_p_arena_urn:arena_facet_queries=&p_r_p_arena_urn:arena_agency_name=[ARENANAME]&p_r_p_arena_urn:arena_search_item_no=0&p_r_p_arena_urn:arena_search_type=solr'
const ITEM_URL_PORTLETS = 'results?p_p_id=crDetailWicket_WAR_arenaportlets&p_p_lifecycle=1&p_p_state=normal&p_p_mode=view&p_p_col_id=column-2&p_p_col_pos=2&p_p_col_count=4&p_r_p_687834046_facet_queries=&p_r_p_687834046_search_item_no=0&p_r_p_687834046_sort_advice=field%3DRelevance%26direction%3DDescending&p_r_p_687834046_search_type=solr&p_r_p_687834046_search_item_id=[ITEMID]&p_r_p_687834046_agency_name=[ARENANAME]'
const HOLDINGS_URL_PORTLET = 'results?p_p_id=crDetailWicket_WAR_arenaportlet&p_p_lifecycle=2&p_p_state=normal&p_p_mode=view&p_p_resource_id=/crDetailWicket/?wicket:interface=:0:recordPanel:holdingsPanel::IBehaviorListener:0:&p_p_cacheability=cacheLevelPage&p_p_col_id=column-2&p_p_col_pos=1&p_p_col_count=3'
const HOLDINGS_URL_PORTLETS = 'results?p_p_id=crDetailWicket_WAR_arenaportlets&p_p_lifecycle=2&p_p_state=normal&p_p_mode=view&p_p_resource_id=/crDetailWicket/?wicket:interface=:0:recordPanel:holdingsPanel::IBehaviorListener:0:&p_p_cacheability=cacheLevelPage&p_p_col_id=column-2&p_p_col_pos=1&p_p_col_count=3'
const HOLDINGSDETAIL_URL_PORTLET = 'results?p_p_id=crDetailWicket_WAR_arenaportlet&p_p_lifecycle=2&p_p_state=normal&p_p_mode=view&p_p_resource_id=[RESOURCEID]&p_p_cacheability='
const HOLDINGSDETAIL_URL_PORTLETS = 'results?p_p_id=crDetailWicket_WAR_arenaportlets&p_p_lifecycle=2&p_p_state=normal&p_p_mode=view&p_p_resource_id=[RESOURCEID]&p_p_cacheability='

/**
Expand All @@ -30,18 +28,34 @@ exports.getService = (service) => common.getService(service)
*/
exports.getLibraries = async function (service) {
const responseLibraries = common.initialiseGetLibrariesResponse(service)
let $ = null;

try {
const agent = request.agent()
if (responseLibraries.libraries.length > 0) return common.endResponse(responseLibraries)

if (service.PreLoad)
// Get necessary session cookies
await agent.get(service.Url);

if (service.SignupUrl) {
// This service needs to be loaded using the signup page rather
// than the advanced search page.
let signupResponse = await agent.get(service.SignupUrl);
$ = cheerio.load(signupResponse.text);

if ($('select[name="choiceBranch"] option').length > 1) {
$('select[name="choiceBranch"] option').each(function () {
if (common.isLibrary($(this).text())) responseLibraries.libraries.push($(this).text())
})
return common.endResponse(responseLibraries)
}
}

// Get the advanced search page
let advancedSearchResponse = null
// The AdvancedUrl tends to either be advanced-search or extended-search
advancedSearchResponse = await agent.get(service.Url + service.AdvancedUrl)
let advancedSearchResponse = await agent.get(service.Url + service.AdvancedUrl)

// The advanced search page may have libraries listed on it
let $ = cheerio.load(advancedSearchResponse.text)
$ = cheerio.load(advancedSearchResponse.text)
if ($('.arena-extended-search-branch-choice option').length > 1) {
$('.arena-extended-search-branch-choice option').each(function () {
if (common.isLibrary($(this).text())) responseLibraries.libraries.push($(this).text())
Expand All @@ -51,7 +65,7 @@ exports.getLibraries = async function (service) {

// If not we'll need to call a portlet to get the data
const headers = { Accept: 'text/xml', 'Wicket-Ajax': true, 'Wicket-FocusedElementId': 'id__extendedSearch__WAR__arenaportlet____e', 'Content-Type': 'application/x-www-form-urlencoded' }
const url = service.Url + service.AdvancedUrl + (service.portlets ? LIBRARIES_URL_PORTLETS : LIBRARIES_URL_PORTLET)
const url = service.Url + service.AdvancedUrl + LIBRARIES_URL_PORTLETS
const responseHeaderRequest = await agent.post(url).send(querystring.stringify({ 'organisationHierarchyPanel:organisationContainer:organisationChoice': service.OrganisationId })).set(headers)
const js = await xml2js.parseStringPromise(responseHeaderRequest.text)

Expand Down Expand Up @@ -81,10 +95,11 @@ exports.searchByISBN = async function (isbn, service) {
try {
const agent = request.agent()

let bookQuery = (service.SearchType !== 'Keyword' ? service.ISBNAlias + '_index:' + isbn : isbn)
//let bookQuery = (service.SearchType !== 'Keyword' ? service.ISBNAlias + '_index:' + isbn : isbn)
let bookQuery = `number_index:${isbn}`;
if (service.OrganisationId) bookQuery = 'organisationId_index:' + service.OrganisationId + '+AND+' + bookQuery

const searchUrl = (service.Portlets ? SEARCH_URL_PORTLETS : SEARCH_URL_PORTLET).replace('[BOOKQUERY]', bookQuery)
const searchUrl = SEARCH_URL_PORTLETS.replace('[BOOKQUERY]', bookQuery)
responseHoldings.url = service.Url + searchUrl

let searchResponse = await agent.get(responseHoldings.url).timeout(20000)
Expand All @@ -98,7 +113,7 @@ exports.searchByISBN = async function (isbn, service) {
itemId = itemId.substring(0, itemId.indexOf('&'))
responseHoldings.id = itemId

const itemDetailsUrl = (service.Portlets ? ITEM_URL_PORTLETS : ITEM_URL_PORTLET).replace('[ARENANAME]', service.ArenaName).replace('[ITEMID]', itemId)
const itemDetailsUrl = ITEM_URL_PORTLETS.replace('[ARENANAME]', service.ArenaName).replace('[ITEMID]', itemId)
const itemUrl = service.Url + itemDetailsUrl

const itemPageResponse = await agent.get(itemUrl).set({ Connection: 'keep-alive' }).timeout(20000)
Expand All @@ -109,26 +124,35 @@ exports.searchByISBN = async function (isbn, service) {
var libName = $(this).find('.arena-branch-name span').text()
var totalAvailable = $(this).find('.arena-availability-info span').eq(0).text().replace('Total ', '')
var checkedOut = $(this).find('.arena-availability-info span').eq(1).text().replace('On loan ', '')
if (libName) responseHoldings.availability.push({ library: libName, available: ((totalAvailable ? parseInt(totalAvailable) : 0) - (checkedOut ? parseInt(checkedOut) : 0)), unavailable: (checkedOut !== '' ? parseInt(checkedOut) : 0) })
var av = ((totalAvailable ? parseInt(totalAvailable) : 0) - (checkedOut ? parseInt(checkedOut) : 0));
var nav = (checkedOut !== '' ? parseInt(checkedOut) : 0);

if (libName && ((av + nav) > 0))
responseHoldings.availability.push({ library: libName, available: av, unavailable: nav })
})
return common.endResponse(responseHoldings)
}

// Get the item holdings widget
const holdingsPanelHeader = { Accept: 'text/xml', 'Wicket-Ajax': true }
const holdingsPanelUrl = service.Url + (service.Portlets ? HOLDINGS_URL_PORTLETS : HOLDINGS_URL_PORTLET)
const holdingsPanelUrl = service.Url + HOLDINGS_URL_PORTLETS

var holdingsPanelPortletResponse = await agent.get(holdingsPanelUrl).set(holdingsPanelHeader).timeout(20000)
var js = await xml2js.parseStringPromise(holdingsPanelPortletResponse.text)
if (!js['ajax-response'] || !js['ajax-response'].component) return common.endResponse(responseHoldings)
$ = cheerio.load(js['ajax-response'].component[0]._)

if ($('.arena-holding-nof-total, .arena-holding-nof-checked-out, .arena-holding-nof-available-for-loan').length > 0) {
$('.arena-holding-child-container').each(function () {
var libName = $(this).find('span.arena-holding-link').text()
var totalAvailable = $(this).find('td.arena-holding-nof-total span.arena-value').text() || (parseInt($(this).find('td.arena-holding-nof-available-for-loan span.arena-value').text() || 0) + parseInt($(this).find('td.arena-holding-nof-checked-out span.arena-value').text() || 0))
var checkedOut = $(this).find('td.arena-holding-nof-checked-out span.arena-value').text()
if (libName) responseHoldings.availability.push({ library: libName, available: (parseInt(totalAvailable) - (checkedOut ? parseInt(checkedOut) : 0)), unavailable: (checkedOut !== '' ? parseInt(checkedOut) : 0) })
$('.arena-holding-child-container').each(function (idx, container) {
var libName = $(container).find('span.arena-holding-link').text()
var totalAvailable = $(container).find('.arena-holding-nof-total span.arena-value').text() || (parseInt($(container).find('td.arena-holding-nof-available-for-loan span.arena-value').text() || 0) + parseInt($(container).find('td.arena-holding-nof-checked-out span.arena-value').text() || 0))
var checkedOut = $(container).find('.arena-holding-nof-checked-out span.arena-value').text()

var av = ((totalAvailable ? parseInt(totalAvailable) : 0) - (checkedOut ? parseInt(checkedOut) : 0));
var nav = (checkedOut !== '' ? parseInt(checkedOut) : 0);

if (libName && ((av + nav) > 0))
responseHoldings.availability.push({ library: libName, available: av, unavailable: nav })
})
return common.endResponse(responseHoldings)
}
Expand All @@ -140,7 +164,7 @@ exports.searchByISBN = async function (isbn, service) {
var holdingsHeaders = { Accept: 'text/xml', 'Wicket-Ajax': true }
holdingsHeaders['Wicket-FocusedElementId'] = 'id__crDetailWicket__WAR__arenaportlets____2a'
var resourceId = '/crDetailWicket/?wicket:interface=:0:recordPanel:holdingsPanel:content:holdingsView:' + (currentOrg + 1) + ':holdingContainer:togglableLink::IBehaviorListener:0:'
var holdingsUrl = service.Url + (service.Portlets ? HOLDINGSDETAIL_URL_PORTLETS : HOLDINGSDETAIL_URL_PORTLET).replace('[RESOURCEID]', resourceId)
var holdingsUrl = service.Url + HOLDINGSDETAIL_URL_PORTLETS.replace('[RESOURCEID]', resourceId)
var holdingsResponse = await agent.get(holdingsUrl).set(holdingsHeaders).timeout(20000)
var holdingsJs = await xml2js.parseStringPromise(holdingsResponse.text)
$ = cheerio.load(holdingsJs['ajax-response'].component[0]._)
Expand All @@ -152,7 +176,7 @@ exports.searchByISBN = async function (isbn, service) {
const availabilityRequests = []
libsData.each(function (i) {
resourceId = '/crDetailWicket/?wicket:interface=:0:recordPanel:holdingsPanel:content:holdingsView:' + (currentOrg + 1) + ':childContainer:childView:' + i + ':holdingPanel:holdingContainer:togglableLink::IBehaviorListener:0:'
const libUrl = service.Url + (service.Portlets ? HOLDINGSDETAIL_URL_PORTLETS : HOLDINGSDETAIL_URL_PORTLET).replace('[RESOURCEID]', resourceId)
const libUrl = service.Url + HOLDINGSDETAIL_URL_PORTLETS.replace('[RESOURCEID]', resourceId)
var headers = { Accept: 'text/xml', 'Wicket-Ajax': true }
availabilityRequests.push(agent.get(libUrl).set(headers).timeout(20000))
})
Expand All @@ -163,10 +187,15 @@ exports.searchByISBN = async function (isbn, service) {
var availabilityJs = await xml2js.parseStringPromise(response.text)
if (availabilityJs && availabilityJs['ajax-response']) {
$ = cheerio.load(availabilityJs['ajax-response'].component[0]._)
var totalAvailable = $('td.arena-holding-nof-total span.arena-value').text()
var checkedOut = $('td.arena-holding-nof-checked-out span.arena-value').text()
var totalAvailable = $('.arena-holding-nof-total span.arena-value').text()
var checkedOut = $('.arena-holding-nof-checked-out span.arena-value').text()
$ = cheerio.load(availabilityJs['ajax-response'].component[2]._)
responseHoldings.availability.push({ library: $('span.arena-holding-link').text(), available: ((totalAvailable ? parseInt(totalAvailable) : 0) - (checkedOut ? parseInt(checkedOut) : 0)), unavailable: (checkedOut ? parseInt(checkedOut) : 0) })

var av = ((totalAvailable ? parseInt(totalAvailable) : 0) - (checkedOut ? parseInt(checkedOut) : 0));
var nav = (checkedOut ? parseInt(checkedOut) : 0);

if ((av + nav) > 0)
responseHoldings.availability.push({ library: $('span.arena-holding-link').text(), available: av, unavailable: nav })
}
})
}
Expand Down
Loading

0 comments on commit 2b5b1bd

Please sign in to comment.