Subversion Repositories munaweb

Rev

Rev 4 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
<!DOCTYPE html>
2
<html lang="en">
3
 
4
<head>
5
    <title>eBay Listings Price Check</title>
6
    <meta charset="UTF-8">
7
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
    <link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
9
    <link rel="icon" href="favicon.ico" type="image/x-icon">
10
 
11
    <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
12
    <link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
13
    <link rel="stylesheet" href="css/style.css">
14
    <script src="js/XMLWriter.js"></script>
15
    <script src="js/vkbeautify.js"></script>
16
    <script src="js/lodash.min.js"></script>
17
    <script src="js/XMLparse.js"></script>
18
    <script src="js/muna-tools.js"></script>
19
</head>
20
 
21
<body onload="return initConfig();">
22
    <div class="w3-main">
23
        <div class="w3-container w3-padding w3-margin w3-card-4">
24
            <div class="w3-container w3-gray" style="height:100px">
25
                <img class="w3-image" src="images/MUNA%20-%20Logo%20100x100.png" alt="MUNA Trading Logo" style="height:100px">
26
                <p id="connected" class="w3-xxlarge w3-right">eBay Listings Price Check
27
                    <input id="login" type="button" class="w3-btn w3-large w3-green w3-margin w3-round-large w3-ripple w3-right w3-hide" onclick="eBayLogin();" value="Login" />
28
                </p>
29
            </div>
30
 
31
            <div class="w3-row">
32
                <div>
33
                    <form id="searchForm" class="w3-container w3-light-grey w3-padding w3-small" onsubmit="return checkListingPrices();">
34
                        <div class="w3-container w3-card-2 w3-cell w3-padding">
35
                            <input id="startButton" type="button" class="w3-btn w3-large w3-black w3-margin w3-round-large w3-ripple w3-right" onclick="checkListingPrices();" value="Start" />
36
                        </div>
37
                    </form>
38
                </div>
39
                <div id="progressBarDiv" class="w3-container w3-padding w3-margin w3-card-4 w3-hide">
40
                    <h2 id="progressBarHeader"></h2>
41
                    <div class="w3-light-grey">
42
                        <div id="progressBar" class="w3-container w3-green w3-center" style="width:0%">0%</div>
43
                    </div>
44
                </div>
45
                <div id="results" class="w3-container w3-padding w3-card-4 w3-hide"></div>
46
                <div id="logging" class="w3-container w3-padding"></div>
47
            </div>
48
        </div>
49
 
50
        <footer class="w3-container w3-center w3-border-top w3-margin">
51
            Copyright &#169; 2018 MUNA Trading. All rights reserved.
52
        </footer>
53
 
54
    </div>
55
 
56
    <script>
57
 
58
// Config
59
var configMinPrice = "5.99";
60
var configDifference = 2.00;
61
var configPercentage = 20.00;
62
var configAbsoluteMinPrice = 5.00;
63
var configAdjMinPrice = 5.48;
64
var configSearchUrl = 'https://ujsoftware.linkpc.net/ebay/search.html?keyword=';
65
var configSearchUrlPart2 = '&hideDuplicateItems=on&locatedIn=WorldWide&sortOrder=PricePlusShippingLowest&results=100';
66
 
67
var pagesToProcess = 0;
68
var maxPagesToProcess = 0;
69
var pagesProcessed = 0;
70
var productIdsToProcess = 0;
71
var maxProductIdsToProcess = 0;
72
var productIdsProcessed = 0;
73
var productsToPrice = 0;
74
var maxProductsToPrice = 0;
75
var productsPriced = 0;
76
var html = [];
77
 
78
// Initialize Configuration Variables
79
function initConfig() {
80
    eBayAuthToken = readCookie();
81
    if (eBayAuthToken.length > 0) {
82
        connected();
83
    }
84
 
85
    if (eBayAuthTokenFlag === false) {
86
        var x = document.getElementById("login");
87
        if (x.className.indexOf("w3-show") == -1) {
88
            x.className += " w3-show";
89
        }
90
    }
91
}
92
 
93
function requireNewLogin() {
94
    // dummy
95
}
96
 
97
function checkListingPrices() {
98
    var x;
99
 
100
    document.getElementById("logging").innerHTML = '';
101
 
102
    x = document.getElementById("results");
103
    if (x.className.indexOf("w3-show") == -1) {
104
        x.className += " w3-show";
105
    }
106
    x.className = x.className.replace(" process-errors", "");
107
    x.innerHTML = '';
108
 
109
    initProgressBar('Retrieving Active Listings (1/3)');
110
 
111
    pagesToProcess = 1;
112
    maxPagesToProcess = 1;
113
    pagesProcessed = 0;
114
    eBaySearch(1);
115
 
116
    function checkpagesToProcess() {
117
        if (pagesToProcess > 0) {
118
            window.setTimeout(checkpagesToProcess, 100); // wait 100 milliseconds
119
        } else {
120
            findMissingProductIds();
121
        }
122
    }
123
 
124
    checkpagesToProcess();
125
}
126
 
127
// item filters for request
128
var filterarray = [];
129
var urlfilter = [];
130
 
131
// Fill the array of item filters from input form
132
function fillFilterArray() {
133
    filterarray = [];
134
    var obj = [];
135
 
136
    obj = {
137
        "name": "Seller",
138
        "value": configeBaySellerName,
139
        "paramName": "",
140
        "paramValue": ""
141
    };
142
    filterarray.push(obj);
143
 
144
    obj = {
145
        "name": "MinPrice",
146
        "value": Number(configMinPrice).toFixed(2),
147
        "paramName": "Currency",
148
        "paramValue": "USD"
149
    };
150
    filterarray.push(obj);
151
 
152
    obj = {
153
        "name": "ListingType",
154
        "value": "FixedPrice",
155
        "paramName": "",
156
        "paramValue": ""
157
    };
158
    filterarray.push(obj);
159
 
160
    urlfilter = "";
161
    // Iterate through each filter in the array
162
    for (var i = 0; i < filterarray.length; i++) {
163
        //Index each item filter in filterarray
164
        var itemfilter = filterarray[i];
165
        // Iterate through each parameter in each item filter
166
        for (var index in itemfilter) {
167
            // Check to see if the paramter has a value (some don't)
168
            if (itemfilter[index] !== "") {
169
                if (itemfilter[index] instanceof Array) {
170
                    for (var r = 0; r < itemfilter[index].length; r++) {
171
                        var value = itemfilter[index][r];
172
                        urlfilter += "&itemFilter\(" + i + "\)." + index + "\(" + r + "\)=" + value;
173
                    }
174
                } else {
175
                    urlfilter += "&itemFilter\(" + i + "\)." + index + "=" + itemfilter[index];
176
                }
177
            }
178
        }
179
    }
180
} // End fillFilterArray() function
181
 
