// UserScript
// @name StaleBread
// @namespace there's still time.
// @version 1.20
// @downloadURL https://rentry.co/StaleBread/raw#.user.js
// @description Displays postion of a thread on page 10. This script doesn't seem to work with greasemonkey for some reason.
// @author (me)
// @include http://boards.4chan.org//thread/
// @include https://boards.4chan.org//thread/
// @include http://sys.4chan.org//thread/
// @include https://sys.4chan.org//thread/
// @include http://www.4chan.org//thread/
// @include https://www.4chan.org//thread/
// @include http://boards.4channel.org//thread/
// @include https://boards.4channel.org//thread/
// @include http://sys.4channel.org//thread/
// @include https://sys.4channel.org//thread/
// @include http://www.4channel.org//thread/
// @include https://www.4channel.org//thread/
// @grant none
// @icon data:image/gif;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAIALAAAAAAQABAAAAIvlI+pq+D9DAgUoFkPDlbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw==
// /UserScript

/* Patch Notes


StaleBread


1.20

  • I have seen the light. I finally understand. Page 11 only appears on boards with stickies
    since they don't count towards the max posts per page, so how much room a page 11 has is
    determined by the board's number of stickies.
    But unfortunately the script still seems to have trouble keeping up on very fast boards like
    /biz/, and I don't really know what I can do about that.
  • improved archive detection.

1.18

  • position counter didn't disappear once a thread left page 10. really gonna leave this alone
    until I understand page 11 now.

1.17

  • borked the entire script because of a stray (. I should take a break.

1.16

  • just realized I can query for the max number of threads per page
  • the more I look at page 11, the more confused I get... reverted previous change where the
    pagecount from the api overwrote the native pagecount because it doesn't look like this
    data is actually accurate?
    I'll stop pushing updates for a while until I figure out what the fuck is happening.

1.15

  • forgot to comment a console.log

1.14

  • if there is a page 11, the script will now display the number of threads on page 11 next to
    the normal position counter.
  • improved page update speed when a thread on page 10+ since I'm already querying the api
    anyways. might as well use the data I get. If the thread is not on page 10+, page updates
    still rely on the native updates.

1.13

  • minor adjustment to the still terrible archived detection

1.12

  • [fcx false] fixed issue where the position counter would disappear when new posts were added

1.11

  • a fucking typo

1.1

  • removed 4chanX dependency

1.0

  • functional

*/

/*

*/

"use strict";
//-----------------------------------------------Settings-----------------------------------------------//
const interval = 60 // [number] How much time between updating page position in seconds.  
                    //          Don't set ittoo low.
                    //          You can manually update the position by clicking the
                    //          page counter.
//------------------------------------------------------------------------------------------------------//

if (document.getElementsByClassName("fourchan-x")[0]){
  var fcx = true
} else {
  var fcx = false
}
//console.log("4cx " + fcx)

var updateInterval,pos,pc,perPage,b
var ded = 0
var pageTen = false
const postNo = String(window.location).match(/thread\/(\d+)/)[1]
const board = String(window.location).match(/([^\/]+)\/thread/)[1]

async function getBoard(){
  b = await (await fetch("https://a.4cdn.org/boards.json",{method: "GET",cache: "default"})).json()
  for (var i=0;i<b.boards.length;i++){
    if (b.boards[i].board == board) {
      perPage = b.boards[i].per_page
    }
  }
} 
getBoard()


