ResetEra: Display Posts Per Day

Displays posts per day average

  1. // ==UserScript==
  2. // @name ResetEra: Display Posts Per Day
  3. // @description Displays posts per day average
  4. // @version 4
  5. // @grant none
  6. // @match *://*.resetera.com/members/*
  7. // @match *://*.resetera.com/threads/*
  8. // @match *://*.neogaf.com/members/*
  9. // @match *://*.neogaf.com/threads/*
  10. // @grant GM.log
  11. // @namespace hateradio)))
  12. // ==/UserScript==
  13.  
  14. (() => {
  15. 'use strict'
  16.  
  17. class Posts {
  18.  
  19. constructor(selector) {
  20. this.selector = selector
  21. console.log(this.selector)
  22. let { joined, messages } = this.rawData
  23. console.log('Found date/messages:', joined, messages)
  24.  
  25. this.messages = Posts.toInt(messages)
  26. this.joined = Posts.toDate(joined)
  27.  
  28. console.log('Detected date:', this.joined.toString())
  29. }
  30.  
  31. diff(initial, latest) {
  32. return Math.floor((latest - initial) / Posts.MILLS_PER_DAY)
  33. }
  34.  
  35. template(title, body) {
  36. return `<dl class="pairs pairs--rows pairs--rows--centered re_headerStats--joined"><dt>${title}:</dt><dd>${body}</dd></dl>`
  37. }
  38.  
  39. append() {
  40. const temp = this.template('Posts Per Day', this.average.toFixed(2))
  41. this.parents.forEach(p => p.insertAdjacentHTML('beforeend', temp))
  42. }
  43.  
  44. get parents() {
  45. return [
  46. document.querySelector(this.selector),
  47. document.querySelector('.memberHeader-stats dl').parentElement
  48. ]
  49. }
  50.  
  51. get rawData() {
  52. console.log(this.selector, this.parents)
  53. return Array.from(this.parents[0].querySelectorAll('dl'))
  54. .reduce((o, d) => {
  55. const prop = d.querySelector('dt').textContent.trim().toLowerCase()
  56. const content = d.querySelector('time') ? d.querySelector('time').dateTime : d.querySelector('dd').textContent.trim()
  57. o[prop] = content
  58. return o
  59. }, {})
  60. }
  61.  
  62. get average() {
  63. const days = this.diff(this.joined, new Date())
  64. return this.messages / days
  65. }
  66.  
  67. static toInt(str) {
  68. return +(str.replace(/\D/g, ''))
  69. }
  70.  
  71. // Fixes date parsing for Safari
  72. static toDate(str) {
  73. str = str.split('')
  74. str.splice(-2, 0, ':')
  75. return new Date(str.join(''))
  76. }
  77.  
  78. static main() {
  79. const path = document.location.pathname.substr(1).split('/')[0]
  80.  
  81. if (path === 'threads') {
  82. ModalPosts.listener()
  83. } else {
  84. const p = new Posts('div.re_headerStats')
  85. p.append()
  86. }
  87. }
  88.  
  89. }
  90.  
  91. class ModalPosts extends Posts {
  92.  
  93. constructor(id) {
  94. super(`.memberTooltip-stats dd a[href*="user_id=${id}"]`);
  95. }
  96.  
  97. template(title, body) {
  98. return `<dl class="pairs pairs--rows pairs--rows--centered re_mainStat"><dt>${title}</dt><dd>${body}</dd></dl>`
  99. }
  100.  
  101. get parents() {
  102. return [document.querySelector(this.selector).closest('div')]
  103. }
  104.  
  105. static listener() {
  106. document.body.addEventListener('click', e => {
  107. let { target = null } = e
  108. if (e && target && target.tagName === 'IMG') {
  109. target = target.parentElement
  110. }
  111. //console.log('target', target)
  112. const id = e && target && target.href && parseInt(target.href.split('.').pop(), 10)
  113. console.log('id', id)
  114. if (id && !ModalPosts.ID[id]) {
  115. window.setTimeout(() => {
  116. const p = new ModalPosts(id);
  117. p.append()
  118. }, 2000)
  119. ModalPosts.ID[id] = true
  120. }
  121. }, false)
  122. }
  123. }
  124.  
  125. // static inline constants aren't allowed in all browsers yet :(
  126.  
  127. Posts.MILLS_PER_DAY = 24 * 60 * 60 * 1000
  128.  
  129. ModalPosts.ID = {}
  130.  
  131. // window.setInterval(Posts.main, 5000)
  132. Posts.main()
  133.  
  134.  
  135. })()