182
var url = "";
183
 
184
function eBaySearch(pageNumber) {
185
    // Fill the filter array from form input
186
    if (pageNumber == 1) {
187
        fillFilterArray();
188
    }
189
 
190
    // Construct the request
191
    url = configeBayFinding + "?";
192
    url += "OPERATION-NAME=findItemsAdvanced";
193
    url += "&SERVICE-VERSION=" + configeBayFindingVersion;
194
    url += "&SECURITY-APPNAME=" + configAppid;
195
    url += "&GLOBAL-ID=EBAY-US";
196
    url += "&RESPONSE-DATA-FORMAT=JSON";
197
    url += "&REST-PAYLOAD";
198
    url += "&paginationInput.entriesPerPage=100";
199
    url += "&paginationInput.pageNumber=";
200
    url += pageNumber;
201
    url += urlfilter;
202
 
203
    var xhttp = new XMLHttpRequest();
204
 
205
    xhttp.onreadystatechange = function() {
206
        if (this.readyState == 4) {
207
            _cb_findItemsAdvanced(JSON.parse(this.responseText));
208
        }
209
    };
210
 
211
    xhttp.open("GET", configProxyUrl, true);
212
    xhttp.setRequestHeader("X-Proxy-Url", encodeURI(url));
213
    xhttp.send();
214
 
215
    return false;
216
}
217
 
218
function printeBayAPIError(root) {
219
    var x = document.getElementById("results");
220
    x.className += " process-errors";
221
    x.innerHTML += "<h2>eBay API Error<h2>";
222
    x.innerHTML += "<p>Id: " + root.errorMessage[0].error[0].errorId + "<br/>";
223
    x.innerHTML += "<p>Severity: " + root.errorMessage[0].error[0].severity + "<br/>";
224
    x.innerHTML += "<p>Message: " + root.errorMessage[0].error[0].message + "</p>";
225
}
226
 
227
// Parse the response and build an HTML table to display search results
228
function _cb_findItemsAdvanced(root) {
229
    // Error Handling
230
    var response = root.findItemsAdvancedResponse[0];
231
    var ack = response.ack;
232
    if (ack != 'Success') {
233
        printeBayAPIError(response);
234
 
235
        if (ack == 'Failure' || ack == 'PartialFailure') {
236
            --pagesToProcess;
237
            return;
238
        }
239
    }
240
 
241
    createTable(response.searchResult[0].item || [], Number(response.paginationOutput[0].pageNumber), Number(response.paginationOutput[0].totalPages));
242
 
243
   	if (Number(response.paginationOutput[0].totalPages) > Number(response.paginationOutput[0].pageNumber)) {
244
   		++maxPagesToProcess;
245
   		++pagesToProcess;
246
   		eBaySearch(Number(response.paginationOutput[0].pageNumber) + 1);
247
   	}
248
 
249
    document.getElementById("logging").innerHTML = html.join('');
250
    --pagesToProcess;
251
    ++pagesProcessed;
252
    updateProgressBar(maxPagesToProcess, pagesProcessed);
253
} // End _cb_findItemsAdvanced() function
254
 
255
 
256
function createTable(obj, pageNumber, totalPages) {
257
    if (pageNumber == 1) {
258
        document.getElementById("logging").innerHTML = '';
259
        html = [];
260
 
261
        html.push('<h3>Price Validation</h3>');
262
        html.push('<div class="w3-responsive">');
263
        html.push('<table id="itemTable" class="w3-table-all w3-hoverable css-serial">');
264
        html.push('<thead>');
265
        html.push('<tr>');
266
 
267
        html.push(tableHeader('#'));
268
        html.push(tableHeader('Item Id'));
269
        html.push(tableHeader('Thumbnail'));
270
        html.push(tableHeader('Title'));
271
        html.push(tableHeader('Product Id'));
272
        html.push(tableHeader('Price'));
273
        html.push(tableHeader('# Active Listings'));
274
        html.push(tableHeader('# Priced Lower'));
275
        html.push(tableHeader('Lowest Price'));
276
        html.push(tableHeader('Highest Price'));
277
        html.push(tableHeader('Above/Below Lowest'));
278
        html.push(tableHeader('Views'));
279
        html.push(tableHeader('Watchers'));
280
        html.push(tableHeaderHidden('Condition'));
281
        html.push(tableHeaderHidden('# Better Condition'));
282
        html.push(tableHeader('Price Adj.'));
283
        html.push(tableHeaderHidden('Best Offer'));
284
        html.push(tableHeaderHidden('MinBetterCondition'));
285
        html.push(tableHeaderHidden('BetterConditionBreakdown'));
286
        html.push(tableHeaderHidden('SameConditionBreakdown'));
287
 
288
        html.push('</tr>');
289
        html.push('</thead>');
290
        html.push('<tbody>');
291
    }
292
 
293
    for (var entry = 0; entry < obj.length; entry++) {
294
        html.push('<tr>');
295
        html.push(tableCell(''));
296
        html.push(tableCell('<a href="' + obj[entry].viewItemURL + '" target="_blank">' + obj[entry].itemId + '</a>'));
297
        html.push(tableCell('<img src="' + obj[entry].galleryURL[0].replace('http:', 'https:') + '">'));
298
        html.push(tableCell(obj[entry].title));
299
        if (obj[entry].productId !== undefined) {
300
            var str = '<a href="' + configSearchUrl;
301
            str += 'ReferenceID%3A' + obj[entry].productId[0].__value__;
302
            str += configSearchUrlPart2 + '" target="_blank">';
303
            str += obj[entry].productId[0]["@type"] + ' ' + obj[entry].productId[0].__value__;
304
            str += '</a>';
305
            html.push(tableCell(str));
306
        } else {
307
            html.push(tableCellLabel('ProductId' + obj[entry].itemId));
308
        }
309
 
310
        html.push(tableCell('$' + Number(obj[entry].sellingStatus[0].convertedCurrentPrice[0].__value__).toFixed(2)));
311
        html.push(tableCell(1));
312
        html.push(tableCell(0));
313
        html.push(tableCell('$0.00'));
314
        html.push(tableCell('$0.00'));
315
        html.push(tableCell('$0.00 (0.00%)'));
316
 
317
        html.push(tableCell(0));
318
        html.push(tableCell(obj[entry].listingInfo[0].watchCount === undefined ? 0 : Number(obj[entry].listingInfo[0].watchCount)));
319
        html.push(tableCellHidden(obj[entry].condition === undefined ? 4000 : Number(obj[entry].condition[0].conditionId)));
320
        html.push(tableCellHidden(0));
321
        html.push(tableCell('<input id="PriceAdj' + obj[entry].itemId + '" type="text" size="10"><br><input type="button" class="w3-btn w3-large w3-black w3-margin w3-round-large w3-ripple" onclick="changePrice(' + obj[entry].itemId + ');" value="Adjust Price" />'));
322
        html.push(tableCellLabelHidden('BestOffer' + obj[entry].itemId, obj[entry].listingInfo[0].bestOfferEnabled));
323
        html.push(tableCellHidden('0'));
324
        html.push(tableCellHidden('[]'));
325
        html.push(tableCellHidden('[]'));
326
 
327
        html.push('</tr>');
328
    }
329
 
330
    if (pageNumber == totalPages) {
331
        html.push('</tbody>');
332
        html.push('</table>');
333
        html.push('</div>');
334
    }
335
}
336
 
