mirror of
https://github.com/LalleSX/4chan-XZ.git
synced 2026-01-30 09:48:12 +01:00
More types!
This commit is contained in:
parent
12483e97c5
commit
fbc329add3
@ -1,16 +1,20 @@
|
|||||||
import { Conf, g } from '../globals/globals'
|
import { Conf, g } from '../globals/globals'
|
||||||
import $ from '../platform/$'
|
import $ from '../platform/$'
|
||||||
|
import type Thread from '../classes/Thread'
|
||||||
/*
|
import type Post from '../classes/Post'
|
||||||
* decaffeinate suggestions:
|
interface Get {
|
||||||
* DS101: Remove unnecessary use of Array.from
|
url(type: any, IDs: { siteID: string }, ...args: any[]): string | undefined
|
||||||
* DS102: Remove unnecessary code created because of implicit returns
|
threadExcerpt(thread: Thread): string
|
||||||
* DS207: Consider shorter variations of null checks
|
threadFromRoot(root: HTMLElement): Thread | null
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
threadFromNode(node: HTMLElement): Thread | null
|
||||||
*/
|
postFromRoot(root: HTMLElement): Post | null
|
||||||
var Get = {
|
postFromNode(root: HTMLElement): Post | null
|
||||||
|
allQuotelinksLinkingTo(post: Post): HTMLAnchorElement[]
|
||||||
|
postDataFromLink(link: HTMLAnchorElement): { boardID: string; postID: number }
|
||||||
|
}
|
||||||
|
var Get: Get = {
|
||||||
url(type, IDs, ...args) {
|
url(type, IDs, ...args) {
|
||||||
let f, site
|
let f: ((IDs: { siteID: string }, ...args: any[]) => string) | undefined, site: typeof g.sites[0]
|
||||||
if ((site = g.sites[IDs.siteID]) && (f = $.getOwn(site.urls, type))) {
|
if ((site = g.sites[IDs.siteID]) && (f = $.getOwn(site.urls, type))) {
|
||||||
return f(IDs, ...Array.from(args))
|
return f(IDs, ...Array.from(args))
|
||||||
} else {
|
} else {
|
||||||
@ -43,7 +47,7 @@ var Get = {
|
|||||||
},
|
},
|
||||||
threadFromNode(node) {
|
threadFromNode(node) {
|
||||||
return Get.threadFromRoot(
|
return Get.threadFromRoot(
|
||||||
$.x(`ancestor-or-self::${g.SITE.xpath.thread}`, node),
|
$.x(`ancestor-or-self::${g.SITE.xpath.threadContainer}[1]`, node)[0],
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
postFromRoot(root) {
|
postFromRoot(root) {
|
||||||
@ -60,20 +64,23 @@ var Get = {
|
|||||||
},
|
},
|
||||||
postFromNode(root) {
|
postFromNode(root) {
|
||||||
return Get.postFromRoot(
|
return Get.postFromRoot(
|
||||||
$.x(`ancestor-or-self::${g.SITE.xpath.postContainer}[1]`, root),
|
$.x(`ancestor-or-self::${g.SITE.xpath.postContainer}`, root)[0],
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
postDataFromLink(link) {
|
postDataFromLink(link: any) {
|
||||||
let boardID, postID, threadID
|
let boardID: any, postID: any, threadID: any
|
||||||
if (link.dataset.postID) {
|
if (link.dataset?.postID) {
|
||||||
// resurrected quote
|
// resurrected quote
|
||||||
;({ boardID, threadID, postID } = link.dataset)
|
({ boardID, threadID, postID } = link.dataset)
|
||||||
if (!threadID) {
|
if (!threadID) {
|
||||||
threadID = 0
|
threadID = '0'
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const match = link.href.match(g.SITE.regexp.quotelink)
|
const match = link.href.match(g?.SITE?.regexp?.quotelink)
|
||||||
;[boardID, threadID, postID] = Array.from(match.slice(1))
|
if (!match) {
|
||||||
|
throw new Error('Invalid link')
|
||||||
|
}
|
||||||
|
[boardID, threadID, postID] = match.slice(1)
|
||||||
if (!postID) {
|
if (!postID) {
|
||||||
postID = threadID
|
postID = threadID
|
||||||
}
|
}
|
||||||
@ -83,7 +90,7 @@ var Get = {
|
|||||||
threadID: +threadID,
|
threadID: +threadID,
|
||||||
postID: +postID,
|
postID: +postID,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
allQuotelinksLinkingTo(post) {
|
allQuotelinksLinkingTo(post) {
|
||||||
// Get quotelinks & backlinks linking to the given post.
|
// Get quotelinks & backlinks linking to the given post.
|
||||||
const quotelinks = []
|
const quotelinks = []
|
||||||
@ -1,37 +0,0 @@
|
|||||||
import BoardConfig from '../General/BoardConfig'
|
|
||||||
import { d, g } from '../globals/globals'
|
|
||||||
import SimpleDict from './SimpleDict'
|
|
||||||
|
|
||||||
export default class Board {
|
|
||||||
toString() {
|
|
||||||
return this.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(ID) {
|
|
||||||
this.ID = ID
|
|
||||||
this.boardID = this.ID
|
|
||||||
this.siteID = g.SITE.ID
|
|
||||||
this.threads = new SimpleDict()
|
|
||||||
this.posts = new SimpleDict()
|
|
||||||
this.config = BoardConfig.boards?.[this.ID] || {}
|
|
||||||
|
|
||||||
g.boards[this.ID] = this
|
|
||||||
}
|
|
||||||
|
|
||||||
cooldowns() {
|
|
||||||
const c2 = (this.config || {}).cooldowns || {}
|
|
||||||
const c = {
|
|
||||||
thread: c2.threads || 0,
|
|
||||||
reply: c2.replies || 0,
|
|
||||||
image: c2.images || 0,
|
|
||||||
thread_global: 300, // inter-board thread cooldown
|
|
||||||
}
|
|
||||||
// Pass users have reduced cooldowns.
|
|
||||||
if (d.cookie.indexOf('pass_enabled=1') >= 0) {
|
|
||||||
for (var key of ['reply', 'image']) {
|
|
||||||
c[key] = Math.ceil(c[key] / 2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
46
src/classes/Board.ts
Normal file
46
src/classes/Board.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import BoardConfig from '../General/BoardConfig';
|
||||||
|
import { d, g } from '../globals/globals';
|
||||||
|
import Post from './Post';
|
||||||
|
import Thread from './Thread';
|
||||||
|
import SimpleDict from './SimpleDict';
|
||||||
|
|
||||||
|
export default class Board {
|
||||||
|
ID: string;
|
||||||
|
boardID: string;
|
||||||
|
siteID: string;
|
||||||
|
threads: SimpleDict<Thread>;
|
||||||
|
posts: SimpleDict<Post>;
|
||||||
|
config: any;
|
||||||
|
|
||||||
|
constructor(ID: string) {
|
||||||
|
this.ID = ID;
|
||||||
|
this.boardID = this.ID;
|
||||||
|
this.siteID = g.SITE.ID;
|
||||||
|
this.threads = new SimpleDict();
|
||||||
|
this.posts = new SimpleDict();
|
||||||
|
this.config = BoardConfig.domain(this.ID)
|
||||||
|
|
||||||
|
g.boards[this.ID] = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return this.ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
cooldowns() {
|
||||||
|
const c2 = (this.config || {}).cooldowns || {};
|
||||||
|
const c = {
|
||||||
|
thread: c2.threads || 0,
|
||||||
|
reply: c2.replies || 0,
|
||||||
|
image: c2.images || 0,
|
||||||
|
thread_global: 300, // inter-board thread cooldown
|
||||||
|
};
|
||||||
|
// Pass users have reduced cooldowns.
|
||||||
|
if (d.cookie.indexOf('pass_enabled=1') >= 0) {
|
||||||
|
for (let key of ['reply', 'image']) {
|
||||||
|
c[key] = Math.ceil(c[key] / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,59 +0,0 @@
|
|||||||
import Main from '../main/Main'
|
|
||||||
|
|
||||||
export default class Callbacks {
|
|
||||||
static initClass() {
|
|
||||||
this.Post = new Callbacks('Post')
|
|
||||||
this.Thread = new Callbacks('Thread')
|
|
||||||
this.CatalogThread = new Callbacks('Catalog Thread')
|
|
||||||
this.CatalogThreadNative = new Callbacks('Catalog Thread')
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(type) {
|
|
||||||
this.type = type
|
|
||||||
this.keys = []
|
|
||||||
}
|
|
||||||
|
|
||||||
push({ name, cb }) {
|
|
||||||
if (!this[name]) {
|
|
||||||
this.keys.push(name)
|
|
||||||
}
|
|
||||||
return (this[name] = cb)
|
|
||||||
}
|
|
||||||
|
|
||||||
execute(node, keys = this.keys, force = false) {
|
|
||||||
let errors
|
|
||||||
if (node.callbacksExecuted && !force) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
node.callbacksExecuted = true
|
|
||||||
for (var name of keys) {
|
|
||||||
try {
|
|
||||||
this[name]?.call(node)
|
|
||||||
} catch (err) {
|
|
||||||
if (!errors) {
|
|
||||||
errors = []
|
|
||||||
}
|
|
||||||
errors.push({
|
|
||||||
message: [
|
|
||||||
'"',
|
|
||||||
name,
|
|
||||||
'" crashed on node ',
|
|
||||||
this.type,
|
|
||||||
' No.',
|
|
||||||
node.ID,
|
|
||||||
' (',
|
|
||||||
node.board,
|
|
||||||
').',
|
|
||||||
].join(''),
|
|
||||||
error: err,
|
|
||||||
html: node.nodes?.root?.outerHTML,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errors) {
|
|
||||||
return Main.handleErrors(errors)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Callbacks.initClass()
|
|
||||||
68
src/classes/Callbacks.ts
Normal file
68
src/classes/Callbacks.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import Main from '../main/Main';
|
||||||
|
|
||||||
|
export default class Callbacks {
|
||||||
|
private type: string;
|
||||||
|
private keys: string[];
|
||||||
|
|
||||||
|
static Post: Callbacks;
|
||||||
|
static Thread: Callbacks;
|
||||||
|
static CatalogThread: Callbacks;
|
||||||
|
static CatalogThreadNative: Callbacks;
|
||||||
|
|
||||||
|
static initClass() {
|
||||||
|
this.Post = new Callbacks('Post');
|
||||||
|
this.Thread = new Callbacks('Thread');
|
||||||
|
this.CatalogThread = new Callbacks('Catalog Thread');
|
||||||
|
this.CatalogThreadNative = new Callbacks('Catalog Thread');
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(type: string) {
|
||||||
|
this.type = type;
|
||||||
|
this.keys = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
push({ name, cb }: { name: string; cb: () => void }) {
|
||||||
|
if (!this[name]) {
|
||||||
|
this.keys.push(name);
|
||||||
|
}
|
||||||
|
return (this[name] = cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
execute(node: any, keys = this.keys, force = false) {
|
||||||
|
let errors: any[];
|
||||||
|
if (node.callbacksExecuted && !force) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
node.callbacksExecuted = true;
|
||||||
|
for (let name of keys) {
|
||||||
|
try {
|
||||||
|
this[name]?.call(node);
|
||||||
|
} catch (err: any) {
|
||||||
|
if (!errors) {
|
||||||
|
errors = [];
|
||||||
|
}
|
||||||
|
errors.push({
|
||||||
|
message: [
|
||||||
|
'"',
|
||||||
|
name,
|
||||||
|
'" crashed on node ',
|
||||||
|
this.type,
|
||||||
|
' No.',
|
||||||
|
node.ID,
|
||||||
|
' (',
|
||||||
|
node.board,
|
||||||
|
').',
|
||||||
|
].join(''),
|
||||||
|
error: err,
|
||||||
|
html: node.nodes?.root?.outerHTML,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors) {
|
||||||
|
return Main.handleErrors(errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Callbacks.initClass();
|
||||||
@ -1,6 +1,7 @@
|
|||||||
import SimpleDict from './SimpleDict'
|
import SimpleDict from './SimpleDict'
|
||||||
import $ from '../platform/$'
|
import $ from '../platform/$'
|
||||||
import { g } from '../globals/globals'
|
import { g } from '../globals/globals'
|
||||||
|
import Post from './Post'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* decaffeinate suggestions:
|
* decaffeinate suggestions:
|
||||||
@ -8,15 +9,35 @@ import { g } from '../globals/globals'
|
|||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
||||||
*/
|
*/
|
||||||
export default class Thread {
|
export default class Thread {
|
||||||
|
board: string
|
||||||
|
ID: number
|
||||||
|
threadID: number
|
||||||
|
boardID: string
|
||||||
|
siteID: string
|
||||||
|
fullID: string
|
||||||
|
posts: SimpleDict<Post>
|
||||||
|
isDead: boolean
|
||||||
|
isHidden: boolean
|
||||||
|
isSticky: boolean
|
||||||
|
isClosed: boolean
|
||||||
|
isArchived: boolean
|
||||||
|
postLimit: boolean
|
||||||
|
fileLimit: boolean
|
||||||
|
lastPost: number
|
||||||
|
ipCount: undefined
|
||||||
|
json: null | any
|
||||||
|
OP: null | Post
|
||||||
|
catalogView: null | any
|
||||||
|
nodes: { root: null | HTMLElement }
|
||||||
toString() {
|
toString() {
|
||||||
return this.ID
|
return this.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(ID, board) {
|
constructor(ID: string, board: string) {
|
||||||
this.board = board
|
this.board = board
|
||||||
this.ID = +ID
|
this.ID = +ID
|
||||||
this.threadID = this.ID
|
this.threadID = this.ID
|
||||||
this.boardID = this.board.ID
|
this.boardID = g.BOARD.ID
|
||||||
this.siteID = g.SITE.ID
|
this.siteID = g.SITE.ID
|
||||||
this.fullID = `${this.board}.${this.ID}`
|
this.fullID = `${this.board}.${this.ID}`
|
||||||
this.posts = new SimpleDict()
|
this.posts = new SimpleDict()
|
||||||
@ -40,8 +61,8 @@ export default class Thread {
|
|||||||
g.threads.push(this.fullID, this)
|
g.threads.push(this.fullID, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
setPage(pageNum) {
|
setPage(pageNum: number): void {
|
||||||
let icon
|
let icon: HTMLElement | null
|
||||||
const { info, reply } = this.OP.nodes
|
const { info, reply } = this.OP.nodes
|
||||||
if (!(icon = $('.page-num', info))) {
|
if (!(icon = $('.page-num', info))) {
|
||||||
icon = $.el('span', { className: 'page-num' })
|
icon = $.el('span', { className: 'page-num' })
|
||||||
@ -54,7 +75,7 @@ export default class Thread {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setCount(type, count, reachedLimit) {
|
setCount(type: string, count: number, reachedLimit: boolean): void {
|
||||||
if (!this.catalogView) {
|
if (!this.catalogView) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -63,7 +84,7 @@ export default class Thread {
|
|||||||
return (reachedLimit ? $.addClass : $.rmClass)(el, 'warning')
|
return (reachedLimit ? $.addClass : $.rmClass)(el, 'warning')
|
||||||
}
|
}
|
||||||
|
|
||||||
setStatus(type, status) {
|
setStatus(type: string, status: boolean): void {
|
||||||
const name = `is${type}`
|
const name = `is${type}`
|
||||||
if (this[name] === status) {
|
if (this[name] === status) {
|
||||||
return
|
return
|
||||||
@ -77,7 +98,7 @@ export default class Thread {
|
|||||||
return this.setIcon('Archived', this.isArchived)
|
return this.setIcon('Archived', this.isArchived)
|
||||||
}
|
}
|
||||||
|
|
||||||
setIcon(type, status) {
|
setIcon(type: string, status: boolean): void {
|
||||||
const typeLC = type.toLowerCase()
|
const typeLC = type.toLowerCase()
|
||||||
let icon = $(`.${typeLC}Icon`, this.OP.nodes.info)
|
let icon = $(`.${typeLC}Icon`, this.OP.nodes.info)
|
||||||
if (!!icon === status) {
|
if (!!icon === status) {
|
||||||
@ -117,11 +138,11 @@ export default class Thread {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
kill() {
|
kill(): boolean {
|
||||||
return (this.isDead = true)
|
return (this.isDead = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
collect() {
|
collect(): boolean {
|
||||||
let n = 0
|
let n = 0
|
||||||
this.posts.forEach(function (post) {
|
this.posts.forEach(function (post) {
|
||||||
if (post.clones.length) {
|
if (post.clones.length) {
|
||||||
@ -132,7 +153,7 @@ export default class Thread {
|
|||||||
})
|
})
|
||||||
if (!n) {
|
if (!n) {
|
||||||
g.threads.rm(this.fullID)
|
g.threads.rm(this.fullID)
|
||||||
return this.board.threads.rm(this)
|
return this.board.threads.rm(this.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user