Agent/AuctionServices/Scraper/Drouot/Drouot.js

452 lines
13 KiB
JavaScript

// Interencheres.js
'use strict';
const {Scraper} = require('../Scraper');
const DrouotData = require('./DrouotData');
class Drouot extends Scraper {
constructor(Url) {
super(Url);
this.platformData = new DrouotData();
this.platformData.getUrlInfo(Url).then((data) => {
if(data.lotID == 0 && data.saleID == 0){
throw new Error('Invalid URL');
}
});
this._Name = 'drouot'
this._PAGE_MAIN = "https://drouot.com/fr/"
this._PAGE_LOGIN = "https://auth.drouot.com/login"
this._USER = "jp.ranu@cogip.de"
this._PWD = "LYPYRKDUsSMH5BaWQxvH#"
this._PATH_SESSION_FILE = ".session/session_drouot.json"
this._PATH_PROTOBUF_FILE = "./AuctionServices/Scraper/Drouot/drouot.proto"
this._BROWSER_TOOL = "playwrightBrowser"
}
getPictures = async ({ page, data}) => {
const PictList = await this.platformData.getPictures(page, this.Url);
console.log('PictList : '+PictList)
return PictList
}
getLotInfos = async ({ page, data}) => {
console.log("getLotInfos "+this._Name+": "+this.Url)
// Navigate the page to a URL
await page.goto(this.Url);
let idLot = await this.platformData.getLotID(this.Url);
console.log('idLot : '+idLot)
// ## LotNumber
let lotNumber = await this.platformData.getLotNumber(page);
console.log('lotNumber : '+lotNumber)
// ## Title
let title = await this.platformData.getLotTitle(page);
console.log('title : '+title)
// ## Estimate
let {EstimateLow, EstimateHigh} = await this.platformData.getEstimate(page);
console.log('EstimateLow : '+EstimateLow)
// ## Description
let Description = await this.platformData.getDescription(page);
//console.log('Description : '+Description)
// ## Fees
let {feesText, fees} = await this.platformData.getFees(page);
console.log('feesText : '+feesText)
console.log('fees : '+fees)
// ################
// ### SALE
let {id_sale, urlSale} = await this.platformData.getSaleID(page);
console.log('SellNumber : '+id_sale)
console.log('url : '+urlSale)
let LotInfos = {
idPlatform: idLot,
platform : this._Name,
url: this.Url,
title: title,
lotNumber: lotNumber,
EstimateLow: EstimateLow,
EstimateHigh: EstimateHigh,
Description: Description,
feesText: feesText,
fees: fees,
saleInfo: {
idSale: id_sale,
url: urlSale
}
}
console.log('LotInfos : '+LotInfos)
return LotInfos
}
getSaleInfos = async ({ page, data}) => {
console.log("getSaleInfos "+this._Name+": "+this.Url)
// Navigate the page to a URL
await page.goto(this.Url);
let {saleID, urlSale} = await this.platformData.getUrlInfo(this.Url);
console.log('saleID : '+saleID)
console.log('urlSale : '+urlSale)
// ## Title
let title = await this.platformData.getSaleTitle(page);
console.log('title : '+title)
// ## Date
let date = await this.platformData.getSaleDate(page);
console.log('date : '+date)
// ## Location
let location = await this.platformData.getSaleLocation(page);
console.log('location : '+location)
// ## SaleHouseName
let saleHouseName = await this.platformData.getSaleHouseName(page);
console.log('saleHouseName : '+saleHouseName)
// ## Status
// ready : ready to be followed
// following : sale is followed by the AuctionAgent
// askStop : sale is followed by the AuctionAgent and the user ask to stop following
// pause : the Sale is stopped by the Auction House and ready to restart
// end : the Sale is ended
let status = 'ready'
let SaleInfo = {
idPlatform: saleID,
platform : this._Name,
url: urlSale,
title: title,
date: date,
location: location,
saleHouseName: saleHouseName,
status: status
}
console.log('SaleInfo : ', JSON.stringify(SaleInfo, null, 2));
return SaleInfo
}
getLotList = async ({ page, data}) => {
console.log("getLotList "+this._Name+": "+this.Url)
// Navigate the page to a URL
await page.goto(this.Url);
const LotList = await this.platformData.getLotList(page);
console.log('LotList : '+LotList)
return LotList
}
// ### Playwright
// ###########################################################################
async CheckCookieDialog(page) {
console.log("-- CheckCookieDialog --")
return new Promise(async (resolve, reject) => {
//let XpathCookieButton = "xpath=//button[contains(@class, 'rgpd') and contains(text(), 'Tout refuser')"
// const CookieButton = await page.$$(XpathCookieButton);
const CookieButton = await page.$('//button[contains(@class, "rgpd") and contains(text(), "Tout refuser")]');
//console.log(CookieButton)
if (CookieButton && await CookieButton.isVisible()) {
console.log("-- Click on CookieButton --")
await CookieButton.click();
}
resolve(true)
})
}
async CheckAndConnect(page) {
return new Promise(async (resolve, reject) => {
await page.goto(this._PAGE_MAIN);
await this.CheckCookieDialog(page);
console.log("-- CheckConnexion --")
//get the Connexion button
let XpathConnexion = "//div[contains(@class, 'btn') and contains(@class, 'ghost') and contains(text(), 'Connexion')]"
const Connexion = await page.$$(XpathConnexion);
// if Connection button found => Login
if (Connexion.length > 0) {
console.log("-- Login --")
await page.goto(this._PAGE_LOGIN);
//get the Email field
//console.log("-- get Email Input --")
//await page.type('#email', this._USER);
await page.fill('#email', this._USER);
//console.log("-- get password Input --")
//wait page.type("#password", this._PWD);
await page.fill('#password', this._PWD);
//await page.screenshot({ path: 'screenshot.png', fullPage: true });
//console.log("-- get ConnexionButton --")
//const [ConnexionButton] = await page.$x("//button[contains(text(), 'Connexion')]");
//await ConnexionButton.evaluate(b => b.click());
await page.click("//button[contains(text(), 'Connexion')]");
//console.log("-- Login wait --")
await page.waitForTimeout(1000);
//resolve(page)
const ConnexionOK = await page.$$("//button[contains(text(), 'Continuer en tant que')]");
//console.log(ConnexionOK)
if (ConnexionOK.length > 0) {
//await ConnexionOK.screenshot({ path: 'screenshot.png', fullPage: true });
//await ConnexionOK.evaluate(b => b.click());
await ConnexionOK[0].click();
await page.waitForTimeout(1000);
await this._saveSession(page)
console.log("-- Connection OK --")
resolve(page)
} else {
console.error("-- !!!! Connection ERROR !!!! --");
reject()
}
// Allready connected
} else {
console.log("-- Allready connected --")
resolve(page)
}
})
}
Live = async (browser) => {
const context = await this._getContext(browser);
console.log("Live "+this._Name+": "+this.Url)
let page = await context.newPage();
page = await this.CheckAndConnect(page);
//init Protobuf Decoder
const protobuf = require("protobufjs");
const root = await protobuf.load(this._PATH_PROTOBUF_FILE);
const LiveBiddingMessage = root.lookupType("drouot.LiveBiddingMessage");
const listener = async (params) => {
let buffer = params.payload;
const err = LiveBiddingMessage.verify(buffer);
if (err) {
throw err;
}
const message = LiveBiddingMessage.decode(buffer);
const BideMessage = LiveBiddingMessage.toObject(message, {enums: String});
let DataLot = null
if(BideMessage.vente && BideMessage.vente.lot && BideMessage.vente.lot.lotId != undefined){
DataLot = await this.platformData.getLiveDataLot(BideMessage.vente.lot.lotId);
}
//console.log('BideMessage Type: '+BideMessage.type+' Lot: '+BideMessage.vente.lot.lotId);
switch (BideMessage.type) {
case 'PING':
break;
case 'PONG':
break;
case 'INIT':
console.log('INIT');
break;
case 'CLOSE':
console.log('CLOSE');
break;
case 'BID':
console.log('BID');
console.log('Lot: '+BideMessage.vente.lot.lotId+' Amount: '+BideMessage.vente.bid.amount);
await this.JucundusBid(
BideMessage.vente.lot.lotId,
Date.now(),
BideMessage.vente.bid.amount,
BideMessage.vente.bid.type
);
break;
case 'SELECT_LOT':
console.log('SELECT_LOT');
console.log('Lot: '+BideMessage.vente.lot.lotId);
//console.log('DataLot : '+DataLot)
await this.JucunduNextItem(
BideMessage.vente.venteId,
Date.now(),
BideMessage.vente.lot.lotId,
DataLot.num,
DataLot.titre,
DataLot.description,
DataLot.estimationBasse,
DataLot.estimationHaute,
DataLot
);
break;
case 'STARTING_PRICE':
console.log('STARTING_PRICE');
await this.JucunduNextItem(
BideMessage.vente.venteId,
Date.now(),
BideMessage.vente.lot.lotId,
DataLot.num,
DataLot.titre,
DataLot.description,
DataLot.estimationBasse,
DataLot.estimationHaute,
DataLot
);
break;
case 'INCREMENT':
console.log('INCREMENT');
break;
case 'TENDERING':
console.log('TENDERING');
console.log('Lot: '+BideMessage.vente.lot.lotId+' Amount: '+BideMessage.vente.bid.amount);
await this.JucunduAuctionedItem(
BideMessage.vente.lot.lotId,
Date.now(),
BideMessage.vente.bid.amount,
BideMessage.vente.lot.state == 'ADJ' ? true : false,
BideMessage.vente.bid.type
);
break;
case 'GENERIC_MESSAGE':
console.log('GENERIC_MESSAGE');
break;
case 'CREATE_LOT':
console.log('CREATE_LOT');
break;
case 'NOT_INTERESTED':
break;
case 'INTERESTED':
break;
case 'ACTIVITY':
break;
case 'NEW_CLIENT':
console.log('NEW_CLIENT');
break;
case 'CLOSED_CLIENT':
break;
case 'KILL':
break;
case 'MULTILOT_REQUEST':
break;
case 'MULTILOT_RESPONSE':
break;
case 'SYNC_PAYMENT_LIMIT':
break;
case 'SWITCH_FREE_BID_AUTHORIZE':
break;
case 'REFRESH_CLIENTS_COUNT':
console.log('REFRESH_CLIENTS_COUNT');
break;
default:
//console.log('Unknown type:', BideMessage);
}
};
// create the live URL
let {saleID} = await this.platformData.getUrlInfo(this.Url);
let UrlLive = this._PAGE_MAIN + "live/bidlive/" + saleID;
let CheckAskStop = null;
let Socket = null;
// Stop the Live
const StopLive = async (params) => {
clearInterval(CheckAskStop);
page.close()
browser.close()
}
try{
console.log('UrlLive : '+UrlLive)
await page.goto(UrlLive, { waitUntil: 'domcontentloaded' });
// intercept Lots Data
await page.route('https://api.drouot.com/drouot/gingolem/api/live/venteInfos/'+saleID+'?lang=fr', async route => {
console.log('GetLiveData')
const response = await route.fetch();
const LotData = await response.json();
this.platformData.setLiveData(LotData.data);
route.continue();
});
page.on('websocket', ws => {
Socket = ws;
Socket.on('framereceived', listener);
console.log('Websocket connected');
});
console.log('UrlLive : reload')
await page.reload();
// check if stop was asked
CheckAskStop = setInterval(async () => {
this.JucundusCheckStop()
.then(AskStop => {
if(AskStop){
StopLive()
}
})
}, 10000); // 10000 milliseconds = 10 seconds
}catch(e){
console.log('Error : '+e)
throw new Error('Error: '+e)
}
}
};
module.exports = Drouot