337
function setCellsAttribute(table, row, col, label) {
338
    table.rows[row].cells[col].setAttribute("id", label);
339
}
340
 
341
function sortTableDesc(tableName, column) {
342
    var table, rows, switching, i, x, y, shouldSwitch;
343
    --column; // column parameter starts with 1
344
    table = document.getElementById(tableName);
345
    switching = true;
346
    /*Make a loop that will continue until
347
    no switching has been done:*/
348
    while (switching) {
349
        //start by saying: no switching is done:
350
        switching = false;
351
        rows = table.getElementsByTagName("TR");
352
        /*Loop through all table rows (except the
353
        first, which contains table headers:*/
354
        for (i = 1; i < (rows.length - 1); i++) {
355
            //start by saying there should be no switching:
356
            shouldSwitch = false;
357
            /*Get the two elements you want to compare,
358
            one from current row and one from the next:*/
359
            x = rows[i].getElementsByTagName("TD")[column];
360
            y = rows[i + 1].getElementsByTagName("TD")[column];
361
            //check if the two rows should switch place:
362
            if (x !== undefined && (Number(x.innerHTML.substr(1)) < Number(y.innerHTML.substr(1)))) {
363
                //if so, mark as a switch and break the loop:
364
                shouldSwitch = true;
365
                break;
366
            }
367
        }
368
        if (shouldSwitch) {
369
            /*If a switch has been marked, make the switch
370
            and mark that a switch has been done:*/
371
            rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
372
            switching = true;
373
        }
374
    }
375
}
376
 
377
function findMissingProductIds() {
378
    var i;
379
    var x = document.getElementById("itemTable");
380
    var missingList = [];
381
    var viewList = [];
382
    var maxItems = 20;
383
 
384
    initProgressBar('Retrieving Product Ids (2/3)');
385
 
386
    productIdsToProcess = 0;
387
    maxProductIdsToProcess = 0;
388
    productIdsProcessed = 0;
389
 
390
    for (i = 1; i < x.rows.length; i++) {
391
        if (x.rows[i].cells[4] !== undefined && x.rows[i].cells[4].innerText.length < 1) {
392
            missingList.push(x.rows[i].cells[1].innerText);
393
        } else {
394
            var p = x.rows[i].cells[4].innerText.substr(x.rows[i].cells[4].innerText.indexOf(" ") + 1);
395
            setCellsAttribute(x, i, 5, "Price" + p);
396
            setCellsAttribute(x, i, 6, "Active" + p);
397
            setCellsAttribute(x, i, 7, "Lower" + p);
398
            setCellsAttribute(x, i, 8, "Minimum" + p);
399
            setCellsAttribute(x, i, 9, "Maximum" + p);
400
            setCellsAttribute(x, i, 11, "Views" + x.rows[i].cells[1].innerText);
401
            setCellsAttribute(x, i, 13, "Condition" + p);
402
            setCellsAttribute(x, i, 14, "BetterCondition" + p);
403
            setCellsAttribute(x, i, 17, "MinBetterCondition" + p);
404
            setCellsAttribute(x, i, 18, "BetterConditionBreakdown" + p);
405
            setCellsAttribute(x, i, 19, "SameConditionBreakdown" + p);
406
            viewList.push(x.rows[i].cells[1].innerText);
407
        }
408
    }
409
 
410
    for (i = 0;
411
        (i * maxItems) < missingList.length; i++) {
412
        ++productIdsToProcess;
413
        ++maxProductIdsToProcess;
414
        findMissingProductId(missingList.slice(i * maxItems, (i + 1) * maxItems));
415
    }
416
 
417
    for (i = 0;
418
        (i * maxItems) < viewList.length; i++) {
419
        ++productIdsToProcess;
420
        ++maxProductIdsToProcess;
421
        findViews(viewList.slice(i * maxItems, (i + 1) * maxItems));
422
    }
423
 
424
    function checkproductIdsToProcess() {
425
        if (productIdsToProcess > 0) {
426
            window.setTimeout(checkproductIdsToProcess, 100); // wait 100 milliseconds
427
        } else {
428
            priceProductIds();
429
        }
430
    }
431
 
432
    checkproductIdsToProcess();
433
}
434
 