window.addEventListener("load", function() {
  //console.log("loaded")
  var poscntTemp0 = document.createElement("span")
  poscntTemp0.className = "poscnt"
  poscntTemp0.style = "color:red;font-size:10px;"
  var poscntTemp1 = document.createElement("span")
  poscntTemp1.className = "poscnt"
  poscntTemp1.style = "color:red;font-size:10px;"
  var poscntTemp = [poscntTemp0,poscntTemp1]

  if (fcx){
    var pageCount = document.getElementById("page-count")
    insertAfter(pageCount,poscntTemp[0])
  }
  else {
    var pageCount = document.getElementsByClassName("ts-page")[0]
    var pcntEl = document.getElementsByClassName("thread-stats")
    for (var i=0;i<pcntEl.length;i++) {
      poscntTemp[i].style.float = "right"
      poscntTemp[i].style.marginRight = "5px"
      poscntTemp[i].style.marginTop = "3px"
      //poscntTemp[i].innerHTML = "AAA"
      pcntEl[i].parentNode.insertBefore(poscntTemp[i],pcntEl[i]);
    }
  }
  var poscnt = document.getElementsByClassName("poscnt")

  let observer = new MutationObserver(mutationRecords => {
    //console.log("page")
    updatePos()
  })
  observer.observe(pageCount, { 
    characterData: true, 
    attributes: false, 
    childList: true, 
    subtree: true 
  })

  async function updatePos() {
    //console.log("update pos")
    var sticky = 0
    if (fcx){
      var pageCount = document.getElementById("page-count")
    }
    else {
      var pageCount = document.getElementsByClassName("ts-page")[0]
    }
    var pc = Number(pageCount.textContent)
    //console.log(pc)
    if (pc >= 10) {
      if (!pageTen) {
        //console.log("Page 10")
        pageTen = true
        updateInterval = setInterval(updatePos, interval*1000)
      }
      //var t = await (await fetch("https://a.4cdn.org/" + board + "/threads.json")).json()
      var t = await (await fetch("https://a.4cdn.org/" + board + "/catalog.json",{method: "GET",cache: "default"})).json()
      for (var i=0;i<t.length;i++){
        t[i].threads.findIndex(function(item,p){
          if (item.no == postNo){
            //console.log(i + " " + p)
            return pc = i+1, pos = p+1;
          }
        })
      }
      t[0].threads.findIndex(function(item,p){
        if (item.sticky == 1){
          sticky++
        }
      })
      //console.log(sticky)

      // this overwrites the native page counter with the one obtained from the API
      // it's slow for some reason
      if (!fcx){
        if  (Number(pageCount.textContent) != pc) {
          var dPc = document.getElementsByClassName("ts-page")
          for (var i=0;i<dPc.length;i++){
            dPc[i].textContent = pc
          }
        }
      }
      var noThreads = perPage //t[pc-1].threads.length
      var ptenplus = ""
      if (sticky > 0 && pc < 11) {
        ptenplus = "<small>+" + sticky + "</small>"
      }
      if (pc > 10) {
        noThreads = sticky
      }
      var posStr = pos + "/" + noThreads + ptenplus 
      for (var i=0;i<poscnt.length;i++){
        poscnt[i].innerHTML = " " + posStr
      }
    }
    else if ((pc < 10 && pageTen)) { //|| (pageCount.textContent == "Dead")) {
      //console.log("Left Page 10")
      for (var i=0;i<poscnt.length;i++){
        poscnt[i].innerHTML = ""
      }
      pageTen = false
      clearInterval(updateInterval)
    }
    /*if (pc == 0 || (document.getElementsByClassName("tu-error")[0].textContent == "This thread is archived")){
      ded++
      //console.log("thread not found " + ded)
      if (ded >= 5) {
        for (var i=0;i<poscnt.length;i++){
          poscnt[i].innerHTML = ""
        }
        clearInterval(updateInterval)
      }
    }
    else {
      ded = 0
    }*/
    var archiveStatus = ""
    if (document.getElementsByClassName("tu-error")[0]) {
      archiveStatus = document.getElementsByClassName("tu-error")[0].textContent
    }
    else if (document.getElementById("update-status")) {
      archiveStatus = document.getElementById("update-status").textContent
    }
    if ((archiveStatus == "Archived") || (archiveStatus == "This thread is archived")){
      console.log("archived")
      for (var i=0;i<poscnt.length;i++){
        poscnt[i].innerHTML = ""
      }
      pageTen = false
      clearInterval(updateInterval)
    }
    //console.log("cycle")
  }

  if (!fcx) {
    var dPc = document.getElementsByClassName("ts-page")
    for (var i=0;i<dPc.length;i++) {
      dPc[i].onclick = function() {
        updatePos()
      }
    }
  }
  updatePos()
})

// Utility Functions
function insertAfter(referenceNode, newNode) {
  referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
/*

*/

Edit Report
Pub: 31 May 2021 13:27 UTC
Edit: 04 Jun 2021 18:22 UTC
Views: 82