Subversion Repositories munaweb

Rev

Rev 4 | Rev 6 | Go to most recent revision | Details | Compare with Previous | 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 Listing Promotion</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
    <script src="js/jquery.js"></script>
12
    <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
13
    <link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
14
    <link rel="stylesheet" href="css/style.css">
15
    <script src="js/XMLWriter.js"></script>
16
    <script src="js/lodash.min.js"></script>
17
    <script src="js/XMLparse.js"></script>
18
    <script src="js/moment.js"></script>
19
    <script src="js/moment-timezone.js"></script>
20
    <script src="js/muna-tools.js"></script>
21
</head>
22
 
23
<body onload="return initConfig();">
24
    <div class="w3-main">
25
        <div class="w3-container w3-padding w3-margin w3-card-4">
26
            <div class="w3-container w3-gray" style="height:100px">
27
                <img class="w3-image" src="images/MUNA%20-%20Logo%20100x100.png" alt="MUNA Trading Logo" style="height:100px">
28
                <p id="connected" class="w3-xxlarge w3-right">eBay Listing Promotion
29
                    <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" />
30
               	</p>
31
            </div>
32
 
33
            <div class="w3-row">
34
                <div>
35
                    <form id="searchForm" class="w3-container w3-light-grey w3-padding w3-small" onsubmit="return getListingsForPromote();">
36
                        <div class="w3-container w3-card-2 w3-cell w3-padding">
37
                        	<textarea id="bearer" rows="4" cols="80"></textarea>
38
                            <input id="promoteButton" type="button" class="w3-btn w3-large w3-red w3-margin w3-round-large w3-ripple" onclick="getListingsForPromote();" value="Promote" />
39
                        </div>
40
                    </form>
41
                </div>
42
                <div id="progressBarDiv" class="w3-container w3-padding w3-margin w3-card-4 w3-hide">
43
                  	<h2 id="progressBarHeader"></h2>
44
                    <div class="w3-light-grey">
45
                        <div id="progressBar" class="w3-container w3-green w3-center" style="width:0%">0%</div>
46
                    </div>
47
                </div>
48
                <div id="results" class="w3-container w3-padding w3-card-4 w3-hide"></div>
49
                <div id="logging" class="w3-container w3-padding"></div>
50
            </div>
51
        </div>
52
 
53
        <footer class="w3-container w3-center w3-border-top w3-margin">
54
            Copyright &#169; 2018 MUNA Trading. All rights reserved.
55
        </footer>
56
 
57
    </div>
58
 
59
    <script>
60
 
61
// Config
62
var configCampaignId = '10477406018';
63
 
64
var pagesToProcess = 0;
65
var pagesProcessed = 0;
66
var html = [];
67
 
68
// Initialize Configuration Variables
69
function initConfig() {
70
    eBayAuthToken = readCookie();
71
    if (eBayAuthToken.length > 0) {
72
        connected();
73
    }
74
 
75
    if (eBayAuthTokenFlag === false) {
76
        var x = document.getElementById("login");
77
        if (x.className.indexOf("w3-show") == -1) {
78
            x.className += " w3-show";
79
        }
80
    }
3 - 81
 
82
    getOAuthToken();
2 - 83
}
84
 
85
function requireNewLogin() {
86
    // dummy
87
}
88
 
89
function connected() {
90
    var x;
91
 
92
    eBayAuthTokenFlag = true;
93
    document.getElementById("connected").innerHTML += " (Connected)";
94
 
95
    x = document.getElementById("promoteButton");
96
    x.className = x.className.replace(" w3-red", " w3-black");
97
 
98
    x = document.getElementById("login");
99
    x.className = x.className.replace(" w3-show", "");
100
 
101
    x = document.getElementById("results");
102
    x.innerHTML = "";
103
    x.className = x.className.replace(" w3-show", "");
104
    x.className = x.className.replace("process-errors", "");
105
}
106
 