435
function findMissingProductId(itemIdList) {
436
    var i;
437
    var xml;
438
 
439
    var xw = new XMLWriter('UTF-8', '1.0');
440
    var xhr = new XMLHttpRequest();
441
 
442
    xw.writeStartDocument();
443
    xw.writeStartElement("GetMultipleItemsRequest");
444
    xw.writeAttributeString('xmlns', 'urn:ebay:apis:eBLBaseComponents');
445
 
446
    for (i = 0; i < itemIdList.length; i++) {
447
        xw.writeElementString('ItemID', itemIdList[i]);
448
    }
449
 
450
    xw.writeElementString('IncludeSelector', 'Details');
451
    xw.writeElementString('ErrorLanguage', 'en_US');
452
    xw.writeElementString('Version', configeBayShoppingVersion);
453
    xw.writeElementString('WarningLevel', configWarningLevel);
454
 
455
    xw.writeEndElement(); /* xmlrequest */
456
    xw.writeEndDocument();
457
 
458
    xhr.open('POST', configProxyUrl, true);
459
    xhr.setRequestHeader('Content-Type', 'text/xml');
460
    xhr.setRequestHeader('X-EBAY-API-APP-NAME', configAppid);
461
    xhr.setRequestHeader('X-EBAY-API-VERSION', configeBayShoppingVersion);
462
    xhr.setRequestHeader('X-EBAY-API-CALL-NAME', 'GetMultipleItems');
463
    xhr.setRequestHeader('X-EBAY-API-SITEID', '0');
464
    xhr.setRequestHeader('X-EBAY-API-DEV-NAME', '');
465
    xhr.setRequestHeader('X-EBAY-API-CERT-NAME', '');
466
    xhr.setRequestHeader('X-EBAY-API-REQUEST-ENCODING', 'XML');
467
    xhr.setRequestHeader('X-Proxy-URL', configeBayShopping);
468
 
469
    xml = xw.flush();
470
    xw.close();
471
    //window.alert(vkbeautify.xml(xml));
472
 
473
    xhr.onload = function() {
474
        var obj = XMLparse(xhr.responseXML);
475
        //window.alert(JSON.stringify(obj));
476
        //window.alert(vkbeautify.xml(xhr.responseText));
477
 
478
        var returnCode = obj.Ack;
479
 
480
        var x = document.getElementById("results");
481
 
482
        if (returnCode == 'Success') {
483
            for (i = 0; i < obj.Item.length; i++) {
484
                var ItemID = getJsonValue(obj.Item[i].ItemID);
485
                var SKU = getJsonValue(obj.Item[i].SKU);
486
                var HitCount = getJsonValue(obj.Item[i].HitCount);
487
                var n = (SKU === undefined ? 0 : SKU.indexOf(" - "));
488
                var row;
489
                var str;
490
                var code;
491
 
492
                if (n > 0) {
493
                    code = SKU.substr(n + 3);
494
                    code = code.substr(code.indexOf(" ") + 1);
495
                    str = '<a href="' + configSearchUrl;
496
                    str += code;
497
                    str += configSearchUrlPart2 + '" target="_blank">';
498
                    str += SKU.substr(n + 3);
499
                    str += '</a>';
500
                    document.getElementById('ProductId' + ItemID).innerHTML = str;
501
                    x = document.getElementById("itemTable");
502
                    row = document.getElementById('ProductId' + ItemID).parentNode.rowIndex;
503
                    setCellsAttribute(x, row, 5, "Price" + code);
504
                    setCellsAttribute(x, row, 6, "Active" + code);
505
                    setCellsAttribute(x, row, 7, "Lower" + code);
506
                    setCellsAttribute(x, row, 8, "Minimum" + code);
507
                    setCellsAttribute(x, row, 9, "Maximum" + code);
508
                    x.rows[row].cells[11].innerHTML = HitCount;
509
                    setCellsAttribute(x, row, 13, "Condition" + code);
510
                    setCellsAttribute(x, row, 14, "BetterCondition" + code);
511
                    setCellsAttribute(x, row, 17, "MinBetterCondition" + code);
512
                    setCellsAttribute(x, row, 18, "BetterConditionBreakdown" + code);
513
                    setCellsAttribute(x, row, 19, "SameConditionBreakdown" + code);
514
                } else {
515
                    row = document.getElementById('ProductId' + ItemID).parentNode.rowIndex;
516
                    document.getElementById("itemTable").deleteRow(row);
517
                }
518
            }
519
        } else {
520
            x.className += " process-errors";
521
            x.innerHTML += '<p class="w3-red"><strong>' + returnCode + ':</strong></p>';
522
 
523
            var errors = obj.Errors;
524
            x.innerHTML += "<p>";
525
            if (errors.length > 0) {
526
                for (i = 0; i < errors.length; i++) {
527
                    x.innerHTML += errors[i].SeverityCode + " (" + errors[i].ErrorCode + "): " + escapeHtml(errors[i].LongMessage) + "<br/>";
528
                }
529
            } else {
530
                x.innerHTML += obj.Errors.SeverityCode + " (" + obj.Errors.ErrorCode + "): " + escapeHtml(obj.Errors.LongMessage) + "<br/>";
531
            }
532
            x.innerHTML += "</p>";
533
        }
534
 
535
        --productIdsToProcess;
536
        ++productIdsProcessed;
537
        updateProgressBar(maxProductIdsToProcess, productIdsProcessed);
538
    };
539
 
540
    xhr.send(xml);
541
}
542
 
