gyakkun / Show Site-Age of User Alpha

// ==UserScript==
// @name          Show Site-Age of User Alpha
// @author        gyakkun
// @description   How old are you?
// @license       MIT
// @version       0.0.11
// @match        *://bangumi.tv/*
// @match        *://bgm.tv/*
// @match        *://chii.in/*
// @updateURL    https://openuserjs.org/meta/gyakkun/Show_Site-Age_of_User_Alpha.meta.js
// @downloadURL https://openuserjs.org/install/gyakkun/Show_Site-Age_of_User_Alpha.user.js
// @grant none
// ==/UserScript==

(function () {
  //'use strict';

  var PATH = window.location.pathname
  const UID_LIST = [1, 10, 100, 1125, 1250, 1375, 1425, 1500, 2500, 2800, 2950, 3000, 3200, 3300, 4200, 5000, 5750, 6500, 6825, 7500, 7800, 8000, 9000, 9500, 10000, 10500, 11000, 11750, 12500, 13000, 13500, 14000, 15500, 16500, 25000, 32500, 35000, 40000, 50000, 55000, 57500, 60000, 63750, 66000, 70000, 72500, 77500, 80000, 85000, 90000, 95000, 97500, 101000, 105000, 110000, 115000, 120000, 127500, 131000, 135000, 140000, 150000, 155000, 160000, 165000, 170000, 175000, 180000, 185000, 190000, 199000, 200000, 205000, 207500, 210000, 215000, 220000, 222500, 225000, 230000, 235000, 237500, 240000, 245000, 250000, 255000, 260000, 262500, 265000, 267500, 270000, 275000, 277500, 280000, 285000, 287500, 290000, 295000, 300000, 305000, 310000, 307500, 312500, 315000, 317500, 320000, 325000, 330000, 335000, 340000, 350000, 355000, 360000, 370000, 380000, 390000, 395000, 400000, 405000, 410000, 415000, 420000, 425000, 430000, 435000, 437500, 440000, 445000, 450000, 455000, 460000, 465000, 470000, 475000, 480000, 485000, 490000, 500000, 505000, 510000, 515000, 520000, 525000, 530000, 535000, 540000, 545000, 550000, 555000, 557500, 560000, 562500, 565000, 570000, 580000, 585000, 590000, 600000, 605000, 610000, 620000, 630000, 640000, 645000, 650000, 660000, 670000, 680000, 685000, 690000, 700000, 710000, 720000, 730000, 735000, 740000, 750000, 760000, 770000, 775000, 782500, 788750, 794375, 800675, 808750, 816250, 824375, 832500, 840000, 846250, 852500]
  const UID_DATE = [1213804800000, 1215964800000, 1217520000000, 1220889600000, 1223596800000, 1226966400000, 1229212800000, 1231603200000, 1233417600000, 1235836800000, 1239984000000, 1241712000000, 1244563200000, 1247241600000, 1249228800000, 1252080000000, 1254499200000, 1257523200000, 1259683200000, 1262966400000, 1265385600000, 1268841600000, 1271779200000, 1274371200000, 1277395200000, 1280160000000, 1282320000000, 1284480000000, 1287532800000, 1289865600000, 1291939200000, 1293811200000, 1297180800000, 1299081600000, 1301932800000, 1305648000000, 1306944000000, 1309708800000, 1313510400000, 1316880000000, 1318723200000, 1320768000000, 1323820800000, 1325779200000, 1328544000000, 1330617600000, 1334678400000, 1336492800000, 1340380800000, 1343059200000, 1345564800000, 1346947200000, 1349452800000, 1351699200000, 1354896000000, 1357660800000, 1360166400000, 1363363200000, 1365264000000, 1367596800000, 1370102400000, 1374595200000, 1376496000000, 1378742400000, 1381161600000, 1383494400000, 1385913600000, 1389196800000, 1391961600000, 1394812800000, 1398700800000, 1399305600000, 1403452800000, 1405526400000, 1407600000000, 1410883200000, 1414108800000, 1415836800000, 1417795200000, 1422028800000, 1424707200000, 1426089600000, 1428336000000, 1431100800000, 1434384000000, 1437408000000, 1440172800000, 1441987200000, 1444233600000, 1446652800000, 1448985600000, 1454169600000, 1455638400000, 1457366400000, 1461254400000, 1462982400000, 1464796800000, 1467820800000, 1470758400000, 1473868800000, 1477785600000, 1475769600000, 1480204800000, 1482796800000, 1484928000000, 1486569600000, 1490198400000, 1492790400000, 1495209600000, 1497456000000, 1501171200000, 1502640000000, 1504281600000, 1507766400000, 1511222400000, 1514332800000, 1515945600000, 1517587200000, 1519142400000, 1520956800000, 1523462400000, 1526486400000, 1529856000000, 1532880000000, 1535472000000, 1537459200000, 1538928000000, 1542153600000, 1545177600000, 1547913600000, 1550332800000, 1553443200000, 1556121600000, 1558540800000, 1560960000000, 1563206400000, 1565280000000, 1568649600000, 1570752000000, 1573228800000, 1576108800000, 1579708800000, 1581955200000, 1583942400000, 1586188800000, 1588867200000, 1592236800000, 1595433600000, 1598457600000, 1600704000000, 1602979200000, 1605225600000, 1607097600000, 1610208000000, 1614182400000, 1616947200000, 1618675200000, 1622390400000, 1624032000000, 1625587200000, 1628438400000, 1631116800000, 1635206400000, 1637107200000, 1638720000000, 1642003200000, 1644854400000, 1648656000000, 1650038400000, 1651593600000, 1654876800000, 1657900800000, 1660924800000, 1664467200000, 1666051200000, 1667750400000, 1671667200000, 1673971200000, 1676390400000, 1678204800000, 1680969600000, 1683129600000, 1685635200000, 1688313600000, 1690819200000, 1693411200000, 1696176000000, 1698768000000, 1701532800000, 1703894400000, 1706025600000]

  //URLs
  var THREAD_URL = /\/(ep|blog|subject|group|character|person|(index\/[0-9]+\/comments))/

  //Selectors
  var THREAD_AVATAR_SELECTOR = "div[id^='post_'] > a.avatar "

  //Regexes
  var USERNAME_REG = /user\/(.+)/
  var AVATAR_UID_REG = /pic\/user\/.+\/\d+\/\d+\/\d+\/(\d+)\.jpg/

  var ceiling = function (arr, target) {
    let totalLen = arr.length
    let lo = 0,
      hi = totalLen - 1
    while (lo < hi) {
      let mid = Math.floor(lo + (hi - lo) / 2)
      // console.log("mid" + mid)
      if (arr[mid] >= target) {
        hi = mid
      }
      else {
        lo = mid + 1
      }
    }
    if (arr[lo] < target) return -1
    return lo
  }

  var ShowUserSiteAge = function () {
    var that = $(this)
    var postJqObj = that.closest("div[id^='post_']")
    var picSpan = that.children("span")
    var userHref = that.attr("href")
    var username = (!!userHref.match(USERNAME_REG) && userHref.match(USERNAME_REG).length > 0) ? userHref.match(USERNAME_REG)[1] : ""
    var isUsernameAllDigit = username.match(/[0-9]+/)
    if (picSpan.length == 0 && !isUsernameAllDigit) return
    var uidFromUsn = parseInt(username)
    var userIdNotNumber = picSpan.attr("style")
    if (!userIdNotNumber && isNaN(uidFromUsn)) return
    var isMatch = !!userIdNotNumber.match(AVATAR_UID_REG) && userIdNotNumber.match(AVATAR_UID_REG).length > 0
    if (!isMatch && isNaN(uidFromUsn)) return
    var userId = isMatch ? Number(userIdNotNumber.match(AVATAR_UID_REG)[1]) : uidFromUsn
    var ceilingIdIdx = ceiling(UID_LIST, userId)
    var tip = ""
    if (ceilingIdIdx == -1) {
      tip = " (最近加入)"
    }
    else {
      var closestDate = UID_DATE[ceilingIdIdx]
      var dateDelta = new Date().valueOf() - closestDate
      var year = Math.floor(dateDelta / 1000 / 86400 / 365)
      var month = Math.floor((dateDelta - year * 1000 * 86400 * 365) / 1000 / 86400 / 30)
      if (year == 0 && month == 0) {
        tip = " (最近加入)"
      }
      else if (year == 0) {
        tip = " (" + month + "月前加入)"
      }
      else if (month == 0) {
        tip = " (" + year + "年前加入)"
      }
      else {
        tip = " (" + year + "年" + month + "月前加入)"
      }
    }
    // main-reply
    if (postJqObj.children("div.inner").children("span.userInfo").length > 0) {
      postJqObj.children("div.inner").children("span.userInfo").children("strong")
        .append("<span class=\"tip_j\" style=\"display: inline;\">" + tip + "</span>")
    }
    else {
      // sub-reply
      postJqObj.children("div.inner").children("strong").append("<span class=\"tip_j\" style=\"display: inline;\">" + tip + "</span>")
    }
  }

  if (PATH.match(THREAD_URL) !== null) {
    $(THREAD_AVATAR_SELECTOR).each(ShowUserSiteAge)
  }

})()