107
function getListingsForPromote() {
108
    var x;
109
 
110
    if (eBayAuthTokenFlag === false) {
111
        return;
112
    }
113
 
114
    userAccessToken = document.getElementById("bearer").value;
115
    if (userAccessToken.length < 1) {
116
        return;
117
    }
118
 
119
    document.getElementById("logging").innerHTML = '';
120
 
121
    x = document.getElementById("results");
122
    if (x.className.indexOf("w3-show") == -1) {
123
        x.className += " w3-show";
124
    }
125
    x.innerHTML = '<p><strong>Retrieving Listings...</strong></p>';
126
    x.className = x.className.replace("process-errors", "");
127
 
128
    pagesToProcess = 1;
129
    pagesProcessed = 0;
130
    initProgressBar("Retrieving Listings...");
131
    eBaySearch(1);
132
 
133
    function checkpagesToProcess() {
134
        if (pagesToProcess > 0) {
135
            window.setTimeout(checkpagesToProcess, 300); // wait 100 milliseconds
136
        } else {
137
            endProgressBar();
138
            document.getElementById("results").innerHTML += '<p><strong>Sorting / Cleaning List...</strong></p>';
139
            sortTable();
140
            removeDuplicateRows($('#promoteTable'));
141
            processCurrentAds();
142
        }
143
    }
144
 
145
    checkpagesToProcess();
146
}
147
 
148
function processCurrentAds() {
149
    adsToRead = 1;
150
    getCurrentAds(1);
151
 
152
    function checkAdsToRead() {
153
        if (adsToRead > 0) {
154
            window.setTimeout(checkAdsToRead, 100); // wait 100 milliseconds
155
        } else {
156
            updateAds();
157
        }
158
    }
159
 
160
    checkAdsToRead();
161
}
162
 
163
function updateAds() {
164
    var i = 1;
165
    var pt = document.getElementById("promoteTable");
166
    var x;
167
    var updateList = [];
168
    var addList = [];
169
    var entry;
170
    var maxAds = 500;
171
 
172
    adsToUpdate = 0;
173
 
174
    for (i = 1; i < pt.rows.length; i++) {
175
        if (pt.rows[i].cells[1].innerHTML != pt.rows[i].cells[3].innerHTML) {
176
            entry = '{"bidPercentage":"' + pt.rows[i].cells[1].innerHTML + '","listingId" : "' + pt.rows[i].cells[0].innerHTML + '"}';
177
            if (pt.rows[i].cells[2].innerHTML.length > 0) {
178
                if (updateList.indexOf(entry) == -1) {
179
                    updateList.push(entry);
180
                }
181
            } else {
182
                if (addList.indexOf(entry) == -1) {
183
                    addList.push(entry);
184
                }
185
            }
186
        }
187
    }
188
 
189
    for (i = 0; (i * maxAds) < updateList.length; i++) {
190
        ++adsToUpdate;
191
        updateAd(1, updateList.slice(i * maxAds, (i + 1) * maxAds));
192
    }
193
 
194
    for (i = 0; (i * maxAds) < addList.length; i++) {
195
        ++adsToUpdate;
196
        updateAd(0, addList.slice(i * maxAds, (i + 1) * maxAds));
197
    }
198
 
199
    function checkAdsToUpdate() {
200
        if (adsToUpdate > 0) {
201
            window.setTimeout(checkAdsToUpdate, 100); // wait 100 milliseconds
202
        } else {
203
            x = document.getElementById("results");
204
            x.innerHTML += '<p><strong>Report Finished!</strong></p>';
205
            if (!x.className.includes("process-errors")) {
206
                setTimeout(function() {
207
                    x.className = x.className.replace(" w3-show", "");
208
                }, 3000);
209
            }
210
        }
211
    }
212
 
213
    checkAdsToUpdate();
214
}
215
 