543
function findViews(itemIdList) {
544
    var i;
545
    var xml;
546
 
547
    var xw = new XMLWriter('UTF-8', '1.0');
548
    var xhr = new XMLHttpRequest();
549
 
550
    xw.writeStartDocument();
551
    xw.writeStartElement("GetMultipleItemsRequest");
552
    xw.writeAttributeString('xmlns', 'urn:ebay:apis:eBLBaseComponents');
553
 
554
    for (i = 0; i < itemIdList.length; i++) {
555
        xw.writeElementString('ItemID', itemIdList[i]);
556
    }
557
 
558
    xw.writeElementString('ErrorLanguage', 'en_US');
559
    xw.writeElementString('Version', configeBayShoppingVersion);
560
    xw.writeElementString('WarningLevel', configWarningLevel);
561
 
562
    xw.writeEndElement(); /* xmlrequest */
563
    xw.writeEndDocument();
564
 
565
    xhr.open('POST', configProxyUrl, true);
566
    xhr.setRequestHeader('Content-Type', 'text/xml');
567
    xhr.setRequestHeader('X-EBAY-API-APP-NAME', configAppid);
568
    xhr.setRequestHeader('X-EBAY-API-VERSION', configeBayShoppingVersion);
569
    xhr.setRequestHeader('X-EBAY-API-CALL-NAME', 'GetMultipleItems');
570
    xhr.setRequestHeader('X-EBAY-API-SITEID', '0');
571
    xhr.setRequestHeader('X-EBAY-API-DEV-NAME', '');
572
    xhr.setRequestHeader('X-EBAY-API-CERT-NAME', '');
573
    xhr.setRequestHeader('X-EBAY-API-REQUEST-ENCODING', 'XML');
574
    xhr.setRequestHeader('X-Proxy-URL', configeBayShopping);
575
 
576
    xml = xw.flush();
577
    xw.close();
578
    //window.alert(vkbeautify.xml(xml));
579
 
580
    xhr.onload = function() {
581
        var obj = XMLparse(xhr.responseXML);
582
        //window.alert(JSON.stringify(obj));
583
        //window.alert(vkbeautify.xml(xhr.responseText));
584
 
585
        var returnCode = obj.Ack;
586
 
587
        var x = document.getElementById("results");
588
 
589
        if (returnCode == 'Success') {
590
            for (i = 0; i < obj.Item.length; i++) {
591
                var ItemID = getJsonValue(obj.Item[i].ItemID);
592
                var HitCount = getJsonValue(obj.Item[i].HitCount);
593
 
594
                document.getElementById('Views' + ItemID).innerHTML = HitCount;
595
            }
596
        } else {
597
            x.className += " process-errors";
598
            x.innerHTML += '<p class="w3-red"><strong>' + returnCode + ':</strong></p>';
599
 
600
            var errors = obj.Errors;
601
            x.innerHTML += "<p>";
602
            if (errors.length > 0) {
603
                for (i = 0; i < errors.length; i++) {
604
                    x.innerHTML += errors[i].SeverityCode + " (" + errors[i].ErrorCode + "): " + escapeHtml(errors[i].LongMessage) + "<br/>";
605
                }
606
            } else {
607
                x.innerHTML += obj.Errors.SeverityCode + " (" + obj.Errors.ErrorCode + "): " + escapeHtml(obj.Errors.LongMessage) + "<br/>";
608
            }
609
            x.innerHTML += "</p>";
610
        }
611
 
612
        --productIdsToProcess;
613
        ++productIdsProcessed;
614
        updateProgressBar(maxProductIdsToProcess, productIdsProcessed);
615
    };
616
 
617
    xhr.send(xml);
618
}
619
 
620
function priceProductIds() {
621
    var i;
622
    var price;
623
    var lowest;
624
    var difference;
625
    var percentage;
626
    var noPricedLower;
627
    var noActive;
628
    var noBetterCondition;
629
    var percLower;
630
    var x = document.getElementById("itemTable");
631
 
632
    initProgressBar('Retrieving Prices (3/3)');
633
 
634
    productsToPrice = 0;
635
    maxProductsToPrice = 0;
636
    productsPriced = 0;
637
 
638
    for (i = 1; i < x.rows.length; i++) {
639
        ++productsToPrice;
640
        ++maxProductsToPrice;
641
        findProductPrices(x.rows[i].cells[4].innerText, 1);
642
    }
643
 
644
    function checkProductsToPrice() {
645
        if (productsToPrice > 0) {
646
            window.setTimeout(checkProductsToPrice, 100); // wait 100 milliseconds
647
        } else {
648
            /*
649
                xxxxx
650
                Minimum of 5 comparison listings
651
                (Take out lowest and highest price before calculating the average)
652
                (Don't go under $4.98)
653
                (Price items below cheapest item with better condition)
654
                Price within the first 20-25% listing (by number)
655
                (Price below the average price)
656
                adjust BIN (buy it now) when changing the price: No BIN under $10; minimum accepted 65%, auto-accepted 85+%
657
                (disregard certain sellers (for now decluttr and zuber, list could be expanded))
658
            */
659
            for (i = (x.rows.length - 1); i > 0; i--) {
660
                noPricedLower = Number(x.rows[i].cells[7].innerHTML);
661
                noActive = Number(x.rows[i].cells[6].innerHTML);
662
 
663
                if (noActive < 6) {
664
                    document.getElementById("itemTable").deleteRow(i);
665
                    continue;
666
                }
667
 
668
                if (noPricedLower > 0) {
669
                    price = Number(x.rows[i].cells[5].innerHTML.substr(1));
670
                    lowest = Number(x.rows[i].cells[8].innerHTML.substr(1));
671
                    difference = price - lowest;
672
                    percentage = 100.00 - (lowest / price * 100.00);
673
                    x.rows[i].cells[10].innerHTML = "$" + difference.toFixed(2) + " (" + percentage.toFixed(2) + "%)";
674
 
675
                    percLower = (noPricedLower / noActive) * 100.00;
676
                    if (noPricedLower > 24.99) {
677
                        x.rows[i].cells[5].style.color = "red";
678
                        x.rows[i].cells[7].style.color = "red";
679
                    } else {
680
                        document.getElementById("itemTable").deleteRow(i);
681
                        continue;
682
                    }
683
 
684
                    if (difference < configDifference || percentage < configPercentage || price < configAbsoluteMinPrice) {
685
                        document.getElementById("itemTable").deleteRow(i);
686
                        continue;
687
                    } else {
688
                        x.rows[i].cells[5].style.color = "red";
689
                        x.rows[i].cells[10].style.color = "red";
690
                    }
691
                } else if (noPricedLower === 0) {
692
                    noBetterCondition = Number(x.rows[i].cells[14].innerHTML);
693
                    if (noActive == (noBetterCondition + 1)) {
694
                        document.getElementById("itemTable").deleteRow(i);
695
                        continue;
696
                    }
697
 
698
                    price = Number(x.rows[i].cells[5].innerHTML.substr(1));
699
                    lowest = Number(x.rows[i].cells[8].innerHTML.substr(1));
700
                    difference = price - lowest;
701
                    percentage = 100.00 - (lowest / price * 100.00);
702
                    x.rows[i].cells[10].innerHTML = "$" + difference.toFixed(2) + " (" + percentage.toFixed(2) + "%)";
703
 
704
                    if ((difference * -1.00) < configDifference && (percentage * -1.00) < configPercentage) {
705
                        document.getElementById("itemTable").deleteRow(i);
706
                        continue;
707
                    } else {
708
                        x.rows[i].cells[5].style.color = "green";
709
                        x.rows[i].cells[10].style.color = "green";
710
                    }
711
                    continue;
712
                }
713
            }
714
 
715
            endProgressBar();
716
 
717
            x = document.getElementById("results");
718
            x.innerHTML += '<p><strong>Sorting Report.....</strong></p>';
719
 
720
            sortTableDesc("itemTable", 6);
721
 
722
            x.innerHTML += '<p><strong>Report Finished!</strong></p>';
723
            if (!x.className.includes("process-errors")) {
724
                setTimeout(function() {
725
                    x.className = x.className.replace(" w3-show", "");
726
                }, 3000);
727
            }
728
        }
729
    }
730
 
731
    checkProductsToPrice();
732
}
733
 
