11// Code for searching APOLLO MAPPING API
22
33import ky from 'ky'
4- import { Providers , maxAbs , filterFeaturesWithSearchParams } from './search-utilities'
4+ import { Providers , maxAbs , filterFeaturesWithSearchParams , processInChunks } from './search-utilities'
55import { v4 as uuidv4 } from 'uuid'
66import bboxPolygon from '@turf/bbox-polygon'
77import { log } from '../utilities'
8- import type GeoJSON from 'react-map-gl'
9-
10- // https://imagehunter.apollomapping.com/
118
129const APOLLO_API_URL = 'https://imagehunter-api.apollomapping.com'
1310const APOLLO_DOMAIN = 'https://imagehunter.apollomapping.com'
1411
1512const searchApollo = async ( searchSettings , apolloApikey , searchPolygon : any | null = null , setters : any | null = null ) : Promise < any > => {
13+
14+ const generateXAuthToken = async ( ) : Promise < string > => {
15+ const now = new Date ( ) ;
16+ const day = now . getUTCDate ( ) ;
17+ const hour = now . getUTCHours ( ) ;
18+ const secret = "iGsZ1wMw8xERUZrxNPvBt2TlFTFcN3P2" ;
19+ const raw = `${ day } ${ hour } ${ secret } ` ;
20+ const msgUint8 = new TextEncoder ( ) . encode ( raw ) ; // encode string to Uint8Array
21+ const hashBuffer = await window . crypto . subtle . digest ( "SHA-256" , msgUint8 ) ; // hash
22+ const hashArray = Array . from ( new Uint8Array ( hashBuffer ) ) ; // buffer -> byte array
23+ const hashHex = hashArray . map ( b => b . toString ( 16 ) . padStart ( 2 , "0" ) ) . join ( "" ) ; // byte array -> hex string
24+
25+ return hashHex ;
26+ }
27+
1628 const apolloPayload = {
1729 startDate : searchSettings . startDate . toISOString ( ) . substring ( 0 , 19 ) , // '1970-01-01T12:00:00',
1830 endDate : searchSettings . endDate . toISOString ( ) . substring ( 0 , 19 ) ,
@@ -29,32 +41,17 @@ const searchApollo = async (searchSettings, apolloApikey, searchPolygon: any | n
2941 stereo : false ,
3042 seasonal : false ,
3143 }
44+
3245 const apolloPayloadBody = new URLSearchParams ( apolloPayload as any ) . toString ( )
3346 // Better have a look at maxar payload construction
3447
3548 // WIP, returns 401 unauthorized because origin and referer headers are overwritten on post
36- // return {
37- // searchResultsJson: {
38- // 'features': [],
39- // type: 'FeatureCollection'
40- // }
41- // }
4249
4350 // Returns 401 Unauthorized probably because request is actually sent to http non-sll server url because dev server has no tls and origin and referer are overwritten by browser to localhost
4451 // Tried using a CORS proxy, with no luck like [cors-anywhere](https://github.com/Rob--W/cors-anywhere/#documentation) public one or [allorigins](https://allorigins.win/) or any recent one listed [here](https://nordicapis.com/10-free-to-use-cors-proxies/)
4552
46- // const requestOptions = {headers: { 'Host': APOLLO_DOMAIN, 'Origin': APOLLO_DOMAIN, 'Referer': APOLLO_DOMAIN, }, method: 'POST'};
47- // let apolloRequest = new Request(APOLLO_SEARCH_URL, requestOptions);
4853 const apolloRequest = `${ APOLLO_API_URL } /ajax/search`
49- // let apolloRequest = 'https://api.allorigins.win/get?url=https%3A%2F%2Freqres.in%2Fapi%2Fusers'
50- // let apolloRequest = 'https://test.cors.workers.dev/?https%3A%2F%2Freqres.in%2Fapi%2Fusers'
51- // apolloRequest = 'http://localhost:8010/proxy/ajax/search'
52- // let apolloRequest = `https://api.allorigins.win/post?url=${encodeURIComponent(APOLLO_SEARCH_URL)}`
53- // const testPayload = {
54- // name: 'morpheudezetterz',
55- // job: 'letrezterzder',
56- // }
57-
54+ const token = await generateXAuthToken ( )
5855 const apolloResultsRaw = await ky
5956 . post ( apolloRequest , {
6057 headers : {
@@ -63,9 +60,9 @@ const searchApollo = async (searchSettings, apolloApikey, searchPolygon: any | n
6360 Referer : APOLLO_DOMAIN ,
6461 'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8' ,
6562 'Content-Length' : `${ apolloPayloadBody . length } ` ,
66- // 'Content-Length': '867'
63+ "X-Auth-Token" : token ,
6764 } ,
68- body : apolloPayloadBody , // testPayload, apolloPayload, fakePayload
65+ body : apolloPayloadBody ,
6966 } )
7067 . json ( )
7168
@@ -79,7 +76,7 @@ const searchApollo = async (searchSettings, apolloApikey, searchPolygon: any | n
7976 // A better way could be to add a callback on hover in datagrid if preview does not exist to retrieve its url
8077 // Initiate search for previews/thumbnails
8178 // TODO REDO
82- void getApolloPreviewsAsync ( searchResultsJson ) . then ( ( results ) => {
79+ void getApolloPreviewsAsync ( searchResultsJson , token ) . then ( ( results ) => {
8380 if ( setters ) {
8481 // const searchResults = {
8582 // input: searchPolygon,
@@ -131,58 +128,55 @@ const formatApolloResults = (apolloResultsRaw): GeoJSON.FeatureCollection => {
131128}
132129
133130const timer = async ( ms ) : Promise < any > => await new Promise ( ( resolve ) => setTimeout ( resolve , ms ) )
134-
135- const getApolloPreviewsAsync = async ( apolloResults ) : Promise < void > => {
136- const chunkSize = 10
137- // Send batches of chunkSize POST requests to ApolloMapping API server
138- for ( let i = 0 ; i < apolloResults . features . length ; i += chunkSize ) {
139- const chunk = apolloResults . features . slice ( i , i + chunkSize )
140- const errors : string [ ] = [ ]
141- // Await all promises of chunk fetching
142- await Promise . all (
143- chunk . map ( async ( feature ) => {
144- const previewPayload = {
145- catid : feature . properties . id ,
146- satellite : 'scene' ,
147- satelliteShortName : feature . properties . providerProperties . satelliteShortName ,
148- isRefresh : false ,
149- forceHighestQuality : false , // Todo: test true
131+ const getApolloPreviewsAsync = async ( apolloResults , token ) : Promise < void > => {
132+ const errors : string [ ] = [ ] ;
133+
134+ await processInChunks (
135+ async ( feature : any ) => {
136+ const previewPayload = {
137+ catid : feature . properties . id ,
138+ satellite : 'scene' ,
139+ satelliteShortName : feature . properties . providerProperties . satelliteShortName ,
140+ isRefresh : false ,
141+ forceHighestQuality : false ,
142+ } ;
143+
144+ const previewPayloadBody = new URLSearchParams ( previewPayload as any ) . toString ( ) ;
145+
146+ await ky
147+ . post ( `${ APOLLO_API_URL } /ajax/get_preview_image` , {
148+ headers : {
149+ Host : APOLLO_DOMAIN ,
150+ Origin : APOLLO_DOMAIN ,
151+ Referer : APOLLO_DOMAIN ,
152+ 'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8' ,
153+ 'Content-Length' : `${ previewPayloadBody . length } ` ,
154+ "x-auth-token" : token ,
155+ } ,
156+ body : previewPayloadBody ,
157+ timeout : 30000 ,
158+ } )
159+ . json ( )
160+ . then ( ( previewUrlObject ) => {
161+ feature . properties . thumbnail_uri = `${ APOLLO_API_URL } ${ ( previewUrlObject as any ) . path } ` ;
162+ feature . properties . preview_uri = feature . properties . thumbnail_uri ;
163+ } )
164+ . catch ( ( ) => {
165+ errors . push ( 'Error during ky post request to get Apollo preview image' ) ;
166+ } ) ;
167+ } ,
168+ {
169+ items : apolloResults . features ,
170+ chunkSize : 10 ,
171+ delayBetweenChunks : 500 ,
172+ usePromiseAllSettled : false , // Stop on error like original
173+ onChunkComplete : ( chunk , chunkIndex , totalChunks ) => {
174+ if ( errors . length > 0 ) {
175+ throw new Error ( `ApolloMapping Previews fetch - Error during chunk ${ chunkIndex } ` ) ;
150176 }
151- const previewPayloadBody = new URLSearchParams ( previewPayload as any ) . toString ( )
152- // console.log('Fetching preview via ky.post for ', feature.properties.id)
153- // console.log('REQUESTING APOLLO PREVIEW', previewPayload.catid, previewPayload, previewUrlObject, feature.properties.thumbnail_uri)
154- await ky
155- . post ( `${ APOLLO_API_URL } /ajax/get_preview_image` , {
156- headers : {
157- Host : APOLLO_DOMAIN ,
158- Origin : APOLLO_DOMAIN ,
159- Referer : APOLLO_DOMAIN ,
160- 'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8' ,
161- 'Content-Length' : `${ previewPayloadBody . length } ` ,
162- } ,
163- body : previewPayloadBody ,
164- timeout : 30000 ,
165- } )
166- . json ( )
167- . then ( ( previewUrlObject ) => {
168- // console.log('ApolloMapping, found preview ', previewUrlObject)
169- feature . properties . thumbnail_uri = `${ APOLLO_API_URL } ${ ( previewUrlObject as any ) . path as string } `
170- feature . properties . preview_uri = feature . properties . thumbnail_uri
171- } )
172- . catch ( ( ) => {
173- errors . push ( 'Error during ky post request to get Apollo preview image' )
174- } )
175- } )
176- )
177-
178- if ( errors . length > 0 ) {
179- log ( `ApolloMapping Previews fetch - Catched error during chunk previews fetch for loop ${ i } , so break master loop by return` )
180- throw new Error ( `ApolloMapping Previews fetch - Catched error during chunk previews fetch for loop ${ i } , so break master loop by return` )
181- // throw new Error(errors.join());
182- // return
177+ }
183178 }
184- await timer ( 3000 )
185- }
186- }
179+ ) ;
180+ } ;
187181
188182export default searchApollo
0 commit comments