@illgrenoble/visa-print-client
Version:
[](https://badge.fury.io/js/%40illgrenoble%2Fvisa-print-client)
198 lines • 34.2 kB
JavaScript
import { Injectable } from "@angular/core";
import { BehaviorSubject } from "rxjs";
import { PrintEvent, ErrorEvent, PrintJobChunkEvent, PrintJobAvailableEvent } from "../models";
import io from 'socket.io-client';
import * as i0 from "@angular/core";
class VisaPrintService {
constructor() {
this._connections = [];
this._pdfDidOpen = false;
}
static { this._connectionCounter = 1; }
connect(data, connectionOptions) {
connectionOptions = connectionOptions || {};
const socketOptions = {
transports: ['websocket'],
timeout: 1000,
reconnection: true,
reconnectionDelayMax: 10000,
...connectionOptions
};
if (data.path) {
socketOptions.path = data.path;
}
if (data.token) {
socketOptions.auth = {
token: data.token
};
socketOptions.query = {
token: data.token
};
}
const connectionId = `print-connection-${VisaPrintService._connectionCounter++} `;
const location = window.location;
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
const hostname = location.hostname;
const port = location.port ? `:${location.port}` : '';
const host = data.host ? `${data.host}` : `${protocol}//${hostname}${port}`;
const socket = io(`${host}`, socketOptions);
const printEvents$ = new BehaviorSubject(new PrintEvent({ type: 'CONNECTING', connectionId }));
const connection = {
id: connectionId,
event$: printEvents$,
socket: socket,
jobs: new Map(),
printables: [],
};
this._connections.push(connection);
socket.on('connect', () => {
printEvents$.next(new PrintEvent({ type: 'CONNECTED', connectionId }));
});
socket.on('print_job_handled', (jobId) => {
connection.printables = connection.printables.filter(printable => printable.jobId !== jobId);
printEvents$.next(new PrintEvent({ type: 'PRINT_JOB_HANDLED', connectionId, jobId }));
});
socket.on('connect_error', (error) => {
printEvents$.next(new PrintEvent({ type: 'ERROR', connectionId, data: new ErrorEvent({ type: 'CONNECTION_ERROR', message: error.message }) }));
});
socket.on('disconnect', () => {
printEvents$.next(new PrintEvent({ type: 'DISCONNECTED', connectionId }));
});
socket.on('error', (error) => {
printEvents$.next(new PrintEvent({ type: 'ERROR', connectionId, data: new ErrorEvent({ type: 'ERROR', message: error.message }) }));
});
socket.on('exception', (e) => {
printEvents$.next(new PrintEvent({ type: 'ERROR', connectionId, data: new ErrorEvent({ type: 'EXCEPTION', message: e.message }) }));
});
socket.on('print_job_start', (jobId) => {
printEvents$.next(new PrintEvent({ type: 'PRINT_JOB_TRANSFER_STARTED', connectionId, jobId }));
});
socket.on('print_job_end', (jobId) => {
printEvents$.next(new PrintEvent({ type: 'PRINT_JOB_TRANSFER_TERMINATED', connectionId, jobId }));
});
socket.on('print_job_data', (printJob, ack) => {
const { jobId, chunkId, chunkCount, chunkLength, data } = printJob;
if (chunkLength !== data.length) {
console.error(`printer job data of chunk ${chunkId}/${chunkCount} for job ${jobId} ${printJob.fileName} has incorrect length`);
printEvents$.next(new PrintEvent({ type: 'ERROR', connectionId, data: new ErrorEvent({ type: 'ERROR', message: 'Incorrect data length in chunk' }) }));
ack(false);
return;
}
ack(true);
printEvents$.next(new PrintEvent({ type: 'PRINT_JOB_CHUNK_RECEIVED', connectionId, jobId, data: new PrintJobChunkEvent({ jobId, chunkId, chunkCount, chunkLength }) }));
this.handlePrintJob(connection, printJob);
});
return printEvents$;
}
disconnect(connectionId) {
const connection = this._connections.find(connection => connection.id === connectionId);
if (connection) {
connection.socket.disconnect();
}
this._connections = this._connections.filter(connection => connection.id !== connectionId);
}
enablePrinting(connectionId) {
const connection = this._connections.find(connection => connection.id === connectionId);
if (connection) {
connection.socket.emit('enable_print', null, (data) => {
connection.event$.next(new PrintEvent({ type: 'PRINT_ENABLED', connectionId }));
});
}
}
disablePrinting(connectionId) {
const connection = this._connections.find(connection => connection.id === connectionId);
if (connection) {
connection.socket.emit('disable_print', null, (data) => {
connection.event$.next(new PrintEvent({ type: 'PRINT_DISABLED', connectionId }));
});
}
}
openPrintable(connectionId, jobId) {
const connection = this._connections.find(connection => connection.id === connectionId);
if (connection) {
const printable = connection.printables.find(printable => printable.jobId === jobId);
if (printable) {
connection.socket.emit('print_job_handled', printable.jobId);
connection.printables = connection.printables.filter(printable => printable.jobId !== jobId);
this.openPDF(printable.data, connection, jobId);
}
}
}
initialiseReceiver() {
if (!this._iframe) {
this._iframe = document.createElement('iframe');
this._iframe.style.display = 'none';
document.body.appendChild(this._iframe);
this._iframe.onload = () => {
URL.revokeObjectURL(this._pdfUrl);
this._iframe.focus();
try {
this._iframe.contentWindow?.print();
this._pdfDidOpen = true;
}
catch (error) {
}
};
}
}
handlePrintJob(connection, printJob) {
const { jobId, chunkId, chunkCount } = printJob;
if (!connection.jobs.has(jobId)) {
connection.jobs.set(jobId, []);
}
connection.jobs.get(jobId)?.push(printJob);
if (chunkId === chunkCount) {
this.processJob(connection, printJob);
}
}
processJob(connection, printJob) {
const { jobId, chunkCount, fileLength, fileName } = printJob;
const chunks = connection.jobs.get(jobId);
if (chunks) {
// Remove from jobs
connection.jobs.delete(jobId);
// Concatenate all the data
if (chunks.length > 0 && chunks.length === chunkCount) {
const base64 = chunks.reduce((acc, chunk) => {
return acc + chunk.data;
}, '');
const data = atob(base64);
if (data.length === fileLength) {
connection.printables.push({ jobId, data });
connection.event$.next(new PrintEvent({ type: 'PRINT_JOB_AVAILABLE', connectionId: connection.id, data: new PrintJobAvailableEvent({ jobId, fileLength, fileName }) }));
}
else {
connection.event$.next(new PrintEvent({ type: 'ERROR', connectionId: connection.id, data: new ErrorEvent({ type: 'ERROR', message: 'Processes print data has inconsistent length' }) }));
}
}
}
}
openPDF(data, connection, jobId) {
// Convert to binary data
const bytes = new Uint8Array(data.length);
for (let i = 0; i < data.length; i++) {
bytes[i] = data.charCodeAt(i);
}
const blob = new Blob([bytes], { type: 'application/pdf' });
this._pdfUrl = URL.createObjectURL(blob);
this.initialiseReceiver();
// Set the pdf in the iframe
this._pdfDidOpen = false;
this._iframe.src = this._pdfUrl;
setTimeout(() => {
if (this._pdfDidOpen === false) {
connection.event$.next(new PrintEvent({ type: 'PRINT_DIALOG_FAILED', connectionId: connection.id, jobId }));
}
}, 200);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.7", ngImport: i0, type: VisaPrintService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.7", ngImport: i0, type: VisaPrintService, providedIn: 'root' }); }
}
export { VisaPrintService };
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.7", ngImport: i0, type: VisaPrintService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlzYS1wcmludC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGliL3NyYy9zZXJ2aWNlcy92aXNhLXByaW50LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUMsZUFBZSxFQUFzQixNQUFNLE1BQU0sQ0FBQztBQUMxRCxPQUFPLEVBQ0gsVUFBVSxFQUVWLFVBQVUsRUFDVixrQkFBa0IsRUFDbEIsc0JBQXNCLEVBQ3pCLE1BQU0sV0FBVyxDQUFDO0FBQ25CLE9BQU8sRUFBRSxNQUFNLGtCQUFrQixDQUFBOztBQXlCakMsTUFFZSxnQkFBZ0I7SUFGL0I7UUFJWSxpQkFBWSxHQUFpQixFQUFFLENBQUM7UUFLaEMsZ0JBQVcsR0FBRyxLQUFLLENBQUM7S0FtTi9CO2FBdk5rQix1QkFBa0IsR0FBRyxDQUFDLEFBQUosQ0FBSztJQU0vQixPQUFPLENBQUMsSUFBb0IsRUFBRSxpQkFBMkQ7UUFFNUYsaUJBQWlCLEdBQUcsaUJBQWlCLElBQUksRUFBRSxDQUFDO1FBQzVDLE1BQU0sYUFBYSxHQUE0QztZQUMzRCxVQUFVLEVBQUUsQ0FBQyxXQUFXLENBQUM7WUFDekIsT0FBTyxFQUFFLElBQUk7WUFDYixZQUFZLEVBQUUsSUFBSTtZQUNsQixvQkFBb0IsRUFBRSxLQUFLO1lBQzNCLEdBQUcsaUJBQWlCO1NBQ3ZCLENBQUE7UUFFRCxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUU7WUFDWCxhQUFhLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7U0FDbEM7UUFFRCxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDWixhQUFhLENBQUMsSUFBSSxHQUFHO2dCQUNqQixLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUs7YUFDcEIsQ0FBQztZQUNGLGFBQWEsQ0FBQyxLQUFLLEdBQUc7Z0JBQ2xCLEtBQUss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QUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDbEMsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDakM7UUFDRCxNQUFNLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFLEVBQUMsSUFBSSxFQUFFLGlCQUFpQixFQUFDLENBQUMsQ0FBQztRQUMxRCxJQUFJLENBQUMsT0FBTyxHQUFHLEdBQUcsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFekMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFFMUIsNEJBQTRCO1FBQzVCLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7UUFDaEMsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUNaLElBQUksSUFBSSxDQUFDLFdBQVcsS0FBSyxLQUFLLEVBQUU7Z0JBQzVCLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksVUFBVSxDQUFDLEVBQUMsSUFBSSxFQUFFLHFCQUFxQixFQUFFLFlBQVksRUFBRSxVQUFVLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUMsQ0FBQzthQUM3RztRQUNMLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUVaLENBQUM7OEdBek5VLGdCQUFnQjtrSEFBaEIsZ0JBQWdCLGNBRGYsTUFBTTs7U0FDUCxnQkFBZ0I7MkZBQWhCLGdCQUFnQjtrQkFGOUIsVUFBVTttQkFBQztvQkFDUixVQUFVLEVBQUUsTUFBTTtpQkFDckIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0luamVjdGFibGV9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQge0JlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSwgU3ViamVjdH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7XG4gICAgUHJpbnRFdmVudCxcbiAgICBQcmludEpvYixcbiAgICBFcnJvckV2ZW50LFxuICAgIFByaW50Sm9iQ2h1bmtFdmVudCxcbiAgICBQcmludEpvYkF2YWlsYWJsZUV2ZW50XG59IGZyb20gXCIuLi9tb2RlbHNcIjtcbmltcG9ydCBpbyBmcm9tICdzb2NrZXQuaW8tY2xpZW50J1xuaW1wb3J0ICogYXMgU29ja2V0SU9DbGllbnQgZnJvbSAnc29ja2V0LmlvLWNsaWVudCdcbmltcG9ydCBTb2NrZXQgPSBTb2NrZXRJT0NsaWVudC5Tb2NrZXQ7XG5pbXBvcnQge01hbmFnZXJPcHRpb25zfSBmcm9tIFwic29ja2V0LmlvLWNsaWVudC9idWlsZC9lc20vbWFuYWdlclwiO1xuaW1wb3J0IHtTb2NrZXRPcHRpb25zfSBmcm9tIFwic29ja2V0LmlvLWNsaWVudC9idWlsZC9lc20vc29ja2V0XCI7XG5cbmV4cG9ydCB0eXBlIENvbm5lY3Rpb25EYXRhID0ge1xuICAgIGhvc3Q/OiBzdHJpbmc7XG4gICAgcGF0aD86IHN0cmluZztcbiAgICB0b2tlbj86IHN0cmluZztcbn1cblxudHlwZSBQcmludGFibGUgPSB7XG4gICAgam9iSWQ6IG51bWJlcjtcbiAgICBkYXRhOiBzdHJpbmc7XG59XG5cbmV4cG9ydCB0eXBlIENvbm5lY3Rpb24gPSB7XG4gICAgaWQ6IHN0cmluZztcbiAgICBzb2NrZXQ6IFNvY2tldDtcbiAgICBldmVudCQ6IFN1YmplY3Q8UHJpbnRFdmVudD47XG4gICAgam9iczogTWFwPG51bWJlciwgUHJpbnRKb2JbXT47XG4gICAgcHJpbnRhYmxlczogUHJpbnRhYmxlW107XG59XG5cbkBJbmplY3RhYmxlKHtcbiAgICBwcm92aWRlZEluOiAncm9vdCdcbn0pZXhwb3J0IGNsYXNzIFZpc2FQcmludFNlcnZpY2Uge1xuXG4gICAgcHJpdmF0ZSBfY29ubmVjdGlvbnM6IENvbm5lY3Rpb25bXSA9IFtdO1xuICAgIHByaXZhdGUgc3RhdGljIF9jb25uZWN0aW9uQ291bnRlciA9IDE7XG5cbiAgICBwcml2YXRlIF9pZnJhbWU6IEhUTUxJRnJhbWVFbGVtZW50O1xuICAgIHByaXZhdGUgX3BkZlVybDogc3RyaW5nO1xuICAgIHByaXZhdGUgX3BkZkRpZE9wZW4gPSBmYWxzZTtcblxuICAgIHB1YmxpYyBjb25uZWN0KGRhdGE6IENvbm5lY3Rpb25EYXRhLCBjb25uZWN0aW9uT3B0aW9ucz86IFBhcnRpYWw8TWFuYWdlck9wdGlvbnMgJiBTb2NrZXRPcHRpb25zPik6IE9ic2VydmFibGU8UHJpbnRFdmVudD4ge1xuXG4gICAgICAgIGNvbm5lY3Rpb25PcHRpb25zID0gY29ubmVjdGlvbk9wdGlvbnMgfHwge307XG4gICAgICAgIGNvbnN0IHNvY2tldE9wdGlvbnM6IFBhcnRpYWw8TWFuYWdlck9wdGlvbnMgJiBTb2NrZXRPcHRpb25zPiA9IHtcbiAgICAgICAgICAgIHRyYW5zcG9ydHM6IFsnd2Vic29ja2V0J10sXG4gICAgICAgICAgICB0aW1lb3V0OiAxMDAwLFxuICAgICAgICAgICAgcmVjb25uZWN0aW9uOiB0cnVlLFxuICAgICAgICAgICAgcmVjb25uZWN0aW9uRGVsYXlNYXg6IDEwMDAwLFxuICAgICAgICAgICAgLi4uY29ubmVjdGlvbk9wdGlvbnNcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkYXRhLnBhdGgpIHtcbiAgICAgICAgICAgIHNvY2tldE9wdGlvbnMucGF0aCA9IGRhdGEucGF0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkYXRhLnRva2VuKSB7XG4gICAgICAgICAgICBzb2NrZXRPcHRpb25zLmF1dGggPSB7XG4gICAgICAgICAgICAgICAgdG9rZW46IGRhdGEudG9rZW5cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBzb2NrZXRPcHRpb25zLnF1ZXJ5ID0ge1xuICAgICAgICAgICAgICAgIHRva2VuOiBkYXRhLnRva2VuXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjb25uZWN0aW9uSWQgPSBgcHJpbnQtY29ubmVjdGlvbi0ke1Zpc2FQcmludFNlcnZpY2UuX2Nvbm5lY3Rpb25Db3VudGVyKyt9IGA7XG5cbiAgICAgICAgY29uc3QgbG9jYXRpb24gPSB3aW5kb3cubG9jYXRpb247XG4gICAgICAgIGNvbnN0IHByb3RvY29sID0gbG9jYXRpb24ucHJvdG9jb2wgPT09ICdodHRwczonID8gJ3dzczonIDogJ3dzOic7XG4gICAgICAgIGNvbnN0IGhvc3RuYW1lID0gbG9jYXRpb24uaG9zdG5hbWU7XG4gICAgICAgIGNvbnN0IHBvcnQgPSBsb2NhdGlvbi5wb3J0ID8gYDoke2xvY2F0aW9uLnBvcnR9YCA6ICcnO1xuXG4gICAgICAgIGNvbnN0IGhvc3QgPSBkYXRhLmhvc3QgPyBgJHtkYXRhLmhvc3R9YCA6IGAke3Byb3RvY29sfS8vJHtob3N0bmFtZX0ke3BvcnR9YDtcbiAgICAgICAgY29uc3Qgc29ja2V0ID0gaW8oYCR7aG9zdH1gLCBzb2NrZXRPcHRpb25zKTtcblxuICAgICAgICBjb25zdCBwcmludEV2ZW50cyQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFByaW50RXZlbnQ+KG5ldyBQcmludEV2ZW50KHt0eXBlOiAnQ09OTkVDVElORycsIGNvbm5lY3Rpb25JZH0pKTtcbiAgICAgICAgY29uc3QgY29ubmVjdGlvbjogQ29ubmVjdGlvbiA9IHtcbiAgICAgICAgICAgIGlkOiBjb25uZWN0aW9uSWQsXG4gICAgICAgICAgICBldmVudCQ6IHByaW50RXZlbnRzJCxcbiAgICAgICAgICAgIHNvY2tldDogc29ja2V0LFxuICAgICAgICAgICAgam9iczogbmV3IE1hcDxudW1iZXIsIFByaW50Sm9iW10+KCksXG4gICAgICAgICAgICBwcmludGFibGVzOiBbXSxcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLl9jb25uZWN0aW9ucy5wdXNoKGNvbm5lY3Rpb24pO1xuXG4gICAgICAgIHNvY2tldC5vbignY29ubmVjdCcsICgpID0+IHtcbiAgICAgICAgICAgIHByaW50RXZlbnRzJC5uZXh0KG5ldyBQcmludEV2ZW50KHt0eXBlOiAnQ09OTkVDVEVEJywgY29ubmVjdGlvbklkfSkpO1xuICAgICAgICB9KTtcblxuICAgICAgICBzb2NrZXQub24oJ3ByaW50X2pvYl9oYW5kbGVkJywgKGpvYklkOiBudW1iZXIpID0+IHtcbiAgICAgICAgICAgIGNvbm5lY3Rpb24ucHJpbnRhYmxlcyA9IGNvbm5lY3Rpb24ucHJpbnRhYmxlcy5maWx0ZXIocHJpbnRhYmxlID0+IHByaW50YWJsZS5qb2JJZCAhPT0gam9iSWQpO1xuICAgICAgICAgICAgcHJpbnRFdmVudHMkLm5leHQobmV3IFByaW50RXZlbnQoe3R5cGU6ICdQUklOVF9KT0JfSEFORExFRCcsIGNvbm5lY3Rpb25JZCwgam9iSWR9KSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNvY2tldC5vbignY29ubmVjdF9lcnJvcicsIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgcHJpbnRFdmVudHMkLm5leHQobmV3IFByaW50RXZlbnQoe3R5cGU6ICdFUlJPUicsIGNvbm5lY3Rpb25JZCwgZGF0YTogbmV3IEVycm9yRXZlbnQoe3R5cGU6ICdDT05ORUNUSU9OX0VSUk9SJywgbWVzc2FnZTogZXJyb3IubWVzc2FnZX0pfSkpO1xuICAgICAgICB9KTtcblxuICAgICAgICBzb2NrZXQub24oJ2Rpc2Nvbm5lY3QnLCAoKSA9PiB7XG4gICAgICAgICAgICBwcmludEV2ZW50cyQubmV4dChuZXcgUHJpbnRFdmVudCh7dHlwZTogJ0RJU0NPTk5FQ1RFRCcsIGNvbm5lY3Rpb25JZH0pKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc29ja2V0Lm9uKCdlcnJvcicsIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgcHJpbnRFdmVudHMkLm5leHQobmV3IFByaW50RXZlbnQoe3R5cGU6ICdFUlJPUicsIGNvbm5lY3Rpb25JZCwgZGF0YTogbmV3IEVycm9yRXZlbnQoe3R5cGU6ICdFUlJPUicsIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2V9KX0pKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc29ja2V0Lm9uKCdleGNlcHRpb24nLCAoZSkgPT4ge1xuICAgICAgICAgICAgcHJpbnRFdmVudHMkLm5leHQobmV3IFByaW50RXZlbnQoe3R5cGU6ICdFUlJPUicsIGNvbm5lY3Rpb25JZCwgZGF0YTogbmV3IEVycm9yRXZlbnQoe3R5cGU6ICdFWENFUFRJT04nLCBtZXNzYWdlOiBlLm1lc3NhZ2V9KX0pKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc29ja2V0Lm9uKCdwcmludF9qb2Jfc3RhcnQnLCAoam9iSWQ6IG51bWJlcikgPT4ge1xuICAgICAgICAgICAgcHJpbnRFdmVudHMkLm5leHQobmV3IFByaW50RXZlbnQoe3R5cGU6ICdQUklOVF9KT0JfVFJBTlNGRVJfU1RBUlRFRCcsIGNvbm5lY3Rpb25JZCwgam9iSWR9KSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNvY2tldC5vbigncHJpbnRfam9iX2VuZCcsIChqb2JJZDogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICBwcmludEV2ZW50cyQubmV4dChuZXcgUHJpbnRFdmVudCh7dHlwZTogJ1BSSU5UX0pPQl9UUkFOU0ZFUl9URVJNSU5BVEVEJywgY29ubmVjdGlvbklkLCBqb2JJZH0pKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc29ja2V0Lm9uKCdwcmludF9qb2JfZGF0YScsIChwcmludEpvYjogUHJpbnRKb2IsIGFjaykgPT4ge1xuICAgICAgICAgICAgY29uc3Qge2pvYklkLCBjaHVua0lkLCBjaHVua0NvdW50LCBjaHVua0xlbmd0aCwgZGF0YX0gPSBwcmludEpvYjtcbiAgICAgICAgICAgIGlmIChjaHVua0xlbmd0aCAhPT0gZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBwcmludGVyIGpvYiBkYXRhIG9mIGNodW5rICR7Y2h1bmtJZH0vJHtjaHVua0NvdW50fSBmb3Igam9iICR7am9iSWR9ICR7cHJpbnRKb2IuZmlsZU5hbWV9IGhhcyBpbmNvcnJlY3QgbGVuZ3RoYClcbiAgICAgICAgICAgICAgICBwcmludEV2ZW50cyQubmV4dChuZXcgUHJpbnRFdmVudCh7dHlwZTogJ0VSUk9SJywgY29ubmVjdGlvbklkLCBkYXRhOiBuZXcgRXJyb3JFdmVudCh7dHlwZTogJ0VSUk9SJywgbWVzc2FnZTogJ0luY29ycmVjdCBkYXRhIGxlbmd0aCBpbiBjaHVuayd9KX0pKTtcbiAgICAgICAgICAgICAgICBhY2soZmFsc2UpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYWNrKHRydWUpO1xuICAgICAgICAgICAgcHJpbnRFdmVudHMkLm5leHQobmV3IFByaW50RXZlbnQoe3R5cGU6ICdQUklOVF9KT0JfQ0hVTktfUkVDRUlWRUQnLCBjb25uZWN0aW9uSWQsIGpvYklkLCBkYXRhOiBuZXcgUHJpbnRKb2JDaHVua0V2ZW50KHtqb2JJZCwgY2h1bmtJZCwgY2h1bmtDb3VudCwgY2h1bmtMZW5ndGh9KX0pKTtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlUHJpbnRKb2IoY29ubmVjdGlvbiwgcHJpbnRKb2IpO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gcHJpbnRFdmVudHMkO1xuICAgIH1cblxuICAgIHB1YmxpYyBkaXNjb25uZWN0KGNvbm5lY3Rpb25JZDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLl9jb25uZWN0aW9ucy5maW5kKGNvbm5lY3Rpb24gPT4gY29ubmVjdGlvbi5pZCA9PT0gY29ubmVjdGlvbklkKTtcbiAgICAgICAgaWYgKGNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGNvbm5lY3Rpb24uc29ja2V0LmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9jb25uZWN0aW9ucyA9IHRoaXMuX2Nvbm5lY3Rpb25zLmZpbHRlcihjb25uZWN0aW9uID0+IGNvbm5lY3Rpb24uaWQgIT09IGNvbm5lY3Rpb25JZCk7XG4gICAgfVxuXG4gICAgcHVibGljIGVuYWJsZVByaW50aW5nKGNvbm5lY3Rpb25JZDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLl9jb25uZWN0aW9ucy5maW5kKGNvbm5lY3Rpb24gPT4gY29ubmVjdGlvbi5pZCA9PT0gY29ubmVjdGlvbklkKTtcbiAgICAgICAgaWYgKGNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGNvbm5lY3Rpb24uc29ja2V0LmVtaXQoJ2VuYWJsZV9wcmludCcsIG51bGwsIChkYXRhOiBib29sZWFuKSA9PiB7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5ldmVudCQubmV4dChuZXcgUHJpbnRFdmVudCh7dHlwZTogJ1BSSU5UX0VOQUJMRUQnLCBjb25uZWN0aW9uSWR9KSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBkaXNhYmxlUHJpbnRpbmcoY29ubmVjdGlvbklkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMuX2Nvbm5lY3Rpb25zLmZpbmQoY29ubmVjdGlvbiA9PiBjb25uZWN0aW9uLmlkID09PSBjb25uZWN0aW9uSWQpO1xuICAgICAgICBpZiAoY29ubmVjdGlvbikge1xuICAgICAgICAgICAgY29ubmVjdGlvbi5zb2NrZXQuZW1pdCgnZGlzYWJsZV9wcmludCcsIG51bGwsIChkYXRhOiBib29sZWFuKSA9PiB7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5ldmVudCQubmV4dChuZXcgUHJpbnRFdmVudCh7dHlwZTogJ1BSSU5UX0RJU0FCTEVEJywgY29ubmVjdGlvbklkfSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgb3BlblByaW50YWJsZShjb25uZWN0aW9uSWQ6IHN0cmluZywgam9iSWQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gdGhpcy5fY29ubmVjdGlvbnMuZmluZChjb25uZWN0aW9uID0+IGNvbm5lY3Rpb24uaWQgPT09IGNvbm5lY3Rpb25JZCk7XG4gICAgICAgIGlmIChjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBjb25zdCBwcmludGFibGUgPSBjb25uZWN0aW9uLnByaW50YWJsZXMuZmluZChwcmludGFibGUgPT4gcHJpbnRhYmxlLmpvYklkID09PSBqb2JJZCk7XG4gICAgICAgICAgICBpZiAocHJpbnRhYmxlKSB7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbi5zb2NrZXQuZW1pdCgncHJpbnRfam9iX2hhbmRsZWQnLCBwcmludGFibGUuam9iSWQpO1xuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24ucHJpbnRhYmxlcyA9IGNvbm5lY3Rpb24ucHJpbnRhYmxlcy5maWx0ZXIocHJpbnRhYmxlID0+IHByaW50YWJsZS5qb2JJZCAhPT0gam9iSWQpO1xuICAgICAgICAgICAgICAgIHRoaXMub3BlblBERihwcmludGFibGUuZGF0YSwgY29ubmVjdGlvbiwgam9iSWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0aWFsaXNlUmVjZWl2ZXIoKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5faWZyYW1lKSB7XG4gICAgICAgICAgICB0aGlzLl9pZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICAgICAgICAgIHRoaXMuX2lmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZCh0aGlzLl9pZnJhbWUpO1xuICAgICAgICAgICAgdGhpcy5faWZyYW1lLm9ubG9hZCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBVUkwucmV2b2tlT2JqZWN0VVJMKHRoaXMuX3BkZlVybCk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLl9pZnJhbWUuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9pZnJhbWUuY29udGVudFdpbmRvdz8ucHJpbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGRmRGlkT3BlbiA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGhhbmRsZVByaW50Sm9iKGNvbm5lY3Rpb246IENvbm5lY3Rpb24sIHByaW50Sm9iOiBQcmludEpvYik6IHZvaWQge1xuICAgICAgICBjb25zdCB7IGpvYklkLCBjaHVua0lkLCBjaHVua0NvdW50IH0gPSBwcmludEpvYjtcbiAgICAgICAgaWYgKCFjb25uZWN0aW9uLmpvYnMuaGFzKGpvYklkKSkge1xuICAgICAgICAgICAgY29ubmVjdGlvbi5qb2JzLnNldChqb2JJZCwgW10pO1xuICAgICAgICB9XG4gICAgICAgIGNvbm5lY3Rpb24uam9icy5nZXQoam9iSWQpPy5wdXNoKHByaW50Sm9iKTtcblxuICAgICAgICBpZiAoY2h1bmtJZCA9PT0gY2h1bmtDb3VudCkge1xuICAgICAgICAgICAgdGhpcy5wcm9jZXNzSm9iKGNvbm5lY3Rpb24sIHByaW50Sm9iKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcHJvY2Vzc0pvYihjb25uZWN0aW9uOiBDb25uZWN0aW9uLCBwcmludEpvYjogUHJpbnRKb2IpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qge2pvYklkLCBjaHVua0NvdW50LCBmaWxlTGVuZ3RoLCBmaWxlTmFtZX0gPSBwcmludEpvYjtcbiAgICAgICAgY29uc3QgY2h1bmtzID0gY29ubmVjdGlvbi5qb2JzLmdldChqb2JJZCk7XG4gICAgICAgIGlmIChjaHVua3MpIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBmcm9tIGpvYnNcbiAgICAgICAgICAgIGNvbm5lY3Rpb24uam9icy5kZWxldGUoam9iSWQpO1xuXG4gICAgICAgICAgICAvLyBDb25jYXRlbmF0ZSBhbGwgdGhlIGRhdGFcbiAgICAgICAgICAgIGlmIChjaHVua3MubGVuZ3RoID4gMCAmJiBjaHVua3MubGVuZ3RoID09PSBjaHVua0NvdW50KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYmFzZTY0ID0gY2h1bmtzLnJlZHVjZSgoYWNjLCBjaHVuaykgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYWNjICsgY2h1bmsuZGF0YVxuICAgICAgICAgICAgICAgIH0sICcnKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBhdG9iKGJhc2U2NCk7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGEubGVuZ3RoID09PSBmaWxlTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24ucHJpbnRhYmxlcy5wdXNoKHtqb2JJZCwgZGF0YX0pXG4gICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb24uZXZlbnQkLm5leHQobmV3IFByaW50RXZlbnQoe3R5cGU6ICdQUklOVF9KT0JfQVZBSUxBQkxFJywgY29ubmVjdGlvbklkOiBjb25uZWN0aW9uLmlkLCBkYXRhOiBuZXcgUHJpbnRKb2JBdmFpbGFibGVFdmVudCh7am9iSWQsIGZpbGVMZW5ndGgsIGZpbGVOYW1lfSl9KSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29ubmVjdGlvbi5ldmVudCQubmV4dChuZXcgUHJpbnRFdmVudCh7dHlwZTogJ0VSUk9SJywgY29ubmVjdGlvbklkOiBjb25uZWN0aW9uLmlkLCBkYXRhOiBuZXcgRXJyb3JFdmVudCh7dHlwZTogJ0VSUk9SJywgbWVzc2FnZTogJ1Byb2Nlc3NlcyBwcmludCBkYXRhIGhhcyBpbmNvbnNpc3RlbnQgbGVuZ3RoJ30pfSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgb3BlblBERihkYXRhOiBzdHJpbmcsIGNvbm5lY3Rpb246IENvbm5lY3Rpb24sIGpvYklkOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgLy8gQ29udmVydCB0byBiaW5hcnkgZGF0YVxuICAgICAgICBjb25zdCBieXRlcyA9IG5ldyBVaW50OEFycmF5KGRhdGEubGVuZ3RoKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBieXRlc1tpXSA9IGRhdGEuY2hhckNvZGVBdChpKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW2J5dGVzXSwge3R5cGU6ICdhcHBsaWNhdGlvbi9wZGYnfSk7XG4gICAgICAgIHRoaXMuX3BkZlVybCA9IFVSTC5jcmVhdGVPYmplY3RVUkwoYmxvYik7XG5cbiAgICAgICAgdGhpcy5pbml0aWFsaXNlUmVjZWl2ZXIoKTtcblxuICAgICAgICAvLyBTZXQgdGhlIHBkZiBpbiB0aGUgaWZyYW1lXG4gICAgICAgIHRoaXMuX3BkZkRpZE9wZW4gPSBmYWxzZTtcbiAgICAgICAgdGhpcy5faWZyYW1lLnNyYyA9IHRoaXMuX3BkZlVybDtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5fcGRmRGlkT3BlbiA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uLmV2ZW50JC5uZXh0KG5ldyBQcmludEV2ZW50KHt0eXBlOiAnUFJJTlRfRElBTE9HX0ZBSUxFRCcsIGNvbm5lY3Rpb25JZDogY29ubmVjdGlvbi5pZCwgam9iSWR9KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIDIwMCk7XG5cbiAgICB9XG59XG4iXX0=