734
function findProductPrices(productId, pageNumber) {
735
    var n = productId.indexOf(" ");
736
    var productIdType = productId.substr(0, n);
737
    productId = productId.substr(n + 1);
738
 
739
    url = configeBayFinding + "?";
740
    if (productIdType == 'ReferenceID') {
741
        url += "OPERATION-NAME=findItemsByProduct";
742
    } else {
743
        url += "OPERATION-NAME=findItemsAdvanced";
744
    }
745
    url += "&RESPONSE-DATA-FORMAT=JSON";
746
    url += "&SECURITY-APPNAME=" + configAppid;
747
    url += "&SERVICE-VERSION=" + configeBayFindingVersion;
748
    url += "&GLOBAL-ID=EBAY-US";
749
    url += "&buyerPostalCode=";
750
    url += configZip;
751
    url += "&paginationInput.entriesPerPage=100";
752
    url += "&paginationInput.pageNumber=";
753
    url += pageNumber;
754
 
755
    if (productIdType == 'ReferenceID') {
756
        url += "&productId.@type=";
757
        url += productIdType;
758
        url += "&productId=";
759
        url += productId;
760
    } else {
761
        url += "&keywords=";
762
        url += productId;
763
    }
764
 
765
    url += "&itemFilter(0).name=ExcludeSeller";
766
    url += "&itemFilter(0).value=";
767
    url += configeBaySellerName;
768
 
769
    var xhttp = new XMLHttpRequest();
770
 
771
    xhttp.onreadystatechange = function() {
772
        if (this.readyState == 4) {
773
            _cb_findProductPrices(JSON.parse(this.responseText));
774
        }
775
    };
776
 
777
 
778
    xhttp.open("GET", configProxyUrl, true);
779
    xhttp.setRequestHeader("X-Proxy-Url", encodeURI(url));
780
    xhttp.send();
781
}
782
 
