mirror of
https://git.sr.ht/~cadence/bibliogram
synced 2025-06-27 23:58:22 +00:00

The previous HTML method is gone due to a page restructure. It was able to consistently bypass Instagram's blocking. The IWeb method has a few hundred uses per X time for selfhosters, and a couple dozen uses per X time for servers. This will likely change in the future. There is no known way to bypass Instagram's IWeb blocking. Feel free to look for a way. Further timeline pages are still blocked. The "next page" button defaults to not automatically loading when scrolled, since it will basically never work anyway. Users running personal instances may be able to get a couple of uses out of it.
108 lines
2.5 KiB
JavaScript
108 lines
2.5 KiB
JavaScript
import {ElemJS, q} from "./elemjs/elemjs.js"
|
|
import {quota} from "./quota.js"
|
|
|
|
class FreezeWidth extends ElemJS {
|
|
freeze(text) {
|
|
this.element.style.width = window.getComputedStyle(this.element).width
|
|
this.oldText = this.element.textContent
|
|
this.text(text)
|
|
}
|
|
|
|
unfreeze() {
|
|
this.element.style.width = ""
|
|
this.text(this.oldText)
|
|
}
|
|
}
|
|
|
|
const intersectionThreshold = 0
|
|
|
|
class NextPageController {
|
|
constructor() {
|
|
this.instance = null
|
|
this.activatedCallbacks = []
|
|
}
|
|
|
|
add() {
|
|
const nextPage = q("#next-page")
|
|
if (nextPage) {
|
|
this.instance = new NextPage(nextPage, this)
|
|
} else {
|
|
this.instance = null
|
|
}
|
|
this.activatedCallbacks.forEach(c => c())
|
|
}
|
|
|
|
addActivatedCallback(callback) {
|
|
this.activatedCallbacks.push(callback)
|
|
}
|
|
|
|
async activate() {
|
|
if (this.instance) await this.instance.activate()
|
|
}
|
|
}
|
|
|
|
class NextPage extends FreezeWidth {
|
|
constructor(container, controller) {
|
|
super(container)
|
|
this.controller = controller
|
|
this.clicked = false
|
|
this.nextPageNumber = +this.element.getAttribute("data-page")
|
|
this.auto = this.element.getAttribute("data-auto")
|
|
this.attribute("href", "javascript:void(0)")
|
|
this.event("click", event => this.onClick(event))
|
|
|
|
this.observer = new IntersectionObserver(entries => this.onIntersect(entries), {rootMargin: "0px", threshold: intersectionThreshold})
|
|
if (this.auto !== "off") {
|
|
this.observer.observe(this.element)
|
|
}
|
|
}
|
|
|
|
onClick(event) {
|
|
if (event) event.preventDefault()
|
|
if (this.fetching) return
|
|
this.class("clicked")
|
|
this.fetch()
|
|
}
|
|
|
|
/**
|
|
* @param {IntersectionObserverEntry[]} entries
|
|
*/
|
|
onIntersect(entries) {
|
|
if (entries.some(entry => entry.isIntersecting && entry.intersectionRatio >= intersectionThreshold)) {
|
|
if (this.fetching) return
|
|
this.class("disabled")
|
|
this.class("clicked")
|
|
this.fetch()
|
|
}
|
|
}
|
|
|
|
fetch() {
|
|
if (this.fetching) return
|
|
this.fetching = true
|
|
this.freeze(this.element.getAttribute("data-loading-text"))
|
|
const type = this.element.getAttribute("data-type")
|
|
|
|
return fetch(`/fragment/user/${this.element.getAttribute("data-username")}/${this.nextPageNumber}?type=${type}`).then(res => {
|
|
if (res.status === 200) {
|
|
quota.change(-1)
|
|
}
|
|
return res.text()
|
|
}).then(text => {
|
|
q("#next-page-container").remove()
|
|
this.observer.disconnect()
|
|
q("#timeline").insertAdjacentHTML("beforeend", text)
|
|
this.controller.add()
|
|
})
|
|
}
|
|
|
|
activate() {
|
|
if (this.fetching) return
|
|
this.class("disabled")
|
|
return this.fetch()
|
|
}
|
|
}
|
|
|
|
const controller = new NextPageController()
|
|
controller.add()
|
|
export {controller}
|