216
function getCurrentAds(pageNumber) {
217
    var i;
218
    var response;
219
    var limit = 500;
220
    url = configeBayAdCampaign;
221
    url += configCampaignId;
222
    url += '/ad?';
223
    url += 'offset=';
224
    url += (pageNumber - 1) * limit;
225
    url += '&limit=';
226
    url += limit;
227
 
228
    var xhttp = new XMLHttpRequest();
229
 
230
    xhttp.onreadystatechange = function() {
231
        if (this.readyState == 4) {
232
            if (this.status == 200) {
233
                response = JSON.parse(this.responseText);
234
 
235
                for (i = 0; i < response.ads.length; i++) {
236
                    itemId = response.ads[i].listingId;
237
                    if (document.getElementById('AdId' + itemId) !== null) {
238
                        document.getElementById('AdId' + itemId).innerHTML = response.ads[i].adId;
239
                        document.getElementById('CurrentRate' + itemId).innerHTML = response.ads[i].bidPercentage;
240
                    }
241
                }
242
 
243
                if (Number(response.total) > (pageNumber * limit)) {
244
                    ++adsToRead;
245
                    document.getElementById("results").innerHTML += '<p><strong>Retrieving Ads (' + pageNumber + '/' + Number((response.total / limit) + 1).toFixed(0) + ')</strong></p>';
246
                    getCurrentAds(pageNumber + 1);
247
                }
248
            }
249
 
250
            --adsToRead;
251
        }
252
    };
253
 
254
    xhttp.open("GET", configProxyUrl, true);
255
    xhttp.setRequestHeader("X-Proxy-Url", encodeURI(url));
256
    xhttp.setRequestHeader('X-Authorization', 'Bearer ' + userAccessToken);
257
    xhttp.send();
258
}
259
 
260
function updateAd(flag, list) {
261
    var xhttp;
262
    var json;
263
    var i;
264
    var obj;
265
 
266
    if (list.length === 0) {
267
        return;
268
    }
269
 
270
    json = '{"requests":[' + list.join(',') + ']}';
271
 
272
    if (flag) {
273
        url = configeBayAdCampaign;
274
        url += configCampaignId;
275
        url += '/bulk_update_ads_bid_by_listing_id';
276
 
277
        xhttp = new XMLHttpRequest();
278
 
279
        xhttp.onreadystatechange = function() {
280
            if (this.readyState == 4) {
281
                obj = JSON.parse(this.responseText);
282
                if (this.status == 200 || this.status == 207) {
283
                    for (i = 0; i < obj.responses.length; i++) {
284
                        if (Number(obj.responses[i].statusCode) == 200) {
285
                            document.getElementById('AdId' + obj.responses[i].listingId).innerHTML = obj.responses[i].adId;
286
                            document.getElementById('UpdateStatus' + obj.responses[i].listingId).innerHTML = 'Updated';
287
                            document.getElementById('UpdateStatus' + obj.responses[i].listingId).style.color = 'green';
288
                        } else {
289
                            document.getElementById('UpdateStatus' + obj.responses[i].listingId).innerHTML = 'Update Failed (';
290
                            if (obj.responses[i].errors !== undefined) {
291
                                document.getElementById('UpdateStatus' + obj.responses[i].listingId).innerHTML += obj.responses[i].errors[0].message;
292
                            } else if (obj.responses[i].statusCode !== undefined) {
293
                                document.getElementById('UpdateStatus' + obj.responses[i].listingId).innerHTML += obj.responses[i].statusCode;
294
                            }
295
                            document.getElementById('UpdateStatus' + obj.responses[i].listingId).innerHTML += ')';
296
                            document.getElementById('UpdateStatus' + obj.responses[i].listingId).style.color = 'red';
297
                        }
298
                    }
299
                } else {
300
                    var x = document.getElementById("results");
301
                    x.className += " process-errors";
302
                    x.innerHTML += '<p class="w3-red">Bulk Update Ads: <strong>' + this.status + '</strong></p>';
303
                }
304
 
305
                --adsToRead;
306
            }
307
        };
308
 
309
        xhttp.open("POST", configProxyUrl, true);
310
        xhttp.setRequestHeader("X-Proxy-Url", encodeURI(url));
311
        xhttp.setRequestHeader('X-Authorization', 'Bearer ' + userAccessToken);
312
        xhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
313
        xhttp.send(json);
314
 
315
    } else {
316
        url = configeBayAdCampaign;
317
        url += configCampaignId;
318
        url += '/bulk_create_ads_by_listing_id';
319
 
320
        xhttp = new XMLHttpRequest();
321
 
322
        xhttp.onreadystatechange = function() {
323
            if (this.readyState == 4) {
324
                obj = JSON.parse(this.responseText);
325
                if (this.status == 200 || this.status == 207) {
326
                    for (i = 0; i < obj.responses.length; i++) {
327
                        if (Number(obj.responses[i].statusCode) == 201) {
328
                            document.getElementById('AdId' + obj.responses[i].listingId).innerHTML = obj.responses[i].adId;
329
                            document.getElementById('UpdateStatus' + obj.responses[i].listingId).innerHTML = 'Added';
330
                            document.getElementById('UpdateStatus' + obj.responses[i].listingId).style.color = 'green';
331
                        } else {
332
                            document.getElementById('UpdateStatus' + obj.responses[i].listingId).innerHTML = 'Add Failed (' + obj.responses[i].errors[0].message + ')';
333
                            document.getElementById('UpdateStatus' + obj.responses[i].listingId).style.color = 'red';
334
                        }
335
                    }
336
                } else {
337
                    var x = document.getElementById("results");
338
                    x.className += " process-errors";
339
                    x.innerHTML += '<p class="w3-red">Bulk Create Ads: <strong>' + this.status + '</strong></p>';
340
                }
341
 
342
                --adsToRead;
343
            }
344
        };
345
 
346
        xhttp.open("POST", configProxyUrl, true);
347
        xhttp.setRequestHeader("X-Proxy-Url", encodeURI(url));
348
        xhttp.setRequestHeader('X-Authorization', 'Bearer ' + userAccessToken);
349
        xhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
350
        xhttp.send(json);
351
    }
352
 
353
    --adsToUpdate;
354
}
355
 