783
function _cb_findProductPrices(root) {
784
    var array;
785
    var response;
786
    var ack;
787
    var productId;
788
    var i;
789
    var currentPrice;
790
    var Title = "";
791
    var noLower;
792
    var noActive;
793
    var minPrice;
794
    var maxPrice;
795
    var conditionId;
796
    var currentConditionId;
797
    var noBetterCondition;
798
    var myPrice;
799
    var currentPriceInt;
800
    var minBetterCondition;
801
    var betterConditionbBreakdown = [];
802
    var sameConditionbBreakdown = [];
803
 
804
    if (root.findItemsAdvancedResponse !== undefined) {
805
        response = root.findItemsAdvancedResponse[0];
806
    } else if (root.findItemsByProductResponse !== undefined) {
807
        response = root.findItemsByProductResponse[0];
808
    } else {
809
        --productsToPrice;
810
        ++productsPriced;
811
        updateProgressBar(maxProductsToPrice, productsPriced);
812
        return;
813
    }
814
 
815
    ack = response.ack;
816
    if (ack != 'Success') {
817
        printeBayAPIError(response);
818
 
819
        if (ack == 'Failure' || ack == 'PartialFailure') {
820
            --productsToPrice;
821
            ++productsPriced;
822
            updateProgressBar(maxProductsToPrice, productsPriced);
823
            return;
824
        }
825
    }
826
 
827
    if (root.findItemsAdvancedResponse !== undefined) {
828
        array = typeof root.findItemsAdvancedResponse[0] != 'object' ? JSON.parse(root.findItemsAdvancedResponse[0]) : root.findItemsAdvancedResponse[0].searchResult[0].item;
829
        response = root.findItemsAdvancedResponse[0];
830
        url = new URL(response.itemSearchURL);
831
        productId = url.searchParams.get("_nkw");
832
    } else {
833
        array = typeof root.findItemsByProductResponse[0] != 'object' ? JSON.parse(root.findItemsByProductResponse[0]) : root.findItemsByProductResponse[0].searchResult[0].item;
834
        url = new URL(response.itemSearchURL);
835
        productId = url.searchParams.get("_productid");
836
    }
837
 
838
    var items = response.searchResult[0].item || [];
839
    noActive = Number(document.getElementById('Active' + productId).innerHTML);
840
    noLower = Number(document.getElementById('Lower' + productId).innerHTML);
841
    myPrice = Number(document.getElementById('Price' + productId).innerHTML.substr(1));
842
    minPrice = Number(document.getElementById('Minimum' + productId).innerHTML.substr(1));
843
    maxPrice = Number(document.getElementById('Maximum' + productId).innerHTML.substr(1));
844
    conditionId = Number(document.getElementById('Condition' + productId).innerHTML);
845
    noBetterCondition = Number(document.getElementById('BetterCondition' + productId).innerHTML);
846
    minBetterCondition = Number(document.getElementById('MinBetterCondition' + productId).innerHTML);
847
    betterConditionbBreakdown = JSON.parse(document.getElementById('BetterConditionBreakdown' + productId).innerHTML);
848
    sameConditionbBreakdown = JSON.parse(document.getElementById('SameConditionBreakdown' + productId).innerHTML);
849
 
850
    for (i = 0; i < items.length; i++) {
851
        Title = items[i].title[0].toLowerCase();
852
        if (Title.includes("disc only") > 0 ||
853
            Title.includes("disk only") > 0 ||
854
            Title.includes("only disc") > 0 ||
855
            Title.includes("only disk") > 0 ||
856
            Title.search(/dis[ck].*only/) > 0) {
857
            continue; // exclude "disc only listing
858
        }
859
 
860
        currentConditionId = (items[i].condition === undefined ? 0 : Number(items[i].condition[0].conditionId));
861
        currentPrice = Number(items[i].sellingStatus[0].convertedCurrentPrice[0].__value__);
862
        currentPriceInt = Math.ceil(currentPrice);
863
 
864
        if (currentConditionId > conditionId) {
865
            continue; // Like for like conditions only
866
        } else if (currentConditionId > conditionId) {
867
            if (minBetterCondition < 0.01 || minBetterCondition > currentPrice) {
868
                minBetterCondition = currentPrice;
869
            }
870
 
871
            ++noBetterCondition;
872
        }
873
 
874
        if (items[i].sellingStatus[0].bidCount === 0 && items[i].listingInfo[0].convertedBuyItNowPrice !== undefined) {
875
            currentPrice = Number(items[i].listingInfo[0].convertedBuyItNowPrice[0].__value__);
876
        }
877
 
878
        if (items[i].shippingInfo[0].shippingServiceCost) {
879
            currentPrice += Number(items[i].shippingInfo[0].shippingServiceCost[0].__value__);
880
        }
881
 
882
        if (currentConditionId > conditionId) {
883
            if (betterConditionbBreakdown[currentPriceInt] === undefined) {
884
                betterConditionbBreakdown[currentPriceInt] = 0;
885
            }
886
            ++betterConditionbBreakdown[currentPriceInt];
887
        } else {
888
            if (sameConditionbBreakdown[currentPriceInt] === undefined) {
889
                sameConditionbBreakdown[currentPriceInt] = 0;
890
            }
891
            ++sameConditionbBreakdown[currentPriceInt];
892
        }
893
 
894
        if (currentPrice < myPrice) {
895
            ++noLower;
896
        }
897
 
898
        if (minPrice < 0.01 || minPrice > currentPrice) {
899
            minPrice = currentPrice;
900
        }
901
 
902
        if (maxPrice < 0.01 || maxPrice < currentPrice) {
903
            maxPrice = currentPrice;
904
        }
905
 
906
        ++noActive;
907
    }
908
 
909
    document.getElementById('Active' + productId).innerHTML = noActive;
910
    document.getElementById('Lower' + productId).innerHTML = noLower;
911
    document.getElementById('Minimum' + productId).innerHTML = '$' + minPrice.toFixed(2);
912
    document.getElementById('Maximum' + productId).innerHTML = '$' + maxPrice.toFixed(2);
913
    document.getElementById('BetterCondition' + productId).innerHTML = noBetterCondition;
914
    document.getElementById('MinBetterCondition' + productId).innerHTML = minBetterCondition;
915
    document.getElementById('BetterConditionBreakdown' + productId).innerHTML = JSON.stringify(betterConditionbBreakdown);
916
    document.getElementById('SameConditionBreakdown' + productId).innerHTML = JSON.stringify(sameConditionbBreakdown);
917
 
918
    if (Number(response.paginationOutput[0].totalPages) > Number(response.paginationOutput[0].pageNumber)) {
919
        ++productsToPrice;
920
        ++maxProductsToPrice;
921
        var row = document.getElementById('Lower' + productId).parentNode.rowIndex;
922
        findProductPrices(document.getElementById("itemTable").rows[row].cells[4].innerText, Number(response.paginationOutput[0].pageNumber) + 1);
923
    }
924
 
925
    --productsToPrice;
926
    ++productsPriced;
927
    updateProgressBar(maxProductsToPrice, productsPriced);
928
}
929
 
930
function changePrice(itemId) {
931
    var i;
932
    var newPrice = parseFloat(document.getElementById('PriceAdj' + itemId).value).toFixed(2);
933
 
934
    if (isNaN(newPrice) || newPrice < configAdjMinPrice) {
935
        document.getElementById('PriceAdj' + itemId).value = '';
936
        return;
937
    }
938
 
939
    document.getElementById('PriceAdj' + itemId).value = newPrice;
940
 
941
    if (eBayAuthTokenFlag === false) {
942
        return;
943
    }
944
 
945
    var xw = new XMLWriter('UTF-8', '1.0');
946
    var xhr = new XMLHttpRequest();
947
 
948
    if (!createAddXML(xw, xhr, 'ReviseItemRequest', 'ReviseItem', itemId, newPrice)) {
949
        return;
950
    }
951
 
952
    xml = xw.flush();
953
    xw.close();
954
    //window.alert(vkbeautify.xml(xml));
955
 
956
    xhr.onload = function() {
957
        var obj = XMLparse(xhr.responseXML);
958
        //window.alert(JSON.stringify(obj));
959
        //window.alert(vkbeautify.xml(xhr.responseText));
960
 
961
        var returnCode = obj.Ack;
962
 
963
        var x = document.getElementById("results");
964
        if (x.className.indexOf("w3-show") == -1) {
965
            x.className += " w3-show";
966
        }
967
        x.className = x.className.replace(" process-errors", "");
968
 
969
        if (returnCode == 'Success' || (returnCode == 'Warning' && (obj.Errors.ErrorCode == '21917108' || obj.Errors.ErrorCode == '23007'))) {
970
            document.getElementById('PriceAdj' + itemId).style.color = "green";
971
 
972
            x.innerHTML = '<p><strong>' + returnCode + '</strong></p>';
973
 
974
            if (returnCode == 'Warning') {
975
                x.innerHTML += "<p>" + obj.Errors.SeverityCode + " (" + obj.Errors.ErrorCode + "): " + escapeHtml(obj.Errors.LongMessage) + "</p>";
976
                x.className += " process-errors";
977
            }
978
            var fees = obj.Fees;
979
            x.innerHTML += "<p>";
980
            for (i = 0; i < fees.length; i++) {
981
                if (fees[i].Fee.text !== "0.0") {
982
                    x.innerHTML += fees[i].Name + ": $" + Number(fees[i].Fee.text).toFixed(2) + "<br/>";
983
                }
984
            }
985
            x.innerHTML += "</p>";
986
 
987
            if (obj.DiscountReason) {
988
                x.innerHTML += "<p>Discount Reason: " + obj.DiscountReason + "</p>";
989
            }
990
 
991
            var recommendations = obj.ListingRecommendations;
992
            if (recommendations) {
993
                if (recommendations.length > 0) {
994
                    for (i = 0; i < recommendations.length; i++) {
995
                        x.innerHTML += decode(recommendations[i]);
996
                    }
997
                } else {
998
                    x.innerHTML += decode(recommendations);
999
                }
1000
            }
1001
        } else {
1002
            document.getElementById('PriceAdj' + itemId).style.color = "red";
1003
            x.innerHTML = "<p><strong>" + returnCode + ":</strong></p>";
1004
            x.className += " process-errors";
1005
 
1006
            var errors = obj.Errors;
1007
            x.innerHTML += "<p>";
1008
            if (errors.length > 0) {
1009
                for (i = 0; i < errors.length; i++) {
1010
                    x.innerHTML += errors[i].SeverityCode + " (" + errors[i].ErrorCode + "): " + escapeHtml(errors[i].LongMessage) + "<br/>";
1011
                }
1012
            } else {
1013
                x.innerHTML += obj.Errors.SeverityCode + " (" + obj.Errors.ErrorCode + "): " + escapeHtml(obj.Errors.LongMessage) + "<br/>";
1014
            }
1015
 
1016
            x.innerHTML += "</p>";
1017
        }
1018
 
1019
        if (obj.Message) {
1020
            x.innerHTML += obj.Message;
1021
        }
1022
 
1023
        if (!x.className.includes("process-errors")) {
1024
            setTimeout(function() {
1025
                x.className = x.className.replace(" w3-show", "");
1026
            }, 3000);
1027
        }
1028
    };
1029
 
1030
    xhr.send(xml);
1031
}
1032
 
