PageSourceSearch

https://kittycorn.org/js/app.js

js kittycorn.org collected 2026-10-07 00:25:24 UTC 22,639 bytes, 615 lines download raw bytes

1var connectWalletButton = document.querySelector('#btn-connect');
2var bragButton = document.querySelector('#btn-brag');
3var contentPostBrag = document.querySelector('#content-post-brag');
4var contentPostBragGas = document.querySelector('#content-post-brag-gas');
5var contentMain = document.querySelector('#content-main');
6var contentFooter = document.querySelector('#content-footer');
7var bragText = document.querySelector('#textarea-field');
8var bragLikeButton;
9var bragReplyText;
10var bragReplyButton;
11var bragDetailButton;
12var account;
13var config;
14
15const cfg_payForLike = false;
16
17if (typeof window.ethereum !== 'undefined') {
18  console.log("Web3 detected!");
19
20  connectWalletButton.addEventListener('click', () => {
21      window.ethereum.enable();
22      getAccount();
23    });
24
25  async function getAccount() {
26    const accounts = await window.ethereum.request({ method: 'eth_accounts' });
27    account = accounts[0];
28    let accountDialog = document.getElementById("dialog-account");
29
30    if (account == undefined) {
31      connectWalletButton.innerHTML = "Connect";
32      connectWalletButton.classList.remove('btn-success');
33      connectWalletButton.classList.add('btn-outline-primary');
34      bragButton.innerHTML = "not connected";
35      bragButton.classList.remove('is-primary');
36      bragButton.classList.add('is-disabled');
37      bragReplyButton = document.querySelectorAll("#btn-brag-reply");
38      bragReplyButton.forEach(element => {
39        element.innerHTML = "not connected";
40        element.classList.remove('is-primary');
41        element.classList.add('is-disabled');
42      });
43    }
44    else {
45      /*function showLackingBratModal() {
46        document.getElementById('dialog-lacking-brat').showModal();
47      }*/
48      connectWalletButton.innerHTML = account.slice(0,5)+"..."+account.slice(38);
49      connectWalletButton.classList.remove('btn-outline-primary');
50      connectWalletButton.classList.add('btn-success');
51
52      window.getBratBalance(account).then(balance => {
53        if (balance < 1) {
54          bragButton.innerHTML = "not enough $BRAT";
55          bragButton.classList.remove('is-primary');
56          bragButton.classList.add('is-disabled');
57          //bragButton.addEventListener("click",showLackingBratModal());
58          bragReplyButton = document.querySelectorAll("#btn-brag-reply");
59          bragReplyButton.forEach(element => {
60            element.innerHTML = "not enough $BRAT";
61            element.classList.remove('is-primary');
62            element.classList.add('is-disabled');
63            //element.addEventListener("click",showLackingBratModal());
64          });
65        }
66        else {
67          bragButton.innerHTML = "braggg";
68          bragButton.classList.remove('is-disabled');
69          bragButton.classList.add('is-primary');
70          //bragButton.removeEventListener("click",showLackingBratModal());
71          bragReplyButton = document.querySelectorAll("#btn-brag-reply");
72          bragReplyButton.forEach(element => {
73            element.innerHTML = "Braggg Reply";
74            element.classList.remove('is-disabled');
75            element.classList.add('is-primary');
76            //bragButton.removeEventListener("click",showLackingBratModal());
77          });
78        }
79        window.getBragAddrIds(account).then(bragIds => {
80          let rank = judgeRank(balance);
81          accountDialog.children[0].children[0].innerHTML = 'Hi '+ account.slice(0,5)+"..."+account.slice(38) +'!';
82          accountDialog.children[0].children[1].innerHTML = 
83          '<span>Balance: '+balance+' BRAT</span><br><span>RANK: <span class="nes-text '+rank['class']+'">'+rank['title']+'</span>'+
84          '</span><br><span>Brags: '+bragIds.length+'</span>';
85        });
86      });
87
88      bragButton.addEventListener('click', () => {
89        window.postBrag(bragText.value,0).then(txId => {
90          window.waitForTx(txId).then(result => {
91            console.log(result);
92          });
93        });
94      });
95
96      forceChain();
97    }
98  }
99
100  async function forceChain() {
101    fetch('./js/config.json')
102    .then((response) => response.json())
103    .then(async function(config) {
104      var params = {
105        chainId: config.networks[config.activeNetwork].chainId,
106        chainName: config.networks[config.activeNetwork].chainName,
107        nativeCurrency: config.networks[config.activeNetwork].nativeCurrency,
108        rpcUrls: config.networks[config.activeNetwork].rpcUrls,
109        blockExplorerUrls: config.networks[config.activeNetwork].blockExplorerUrls,
110      }; 
111      
112
113      let result = await window.ethereum.request({
114        method: 'wallet_addEthereumChain',
115        params: [params],
116      });
117      return result;
118    });
119  }
120
121  document.addEventListener("DOMContentLoaded", function(){
122    getAccount();
123
124  });
125
126  ethereum.on('accountsChanged', (accounts) => {
127    getAccount();
128  });
129
130  ethereum.on('chainChanged', (chainId) => {
131    forceChain();
132    getAccount();
133    console.log("ChainId: "+chainId);
134  });
135
136  bragText.addEventListener('change', () => {
137    contentPostBragGas.innerHTML = "calculating"
138    window.calcGas(bragText.value).then(gasValue => {
139      contentPostBragGas.innerHTML = "Cost: \~"+gasValue/1e9*20+" ETH ("+gasValue+")"; // auto load gas Price??
140    });
141  });
142}
143
144/****************************************/
145/************* LOAD BRAGS ***************/
146/****************************************/
147
148function renderBrag(result,isReply=false,replyLevel=0,charLimit=false) {
149  var safeText = result['text'].replace(/[\u00A0-\u9999<>\&]/g, function(i) {
150    return '&#'+i.charCodeAt(0)+';';
151  }); 
152  safeText = safeText.replace(/\n/g, "<br>");
153  if (charLimit != false) {
154    safeText = (safeText.length > charLimit) ? safeText.substring(0, charLimit)+'&nbsp;<span class="nes-text is-primary">show more...</span>' : safeText;
155  }
156  var isLiked = (result['liked'] == true) ? " is-liked" : "";
157  var isReply = (isReply == true) ? " reply"+replyLevel : "";
158  var timestamp = timeDifference(result['timestamp']);
159
160  var rank = judgeRank(result['bratbalance']);
161
162  brag = 
163  '<div class="nes-container with-title'+isReply+'" data-bragid="'+result['id']+'">\n'+
164  '<span class="title">\n<a href="#u/'+result['owner']+'">'+
165  result['owner'].slice(0,9)+"..."+result['owner'].slice(38)+
166  '</a>&nbsp;'+timestamp+':</span>\n'+
167  '<p class="text" onclick="window.location=\'#b/'+result['id']+'\'">'+safeText+'</p>\n'+
168  '<span hidden>'+result['replies']+'</span>\n'+
169  '<i class="nes-icon is-small thumbs-up'+isLiked+'"></i>\n'+
170  '<span>'+result['likes']+'</span>\n'+
171  '<a class="nes-badge"><span class="'+rank['class']+'">'+rank['title']+'</span></a>'+
172  '<button class="nes-btn brags details">\n<span>&gt;</span>\n</button>\n'+
173  '</div>\n'+
174  '<div class="nes-container brag-details" data-detailid="'+result['id']+'" hidden>\n'+
175  '<p class="text">Brag ID: <span>'+result['id']+'</span></br>\n'+
176  'Tx ID: <span>...</span></br>\n'+
177  'Date: <span>
177'+new Date(result['timestamp'] * 1000).toLocaleString()+'</span></br>\n'+
178  '</p></div>';
179
180  return brag;
181}
182
183function seasonBragButtons() {
184  bragLikeButton = document.querySelectorAll(".thumbs-up");
185  bragLikeButton.forEach(element => {
186    if (!element.classList.contains("is-liked")) {
187      element.addEventListener("click", function(e) {
188        
189        let bragId = e.target.parentNode.dataset.bragid;
190
191        if (cfg_payForLike) { 
192          document.getElementById('dialog-like-step1').showModal();
193          window.approveBrat("1").then(txId => {
194            window.waitForTx(txId).then(result => {
195              if (result) {
196                document.getElementById('dialog-like-step1').close();
197                document.getElementById('dialog-like-step2').showModal();         
198                window.postLike(bragId).then(txId => {
199                  window.waitForTx(txId).then(result => {
200                    if (result) {
201                      document.getElementById('dialog-like-step2').close();
202                      document.getElementById('dialog-like-success').showModal();
203                    }
204                    else console.log(result);
205                  });
206                });
207              }
208              else console.log("failed");
209            });
210          });
211        }
212        else {
213          window.postLike(bragId).then(txId => {
214            console.log("number1: "+txId)
215            window.waitForTx(txId).then(result => {
216              console.log("number2: "+txId)
217              if (result) {
218                document.getElementById('dialog-like-success').showModal();
219              }
220              else console.log(result);
221            });
222          });
223        } 
224      });
225    }
226    else {
227      // we don't do unlikes
228    }
229  });
230
231  bragDetailButton = document.querySelectorAll(".details");
232  bragDetailButton.forEach(element => {
233    element.addEventListener("click", function(e) {
234      var bragId = e.target.parentNode.dataset.bragid;
235      var detailDiv = document.querySelector('[data-detailid="'+bragId+'"]');
236      if (detailDiv.hidden) {
237        detailDiv.hidden = false;
238        window.getBragTx(bragId).then(txId => {
239          if (txId == 0) {
240            detailDiv.querySelector("span:nth-child(3)").innerHTML = "n/a"
241          }
242          else {
243            detailDiv.querySelector("span:nth-child(3)").innerHTML = '<a href="https://etherscan.io/tx/'+txId+'" target="_blank">'+txId+'</a>';
244          }
245        });
246      }
247      else {
248        detailDiv.hidden = true;
249      }
250    });
251  });
252  return
253}
254
255function timeDifference(timestamp) {
256
257  var msPerMinute = 60 * 1000;
258  var msPerHour = msPerMinute * 60;
259  var msPerDay = msPerHour * 24;
260  var msPerMonth = msPerDay * 30;
261  var msPerYear = msPerDay * 365;
262
263  var elapsed = Date.now() - timestamp*1000;
264  var result;
265
266  if (elapsed < msPerMinute) {
267    result = Math.round(elapsed/1000);
268    if (result == 1) return result + ' second ago'; 
269    else return result + ' seconds ago'; 
270  }
271  else if (elapsed < msPerHour) {
272       result = Math.round(elapsed/msPerMinute);
273       if (result == 1) return result + ' minute ago'; 
274       else return result + ' minutes ago';    
275  }
276  else if (elapsed < msPerDay ) {
277       result = Math.round(elapsed/msPerHour);
278       if (result == 1) return result + ' hour ago'; 
279       else return result + ' hours ago';    
280  }
281  else if (elapsed < msPerMonth) {
282      result = Math.round(elapsed/msPerDay);
283      if (result == 1) return result + ' day ago'; 
284      else return result + ' days ago';     
285  }
286  else if (elapsed < msPerYear) {
287      result = Math.round(elapsed/msPerMonth);
288      if (result == 1) return result + ' month ago'; 
289      else return result + ' months ago';     
290  }
291  else {
292      result = Math.round(elapsed/msPerYear);
293      if (result == 1) return result + ' year ago'; 
294      else return result + ' years ago';       
295  }
296}
297
298/*function judgeRank (balance) {
299  var rank = new Array();
300  var factor = 1000;
301  if (balance < 1*factor) { rank['title'] = "Shrimp"; rank['class'] = "is-dark"; }
302  else if (balance >= 1*factor && balance < 5*factor) { rank['title'] = "Guppy"; rank['class'] = "is-dark"; }
303  else if (balance >= 5*factor && balance < 10*factor) { rank['title'] = "Flounder"; rank['class'] = "is-primary"; }
304  else if (balance >= 10*factor && balance < 20*factor) { rank['title'] = "Mackerel"; rank['class'] = "is-primary"; }
305  else if (balance >= 20*factor && balance < 50*factor) { rank['title'] = "Barracuda"; rank['class'] = "is-success"; }
306  else if (balance >= 50*factor && balance < 200*factor) { rank['title'] = "Dolphin"; rank['class'] = "is-success"; }
307  else if (balance >= 200*factor && balance < 1000*factor) { rank['title'] = "Shark"; rank['class'] = "is-warning"; }
308  else if (balance >= 1000*factor && balance < 10000*factor) { rank['title'] = "Giant Squid"; rank['class'] = "is-warning"; }
309  else if (balance >= 10000*factor) { rank['title'] = "Whale"; rank['class'] = "is-error"; }
310  return rank
311}*/
312
313function judgeRank (balance) {
314  var rank = new Array();
315  var factor = 1000;
316  if (balance < 1*factor) { rank['title'] = "Micro Peewee"; rank['class'] = "is-dark"; }
317  else if (balance >= 1*factor && balance < 5*factor) { rank['title'] = "Timid Twig"; rank['class'] = "is-dark"; }
318  else if (balance >= 5*factor && balance < 10*factor) { rank['title'] = "Petite Pepper"; rank['class'] = "is-primary"; }
319  else if (balance >= 10*factor && balance < 20*factor) { rank['title'] = "Modest Meat"; rank['class'] = "is-primary"; }
320  else if (balance >= 20*factor && balance < 50*factor) { rank['title'] = "Confid Cucumb"; rank['class'] = "is-success"; }
321  else if (balance >= 50*factor && balance < 200*factor) { rank['title'] = "Big Boy Wurst"; rank['class'] = "is-success"; }
322  else if (balance >= 200*factor && balance < 1000*factor) { rank['title'] = "Major Shlong"; rank['class'] = "is-warning"; }
323  else if (balance >= 1000*factor && balance < 10000*factor) { rank['title'] = "Giant Gherkin"; rank['class'] = "is-warning"; }
324  else if (balance >= 10000*factor) { rank['title'] = "Titanic T-Bone"; rank['class'] = "is-error"; }
325  return rank
326}
327
328window.getRecentBrags = async function(limit,offset=0) {
329  const start = Date.now();
330  var brag_section = document.querySelector('#brags');
331  var loading_text = document.querySelector('#loading-text');
332
333  window.getCurrentBragId().then(currentId => { // 12
334    currentId = currentId-1-offset;
335    if (limit > currentId) limit = currentId+1;
336    
337    // fetch recent brags from Blockchain
338    var brags = new Array();
339    for (let i=currentId; i>(currentId-limit); i--) {
340      brags[i] = window.fetchBragData(i,account);
341    }
342    console.log(`Execution time: ${Date.now() - start} ms`)
343    brags.reverse();
344
345    Promise.all(brags)
346    .then((results) => {
347      if (offset == 0) {
348        brag_section.innerHTML = '<h2 id="about" class="recent-brags"><a href="">#</a>Recent Brags</h2>';
349      }
350      else {
351        document.querySelector('.show-more').remove();
352      }
353      
354      for (let result of results) {
355        if (result !== undefined) {
356          brag_section.innerHTML += renderBrag(result,false,0,280);
357        }
358      }
359
360      if (currentId >= 0) {
361        brag_section.innerHTML += '<div class="nes-text is-primary show-more">\n'+
362        '<span>show more brags</span>\n</div>\n';
363        var showMoreButton = document.querySelector('.show-more');
364        showMoreButton.addEventListener('click', () => {
365          document.querySelector('.show-more > span').classList.add("dot-typing");
366          window.getRecentBrags(limit,offset+limit);
367        });
368      }
369      else {
370        brag_section.innerHTML += '<div class="nes-text" style="text-align:center;">\n'+
371        '<span>no more brags to show</span>\n</div>\n';
372      }
373
374      seasonBragButtons();
375      const end = Date.now();
376      console.log(`Execution time: ${end - start} ms`);
377    });
378  });
379}
380
381window.getBragsByAddress = async function(address,limit,offset=0) {
382  const start = Date.now();
383  let brag_section = document.querySelector('#brags');
384  let loading = document.querySelector('.loading');
385
386  let brags = new Array();
387  
388  window.getBragAddrIds(address).then(bragIds => { // 12
389    bragIds.sort(function(a, b){return b - a});
390
391    maxBrags = limit+offset>bragIds.length ? bragIds.length : limit+offset;
392
393    let i = offset; //
394    for (; i < maxBrags; i++) { // 5 5-10
395      brags[i] = window.fetchBragData(bragIds[i],account);
396    }
397
398    Promise.all(brags)
399    .then((results) => {
400      if (offset == 0) {
401        brag_section.innerHTML = '<h2 id="about" class="recent-brags"><a href="">#</a>
401Brags by '+address+'</h2>';
402      }
403      else {
404        document.querySelector('.show-more').remove();
405      }
406      
407      for (const result of results) {
408        if (result !== undefined) {
409          brag_section.innerHTML += renderBrag(result);
410        }
411      }
412
413      if (i == maxBrags) {
414        brag_section.innerHTML += '<div class="nes-text is-primary show-more">\n'+
415        '<span>show more brags</span>\n</div>\n';
416        var showMoreButton = document.querySelector('.show-more');
417        showMoreButton.addEventListener('click', () => {
418          document.querySelector('.show-more > span').classList.add("dot-typing");
419          window.getBragsByAddress(address,limit,offset+limit);
420        });
421      }
422      else {
423        brag_section.innerHTML += '<div class="nes-text" style="text-align:center;">\n'+
424        '<span>no more brags to show</span>\n</div>\n';
425      }
426
427      seasonBragButtons();
428      const end = Date.now();
429      console.log(`Execution time: ${end - start} ms`);
430    });
431  });
432}
433
434window.getBragReplies = async function(originalBragId,limit,offset=0) {
435  const start = Date.now();
436  let brag_section = document.querySelector('#brags');
437  let loading = document.querySelector('.loading');
438
439  let brags = new Array();
440  
441  window.getBragReplyIds(originalBragId).then(bragIds => {
442    bragIds.sort(function(a, b){return b - a});
443    console.log(bragIds);
444
445    maxBrags = limit+offset>bragIds.length ? bragIds.length : limit+offset;
446
447    let i = offset; //
448    for (; i < maxBrags; i++) { // 5 5-10
449      brags[i] = window.fetchBragData(bragIds[i],account);
450    }
451
452    Promise.all(brags)
453    .then((results) => {
454      if (offset == 0) {
455      }
456      else {
457        document.querySelector('.show-more').remove();
458      }
459      
460      for (const result of results) {
461        if (result !== undefined) {
462          brag_section.innerHTML += renderBrag(result,true);
463        }
464      }
465      console.log(i);
466      if (i == maxBrags) {
467        brag_section.innerHTML += '<div class="nes-text is-primary show-more">\n'+
468        '<span>show more brags</span>\n</div>\n';
469        var showMoreButton = document.querySelector('.show-more');
470        showMoreButton.addEventListener('click', () => {
471          document.querySelector('.show-more > span').classList.add("dot-typing");
472          window.getBragReplies(originalBragId,limit,offset+limit);
473        });
474      }
475      else {
476        brag_section.innerHTML += '<div class="nes-text" style="text-align:center;">\n'+
477        '<span>no more brags to show</span>\n</div>\n';
478      }
479
480      seasonBragButtons();
481      const end = Date.now();
482      console.log(`Execution time: ${end - start} ms`);
483    });
484  });
485}
486
487/****************************************/
488/*************** PROFILE ****************/
489/****************************************/
490
491
492
493/****************************************/
494/**************** PAGES *****************/
495/****************************************/
496
497function getPage() {
498  fireText();
499  var pathname = new String(window.location.hash);
500
501  fetch('./js/config.json')
502  .then((response) => response.json())
503  .then(async function(data) {
504    config = data;
505  });
506
507  if (pathname == "") { 
508    document.addEventListener("DOMContentLoaded", function(){
509      contentPostBrag.hidden = false;
510      window.getRecentBrags(5);
511    });
512  }
513  else if (pathname.substring(0,3) == "#u/") {
514
515    const regex = new RegExp('^0x[a-fA-F0-9]{40}$');
516    if (regex.test(pathname.substring(3,45))) {
517      contentPostBrag.hidden = true;
518      let address = pathname.substring(3,45);
519      window.getBragsByAddress(address,5);
520    }
521    else {
522      // 404
523    }
524  }
525  else if (pathname.substring(0,3) == "#b/") { 
526
527    const regex = new RegExp("^[0-9]\\d*$");
528    const i = pathname.replace('#b/','');
529    if (regex.test(i)) {
530      contentPostBrag.hidden = true;
531      var brag_section = document.querySelector('#brags');
532      brag_section.innerHTML = '<div class="loading">\n<img src="img/mana.gif">\n<p id="loading-text">loading...</p>\n</div>';
533
534      window.fetchBragData(i).then(result => {
535        brag_section.innerHTML = renderBrag(result);
536        //window.getBragReplies(i,5);
537      });
538    }
539    else {
540      // 404
541    }
542  }
543  else if (pathname.substring(0,10) == "#whitelist") { 
544    fetch("templates/whitelist.html").then(response => {
545      contentPostBrag.hidden = true;
546      response.text().then(html => {
547        contentMain.innerHTML = html;
548      });
549    });
550  }
551  else if (pathname.substring(0,5) == "#brat") { 
552    fetch("templates/brat.html").then(response => {
553      contentPostBrag.hidden = true;
554      response.text().then(html => {    
555
556        window.getSaleRoundDetails().then(result => {
557          contentMain.innerHTML = html;
558          let roundBlock = document.querySelector('[data-round="'+result['currentRound']+'"]');
559
560          let progress = roundBlock.children[1].children[1];
561          progress.value = (result['roundTotalAmount']-result['roundAmountLeft'])*100/result['roundTotalAmount'];
562          
563          let amountSold = roundBlock.children[1].children[2];
564          amountSold.innerHTML = result['roundTotalAmount']-result['roundAmountLeft'];
565
566          let amountTotal = roundBlock.children[1].children[3];
567          amountTotal.innerHTML = result['roundTotalAmount'];
568
569          let maxUserAmount = roundBlock.children[3].children[1];
570          maxUserAmount.innerHTML = result['maxUserAmount'];
571
572          var buyButton = document.querySelector('#btn-buy');
573          buyButton.addEventListener('click', () => {
574            window.saleBuy("0").then(txId => {
575              window.waitForTx(txId).then(result => {
576                console.log(result);
577              });
578            });
579          });
580
581        });
582      });
583    });
584  }
585  else if (pathname.substring(0,4) == "#api") { 
586    fetch("templates/api.html").then(response => {
587      contentPostBrag.hidden = true;
588      response.text().then(html => {
589        contentMain.innerHTML = html;
590      });
591    });
592  }
593  //console.log(window.location.hash);
594}
595
596getPage();
597window.addEventListener('hashchange', function () {
598  getPage();
599});
600
601function fireText() {
602  console.log(
603    " /$$                                                                 "+ '\n' +
604    "| $$                                                                 "+ '\n' +
605    "| $$$$$$$   /$$$$$$  /$$$$$$   /$$$$$$   /$$$$$$   /$$$$$$   /$$$$$$ "+ '\n' +
606    "| $$__  $$ /$$__  $$|____  $$ /$$__  $$ /$$__  $$ /$$__  $$ /$$__  $$"+ '\n' +
607    "| $$  \\ $$| $$  \\__/ /$$$$$$$| $$  \\ $$| $$  \\ $$| $$$$$$$$| $$  \\__/"+ '\n' +
608    "| $$  | $$| $$      /$$__  $$| $$  | $$| $$  | $$| $$_____/| $$      "+ '\n' +
609    "| $$$$$$$/| $$     |  $$$$$$$|  $$$$$$$|  $$$$$$$|  $$$$$$$| $$      "+ '\n' +
610    "|_______/ |__/      \\_______/ \\____  $$ \\____  $$ \\_______/|__/      "+ '\n' +
611    "                              /$$  \\ $$ /$$  \\ $$                    "+ '\n' +
612    "                             |  $$$$$$/|  $$$$$$/                    "+ '\n' +
613    "                              \\______/  \\______/                     ");
614}
615

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.