mirror of
https://github.com/LalleSX/4chan-XZ.git
synced 2026-01-30 09:48:12 +01:00
296 lines
7.5 KiB
JavaScript
296 lines
7.5 KiB
JavaScript
import { Conf, d, g } from '../globals/globals'
|
|
import $ from '../platform/$'
|
|
import { dict, HOUR } from '../platform/helpers'
|
|
|
|
export default class DataBoard {
|
|
static initClass() {
|
|
this.keys = [
|
|
'hiddenThreads',
|
|
'hiddenPosts',
|
|
'lastReadPosts',
|
|
'yourPosts',
|
|
'watchedThreads',
|
|
'watcherLastModified',
|
|
'customTitles',
|
|
]
|
|
|
|
this.changes = []
|
|
}
|
|
|
|
constructor(key, sync, dontClean) {
|
|
this.onSync = this.onSync.bind(this)
|
|
this.key = key
|
|
this.initData(Conf[this.key])
|
|
$.sync(this.key, this.onSync)
|
|
if (!dontClean) {
|
|
this.clean()
|
|
}
|
|
if (!sync) {
|
|
return
|
|
}
|
|
// Chrome also fires the onChanged callback on the current tab,
|
|
// so we only start syncing when we're ready.
|
|
var init = () => {
|
|
$.off(d, '4chanXInitFinished', init)
|
|
return (this.sync = sync)
|
|
}
|
|
$.on(d, '4chanXInitFinished', init)
|
|
}
|
|
|
|
initData(data) {
|
|
let boards
|
|
this.data = data
|
|
if (this.data.boards) {
|
|
let lastChecked
|
|
;({ boards, lastChecked } = this.data)
|
|
this.data['4chan.org'] = { boards, lastChecked }
|
|
delete this.data.boards
|
|
delete this.data.lastChecked
|
|
}
|
|
return this.data[g.SITE.ID] || (this.data[g.SITE.ID] = { boards: dict() })
|
|
}
|
|
|
|
save(change, cb) {
|
|
change()
|
|
DataBoard.changes.push(change)
|
|
return $.get(this.key, { boards: dict() }, items => {
|
|
if (!DataBoard.changes.length) {
|
|
return
|
|
}
|
|
const needSync = (items[this.key].version || 0) > (this.data.version || 0)
|
|
if (needSync) {
|
|
this.initData(items[this.key])
|
|
for (change of DataBoard.changes) {
|
|
change()
|
|
}
|
|
}
|
|
DataBoard.changes = []
|
|
this.data.version = (this.data.version || 0) + 1
|
|
return $.set(this.key, this.data, () => {
|
|
if (needSync) {
|
|
this.sync?.()
|
|
}
|
|
return cb?.()
|
|
})
|
|
})
|
|
}
|
|
|
|
forceSync(cb) {
|
|
return $.get(this.key, { boards: dict() }, items => {
|
|
if ((items[this.key].version || 0) > (this.data.version || 0)) {
|
|
this.initData(items[this.key])
|
|
for (var change of DataBoard.changes) {
|
|
change()
|
|
}
|
|
this.sync?.()
|
|
}
|
|
return cb?.()
|
|
})
|
|
}
|
|
|
|
delete({ siteID, boardID, threadID, postID }, cb) {
|
|
if (!siteID) {
|
|
siteID = g.SITE.ID
|
|
}
|
|
if (!this.data[siteID]) {
|
|
return
|
|
}
|
|
return this.save(() => {
|
|
if (postID) {
|
|
if (!this.data[siteID].boards[boardID]?.[threadID]) {
|
|
return
|
|
}
|
|
delete this.data[siteID].boards[boardID][threadID][postID]
|
|
return this.deleteIfEmpty({ siteID, boardID, threadID })
|
|
} else if (threadID) {
|
|
if (!this.data[siteID].boards[boardID]) {
|
|
return
|
|
}
|
|
delete this.data[siteID].boards[boardID][threadID]
|
|
return this.deleteIfEmpty({ siteID, boardID, threadID })
|
|
} else {
|
|
return delete this.data[siteID].boards[boardID]
|
|
}
|
|
}, cb)
|
|
}
|
|
|
|
deleteIfEmpty({ siteID, boardID, threadID }) {
|
|
if (!this.data[siteID]) {
|
|
return
|
|
}
|
|
if (threadID) {
|
|
if (!Object.keys(this.data[siteID].boards[boardID][threadID]).length) {
|
|
delete this.data[siteID].boards[boardID][threadID]
|
|
return this.deleteIfEmpty({ siteID, boardID, threadID: null })
|
|
}
|
|
} else if (!Object.keys(this.data[siteID].boards[boardID]).length) {
|
|
return delete this.data[siteID].boards[boardID]
|
|
}
|
|
}
|
|
|
|
set(data, cb) {
|
|
return this.save(() => {
|
|
return this.setUnsafe(data)
|
|
}, cb)
|
|
}
|
|
|
|
setUnsafe({ siteID, boardID, threadID, postID, val }) {
|
|
if (!siteID) {
|
|
siteID = g.SITE.ID
|
|
}
|
|
if (!this.data[siteID]) {
|
|
this.data[siteID] = { boards: dict() }
|
|
}
|
|
if (postID !== undefined) {
|
|
let base
|
|
return (((base =
|
|
this.data[siteID].boards[boardID] ||
|
|
(this.data[siteID].boards[boardID] = dict()))[threadID] ||
|
|
(base[threadID] = dict()))[postID] = val)
|
|
} else if (threadID !== undefined) {
|
|
return ((this.data[siteID].boards[boardID] ||
|
|
(this.data[siteID].boards[boardID] = dict()))[threadID] = val)
|
|
} else {
|
|
return (this.data[siteID].boards[boardID] = val)
|
|
}
|
|
}
|
|
|
|
extend({ siteID, boardID, threadID, postID, val }, cb) {
|
|
return this.save(() => {
|
|
const oldVal = this.get({
|
|
siteID,
|
|
boardID,
|
|
threadID,
|
|
postID,
|
|
defaultValue: dict(),
|
|
})
|
|
for (var key in val) {
|
|
var subVal = val[key]
|
|
if (typeof subVal === 'undefined') {
|
|
delete oldVal[key]
|
|
} else {
|
|
oldVal[key] = subVal
|
|
}
|
|
}
|
|
return this.setUnsafe({ siteID, boardID, threadID, postID, val: oldVal })
|
|
}, cb)
|
|
}
|
|
|
|
setLastChecked(key = 'lastChecked') {
|
|
return this.save(() => {
|
|
return (this.data[key] = Date.now())
|
|
})
|
|
}
|
|
|
|
get({ siteID, boardID, threadID, postID, defaultValue }) {
|
|
let board, val
|
|
if (!siteID) {
|
|
siteID = g.SITE.ID
|
|
}
|
|
if ((board = this.data[siteID]?.boards[boardID])) {
|
|
let thread
|
|
if (threadID == null) {
|
|
if (postID != null) {
|
|
for (thread = 0; thread < board.length; thread++) {
|
|
var ID = board[thread]
|
|
if (ID == postID) {
|
|
val = thread[postID]
|
|
break
|
|
}
|
|
}
|
|
} else {
|
|
val = board
|
|
}
|
|
} else if ((thread = board[threadID])) {
|
|
val = postID != null ? thread[postID] : thread
|
|
}
|
|
}
|
|
return val || defaultValue
|
|
}
|
|
|
|
clean() {
|
|
let boardID, middle
|
|
const siteID = g.SITE.ID
|
|
for (boardID in this.data[siteID].boards) {
|
|
var val = this.data[siteID].boards[boardID]
|
|
this.deleteIfEmpty({ siteID, boardID, threadID: val })
|
|
}
|
|
const now = Date.now()
|
|
if (
|
|
now - 2 * HOUR >= (middle = this.data[siteID].lastChecked || 0) ||
|
|
middle > now
|
|
) {
|
|
this.data[siteID].lastChecked = now
|
|
for (boardID in this.data[siteID].boards) {
|
|
this.ajaxClean(boardID)
|
|
}
|
|
}
|
|
}
|
|
|
|
ajaxClean(boardID) {
|
|
const that = this
|
|
const siteID = g.SITE.ID
|
|
const threadsList = g.SITE.urls.threadsListJSON?.({ siteID, boardID })
|
|
if (!threadsList) {
|
|
return
|
|
}
|
|
return $.cache(threadsList, function () {
|
|
if (this.status !== 200) {
|
|
return
|
|
}
|
|
const archiveList = g.SITE.urls.archiveListJSON?.({ siteID, boardID })
|
|
if (!archiveList) {
|
|
return that.ajaxCleanParse(boardID, this.response)
|
|
}
|
|
const response1 = this.response
|
|
return $.cache(archiveList, function () {
|
|
if (
|
|
this.status !== 200 &&
|
|
(!!g.SITE.archivedBoardsKnown || this.status !== 404)
|
|
) {
|
|
return
|
|
}
|
|
return that.ajaxCleanParse(boardID, response1, this.response)
|
|
})
|
|
})
|
|
}
|
|
|
|
ajaxCleanParse(boardID, response1, response2) {
|
|
let board, ID
|
|
const siteID = g.SITE.ID
|
|
if (!(board = this.data[siteID].boards[boardID])) {
|
|
return
|
|
}
|
|
const threads = dict()
|
|
if (response1) {
|
|
for (var page of response1) {
|
|
for (var thread of page.threads) {
|
|
ID = thread.no
|
|
if (ID in board) {
|
|
threads[ID] = board[ID]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (response2) {
|
|
for (ID of response2) {
|
|
if (ID in board) {
|
|
threads[ID] = board[ID]
|
|
}
|
|
}
|
|
}
|
|
this.data[siteID].boards[boardID] = threads
|
|
this.deleteIfEmpty({ siteID, boardID, threadID: null })
|
|
return $.set(this.key, this.data)
|
|
}
|
|
|
|
onSync(data) {
|
|
if ((data.version || 0) <= (this.data.version || 0)) {
|
|
return
|
|
}
|
|
this.initData(data)
|
|
return this.sync?.()
|
|
}
|
|
}
|
|
DataBoard.initClass()
|