1033
function createAddXML(xw, xhr, xmlrequest, callname, itemId, newPrice) {
1034
    xw.writeStartDocument();
1035
    xw.writeStartElement(xmlrequest);
1036
    xw.writeAttributeString('xmlns', 'urn:ebay:apis:eBLBaseComponents');
1037
 
1038
    xw.writeStartElement('RequesterCredentials');
1039
    xw.writeElementString('eBayAuthToken', eBayAuthToken);
1040
    xw.writeEndElement(); /* RequesterCredentials */
1041
 
1042
    xw.writeStartElement('Item');
1043
 
1044
    xw.writeStartElement('StartPrice');
1045
    xw.writeAttributeString('currencyID', 'USD');
1046
    xw.writeString(newPrice);
1047
    xw.writeEndElement(); /* StartPrice */
1048
 
1049
    //xw.writeElementString('ItemID', itemId);
1050
    xw.writeString('<ItemID>' + itemId + '</ItemID>');
1051
 
1052
    if (document.getElementById('BestOffer' + itemId).innerHTML == 'true') {
1053
        if (newPrice >= 14.99) {
1054
            var autoAcceptPrice = newPrice * configAutoAcceptPrice;
1055
            var minBestOfferPrice = newPrice * configMinBestOfferPrice;
1056
 
1057
            xw.writeStartElement('BestOfferDetails');
1058
            xw.writeElementString('BestOfferEnabled', 'true');
1059
            xw.writeEndElement(); /* BestOfferDetails */
1060
            xw.writeStartElement('ListingDetails');
1061
            xw.writeStartElement('BestOfferAutoAcceptPrice');
1062
            xw.writeAttributeString('currencyID', 'USD');
1063
            xw.writeString(autoAcceptPrice.toFixed(2));
1064
            xw.writeEndElement(); /* BestOfferAutoAcceptPrice */
1065
            xw.writeStartElement('MinimumBestOfferPrice');
1066
            xw.writeAttributeString('currencyID', 'USD');
1067
            xw.writeString(minBestOfferPrice.toFixed(2));
1068
            xw.writeEndElement(); /* MinimumBestOfferPrice */
1069
            xw.writeEndElement(); /* ListingDetails */
1070
        } else {
1071
            xw.writeStartElement('BestOfferDetails');
1072
            xw.writeElementString('BestOfferEnabled', 'false');
1073
            xw.writeEndElement(); /* BestOfferDetails */
1074
        }
1075
    }
1076
 
1077
    xw.writeEndElement(); /* Item */
1078
 
1079
    xw.writeElementString('ErrorLanguage', 'en_US');
1080
    xw.writeElementString('Version', configeBayTradingVersion);
1081
    xw.writeElementString('WarningLevel', configWarningLevel);
1082
 
1083
    xw.writeEndElement(); /* xmlrequest */
1084
    xw.writeEndDocument();
1085
 
1086
    xhr.open('POST', configProxyUrl, true);
1087
    xhr.setRequestHeader('Content-Type', 'text/xml');
1088
    xhr.setRequestHeader('X-EBAY-API-APP-NAME', configAppid);
1089
    xhr.setRequestHeader('X-EBAY-API-COMPATIBILITY-LEVEL', configeBayTradingVersion);
1090
    xhr.setRequestHeader('X-EBAY-API-CALL-NAME', callname);
1091
    xhr.setRequestHeader('X-EBAY-API-SITEID', '0');
1092
    xhr.setRequestHeader('X-EBAY-API-DEV-NAME', '');
1093
    xhr.setRequestHeader('X-EBAY-API-CERT-NAME', '');
1094
    xhr.setRequestHeader('X-Proxy-URL', configServiceEndpoint);
1095
 
1096
    return true;
1097
}
1098
 
1099
function connected() {
1100
    var x;
1101
 
1102
    eBayAuthTokenFlag = true;
1103
    document.getElementById("connected").innerHTML += " (Connected)";
1104
 
1105
    x = document.getElementById("login");
1106
    x.className = x.className.replace(" w3-show", "");
1107
 
1108
    x = document.getElementById("results");
1109
    x.innerHTML = "";
1110
    x.className = x.className.replace(" w3-show", "");
1111
}
1112
 
1113
    </script>
1114
 
1115
</body>
1116
</html>