Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Versioning, Tests, fixes and updates #8

Merged
merged 2 commits into from
May 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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