356
 
357
// Build an HTML table to display search results
358
function eBaySearch(pageNo) {
359
    var i;
360
    var xml;
361
 
362
    if (eBayAuthTokenFlag === false) {
363
        return;
364
    }
365
 
366
    var xw = new XMLWriter('UTF-8', '1.0');
367
    var xhr = new XMLHttpRequest();
368
 
369
    if (!createAddXMLSearch(xw, xhr, 'GetSellerList', pageNo)) {
370
        return;
371
    }
372
 
373
    xml = xw.flush();
374
    xw.close();
375
 
376
    xhr.onload = function() {
377
        var obj = XMLparse(xhr.responseXML);
378
 
379
        var returnCode = obj.Ack;
380
 
381
        var x = document.getElementById("results");
382
 
383
        if (returnCode == 'Success') {
384
            createTable(obj.ItemArray, pageNo, Number(obj.PaginationResult.TotalNumberOfPages));
385
 
386
            if (Number(obj.PaginationResult.TotalNumberOfPages) > pageNo) {
387
                maxPagesToProcess = Number(obj.PaginationResult.TotalNumberOfPages);
388
                ++pagesToProcess;
389
                eBaySearch(pageNo + 1);
390
            }
391
 
392
            updateProgressBar(maxPagesToProcess, pagesProcessed);
393
        } else {
394
            x.className += " process-errors";
395
            x.innerHTML += '<p class="w3-red"><strong>' + returnCode + ':</strong></p>';
396
            var errors = obj.Errors;
397
            x.innerHTML += "<p>";
398
            if (errors.length > 0) {
399
                for (i = 0; i < errors.length; i++) {
400
                    x.innerHTML += errors[i].SeverityCode + " (" + errors[i].ErrorCode + "): " + escapeHtml(errors[i].LongMessage) + "<br/>";
401
                }
402
            } else {
403
                x.innerHTML += obj.Errors.SeverityCode + " (" + obj.Errors.ErrorCode + "): " + escapeHtml(obj.Errors.LongMessage) + "<br/>";
404
            }
405
            x.innerHTML += "</p>";
406
        }
407
 
408
        --pagesToProcess;
409
        ++pagesProcessed;
410
 
411
        document.getElementById("logging").innerHTML = html.join('');
412
        updateProgressBar(maxPagesToProcess, pagesProcessed);
413
    };
414
 
415
    xhr.send(xml);
416
}
417
 
