import axios from 'axios' ; import cheerio from 'cheerio' ; import { db } from '../../db' ; import { ProfileRecord , ContractRecord } from '../../schema' ; import { DateTime } from 'luxon' ; import { CronTask } from '../../schema/cron' ; const limit = 20 ; export const TaskDownloadContracts = { id : 'download-contracts' , name : 'Download contracts from https://smlouvy.gov.cz/' , exec : async ( ) => { const profiles = await db < ProfileRecord > ( 'profiles' ) ; console . log ( 'Found ' + profiles . length + ' profiles to download contracts for.' ) ; for ( const profile of profiles ) { try { await downloadContracts ( profile ) ; } catch ( err ) { console . error ( "Couldn't download contracts for " + profile . name + ': ' + err . message ) ; } } } , } ; async function downloadContracts ( profile ) { console . log ( '---' ) ; console . log ( profile . name ) ; if ( ! profile . ico && ! profile . databox ) { console . log ( 'ICO or databox not available, aborting.' ) ; return ; } let url = `https://smlouvy.gov.cz/vyhledavani?searchResultList-limit=${ limit }&all_versions=0&do=searchResultList-setLimit` ; if ( profile . databox ) { url += `&party_box=${ profile . databox }` ; } else { url += `&subject_idnum=${ profile . ico }` ; } const html = ( await axios . get ( url ) ) . data ; const $ = cheerio . load ( html ) ; const contracts = [ ] ; $ ( 'tr' , '#snippet-searchResultList-list' ) . each ( ( i , row ) => { if ( i === 0 ) return ; const items = $ ( row ) . children ( ) ; const amount = parseAmount ( items . eq ( 4 ) . text ( ) . trim ( ) ) ; const contract = { profileId : profile . id , title : items . eq ( 1 ) . text ( ) . trim ( ) , date : parseDate ( items . eq ( 3 ) . text ( ) . trim ( ) ) , amount : amount [ 0 ] , currency : amount [ 1 ] , counterparty : items . eq ( 5 ) . text ( ) . trim ( ) , url : 'https://smlouvy.gov.cz' + items . eq ( 6 ) . find ( 'a' ) . attr ( 'href' ) , } as ContractRecord ; contracts . push ( contract ) ; } ) ; await db ( 'data.contracts' ) . where ( { profileId : profile . id } ) . delete ( ) ; await db ( 'data.contracts' ) . insert ( contracts ) ; console . log ( 'Updated ' + contracts . length + ' contracts' ) ; } function parseAmount ( original ) { if ( original . trim ( ) === 'Neuvedeno' ) return [ null , null ] ; const matches = original . match ( /([\d ]+) ([A-Z]+)/ ) ; if ( ! matches || matches . length < 3 ) return [ null , null ] ; return [ Number ( matches [ 1 ] . replace ( /[^\d]/g , '' ) ) , matches [ 2 ] ] ; } function parseDate ( dateString ) { const matches = dateString . match ( /(\d{1,2})\.(\d{1,2})\.(\d{4})/ ) ; if ( matches && matches . length > 2 ) return DateTime . local ( Number ( matches [ 3 ] ) , Number ( matches [ 2 ] ) , Number ( matches [ 1 ] ) ) . toISODate ( ) ; return DateTime . local ( ) . toISODate ( ) ; }