418
function createAddXMLSearch(xw, xhr, callname, pageNo) {
419
    var startDate = moment(moment().subtract(31, "days").format('YYYY-MM-DD') + " 00:00:00", "YYYY-MM-DD HH:mm:ss").tz("UTC").toISOString();
420
    var todayDate = moment(moment().format('YYYY-MM-DD') + " 23:59:59", "YYYY-MM-DD HH:mm:ss").tz("UTC").toISOString();
421
    var endDate = moment(moment().add(31, "days").format('YYYY-MM-DD') + " 00:00:00", "YYYY-MM-DD HH:mm:ss").tz("UTC").toISOString();
422
 
423
    xw.writeStartDocument();
424
    xw.writeStartElement(callname + "Request");
425
    xw.writeAttributeString('xmlns', 'urn:ebay:apis:eBLBaseComponents');
426
 
427
    xw.writeStartElement('RequesterCredentials');
428
    xw.writeElementString('eBayAuthToken', eBayAuthToken);
429
    xw.writeEndElement(); /* RequesterCredentials */
430
 
431
    xw.writeElementString('GranularityLevel', 'Coarse');
432
    xw.writeElementString('StartTimeFrom', startDate);
433
    xw.writeElementString('StartTimeTo', todayDate);
434
    xw.writeElementString('EndTimeFrom', todayDate);
435
    xw.writeElementString('EndTimeTo', endDate);
436
    xw.writeElementString('OutputSelector', 'ItemArray.Item.ItemID');
437
    xw.writeElementString('OutputSelector', 'ItemArray.Item.ListingType');
438
    xw.writeElementString('OutputSelector', 'PaginationResult');
439
    xw.writeElementString('OutputSelector', 'ItemArray.Item.SellingStatus.ConvertedCurrentPrice');
440
    xw.writeStartElement('Pagination');
441
    xw.writeElementString('EntriesPerPage', '200');
442
    xw.writeElementString('PageNumber', '' + pageNo);
443
    xw.writeEndElement(); /* Pagination*/
444
 
445
    xw.writeElementString('ErrorLanguage', 'en_US');
446
    xw.writeElementString('Version', configeBayTradingVersion);
447
    xw.writeElementString('WarningLevel', configWarningLevel);
448
 
449
    xw.writeEndElement(); /* xmlrequest */
450
    xw.writeEndDocument();
451
 
452
    xhr.open('POST', configProxyUrl, true);
453
    xhr.setRequestHeader('Content-Type', 'text/xml');
454
    xhr.setRequestHeader('X-EBAY-API-APP-NAME', configAppid);
455
    xhr.setRequestHeader('X-EBAY-API-COMPATIBILITY-LEVEL', configeBayTradingVersion);
456
    xhr.setRequestHeader('X-EBAY-API-CALL-NAME', callname);
457
    xhr.setRequestHeader('X-EBAY-API-SITEID', '0');
458
    xhr.setRequestHeader('X-EBAY-API-DEV-NAME', '');
459
    xhr.setRequestHeader('X-EBAY-API-CERT-NAME', '');
460
    xhr.setRequestHeader('X-Proxy-URL', configServiceEndpoint);
461
 
462
    return true;
463
}
464
 
465
function createTable(obj, pageNumber, totalPages) {
466
    var currentPrice;
467
    var adRate;
468
 
469
    if (pageNumber == 1) {
470
        document.getElementById("logging").innerHTML = '';
471
        html = [];
472
 
473
        html.push('<h3>Listing Promotions</h3>');
474
        html.push('<div class="w3-responsive">');
475
        html.push('<table id="promoteTable" class="w3-table-all w3-hoverable">');
476
        html.push('<thead>');
477
        html.push('<tr>');
478
 
479
        html.push(tableHeader('Item ID'));
480
        html.push(tableHeader('New Ad Rate'));
481
        html.push(tableHeader('Ad Id'));
482
        html.push(tableHeader('Current Ad Rate'));
483
        html.push(tableHeader('Create/Update Status'));
484
 
485
        html.push('</tr>');
486
        html.push('</thead>');
487
        html.push('<tbody>');
488
    }
489
 
490
    for (var entry = 0; entry < obj.length; entry++) {
491
 
492
        if (obj[entry].ListingType == 'Chinese') {
493
            continue;
494
        }
495
 
496
        currentPrice = Number(obj[entry].SellingStatus.text).toFixed(2);
497
 
498
        // minimum ad rate is 1.00%
499
        if (currentPrice > 99.99) {
500
            adRate = 2.0;
501
        } else if (currentPrice > 49.99) {
502
            adRate = 2.7;
503
        } else if (currentPrice > 29.99) {
504
            adRate = 3.0;
505
        } else if (currentPrice > 19.99) {
506
            adRate = 3.2;
507
        } else if (currentPrice > 14.99) {
508
            adRate = 3.5;
509
        } else if (currentPrice > 9.99) {
510
            adRate = 3.7;
511
        } else if (currentPrice > 4.99) {
512
            adRate = 4.0;
513
        } else if (currentPrice > 3.99) {
514
            adRate = 4.2;
515
        } else {
516
            continue;
517
        }
518
 
519
        html.push('<tr>');
520
 
521
        html.push(tableCell(obj[entry].ItemID));
522
        html.push(tableCell(Number(adRate).toFixed(1)));
523
        html.push(tableCellLabel('AdId' + obj[entry].ItemID));
524
        html.push(tableCellLabel('CurrentRate' + obj[entry].ItemID));
525
        html.push(tableCellLabel('UpdateStatus' + obj[entry].ItemID));
526
 
527
        html.push('</tr>');
528
    }
529
 
530
    if (pageNumber == totalPages) {
531
        html.push('</tbody>');
532
        html.push('</table>');
533
        html.push('</div>');
534
    }
535
}
536
 
537
function sortTable() {
538
    var i;
539
    var tbl = document.getElementById("promoteTable").tBodies[0];
540
    var store = [];
541
    for (i = 0, len = tbl.rows.length; i < len; i++) {
542
        var row = tbl.rows[i];
543
        var sortnr = parseFloat(row.cells[0].textContent || row.cells[0].innerText);
544
        if (!isNaN(sortnr)) store.push([sortnr, row]);
545
    }
546
    store.sort(function(x, y) {
547
        return x[0] - y[0];
548
    });
549
    for (i = 0, len = store.length; i < len; i++) {
550
        tbl.appendChild(store[i][1]);
551
    }
552
    store = null;
553
}
554
 
3 - 555
function getOAuthToken() {
556
    var code = "";
557
 
558
	var win = window.open(configeBayLoginUrl, "eBay OAUTH", "");
559
 
560
	var pollTimer = window.setInterval(function() {
561
		if (win.closed !== false) {
562
			window.clearInterval(pollTimer);
563
			getApplicationToken(code);
564
		} else {
565
		    if (code === null || code.length === 0) {
566
                try {
567
                  code = getUrlParameter(win, 'code');
568
                } catch(err) {
569
                  // empty
570
                }
571
		    }
572
		}
573
	}, 200);
574
 
575
}
576
 
577
function getApplicationToken(code) {
578
    var param;
579
 
580
    param = 'grant_type=authorization_code';
581
    param += '&code=' + code;
582
    param += '&redirect_uri=' + configRuName;
583
 
584
    var xhttp = new XMLHttpRequest();
585
 
586
    xhttp.onreadystatechange = function() {
587
        if (this.readyState == 4) {
588
            if (this.status == 200) {
589
                response = JSON.parse(this.responseText);
590
 
591
            	document.getElementById("bearer").innerHTML = getJsonValue(response.access_token);
592
            }
593
        }
594
    };
595
 
596
    xhttp.open("POST", configProxyUrl, true);
597
    xhttp.setRequestHeader("X-Proxy-Url", configOauthTokenUrl);
598
    xhttp.setRequestHeader('X-Authorization', 'Basic ' + btoa(configAppid + ':' + configCertid));
4 - 599
    xhttp.setRequestHeader('X-DECODE-PARAMS', '1');
3 - 600
 
601
    xhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
602
    xhttp.send(param);
603
}
2 - 604
    </script>
605
 
606
</body>
607
</html>