-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comment Tracker: Fix edited comment appears as read instead of unread #1773
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"editor.rulers": [100] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,8 +5,28 @@ import { Shared } from '../class/Shared'; | |
import { Comment } from '../models/Comment'; | ||
import { common } from './Common'; | ||
|
||
const getUser = common.getUser.bind(common), | ||
getValue = common.getValue.bind(common); | ||
interface Comment2 { | ||
actions?: HTMLElement; | ||
author?: string; | ||
bump?: string[]; | ||
code?: string; | ||
comment?: HTMLElement; | ||
displayState?: HTMLElement; | ||
id?: string; | ||
index?: number; | ||
isOp?: boolean; | ||
length?: number; | ||
outerWrap?: HTMLElement; | ||
parent?: HTMLElement; | ||
permalink?: HTMLElement; | ||
summary?: HTMLElement; | ||
text?: string; | ||
timestamp?: number; | ||
type?: string; | ||
words?: string[]; | ||
} | ||
|
||
const getValue = common.getValue.bind(common); | ||
class Comments extends Module { | ||
constructor() { | ||
super(); | ||
|
@@ -19,17 +39,23 @@ class Comments extends Module { | |
}; | ||
} | ||
|
||
async comments_load(context, main, source, endless, mainEndless) { | ||
comments_load = async ( | ||
context: HTMLElement, | ||
main: boolean, | ||
_source: never, | ||
endless: number, | ||
mainEndless: unknown | ||
) => { | ||
const commentsV2 = Comment.parseAll(context); | ||
Scope.addData('current', 'commentsV2', commentsV2, endless); | ||
for (const feature of Shared.esgst.commentV2Features) { | ||
await feature(commentsV2, main); | ||
} | ||
let count, comments, i, n; | ||
comments = await this.comments_get(context, document, main, endless); | ||
let count = 0; | ||
const comments = await this.comments_get(context, document, main, endless); | ||
if (!comments.length) return; | ||
Scope.addData('current', 'comments', comments, endless); | ||
for (i = 0, n = comments.length; i < n; ++i) { | ||
for (let i = 0, n = comments.length; i < n; ++i) { | ||
comments[i].index = i; | ||
} | ||
for (const feature of Shared.esgst.commentFeatures) { | ||
|
@@ -64,9 +90,14 @@ class Comments extends Module { | |
const breadcrumbs = context.querySelectorAll( | ||
'.page__heading:not([data-esgst]) .page__heading__breadcrumbs' | ||
); | ||
count = breadcrumbs[1] || breadcrumbs[0]; | ||
if (count) { | ||
count = parseInt(count.firstElementChild.textContent.replace(/,/g, '').match(/\d+/)[0]); | ||
const countElement = breadcrumbs[1] || breadcrumbs[0]; | ||
if (countElement && countElement.firstElementChild) { | ||
const reMatches = countElement.firstElementChild.textContent | ||
.replace(/,/g, '') | ||
.match(/\d+/); | ||
if (reMatches) { | ||
count = parseInt(reMatches[0]); | ||
} | ||
} else { | ||
count = 0; | ||
} | ||
|
@@ -97,22 +128,30 @@ class Comments extends Module { | |
if (Settings.get('ged')) { | ||
this.esgst.ged_addIcons(comments); | ||
} | ||
} | ||
}; | ||
|
||
async comments_get(context, mainContext, main, endless) { | ||
let comment, comments, i, matches, sourceLink; | ||
comments = []; | ||
matches = context.querySelectorAll( | ||
comments_get = async ( | ||
context: HTMLElement, | ||
mainContext: Document, | ||
main: boolean, | ||
endless: number | ||
) => { | ||
let comment: Comment2; | ||
const comments: Comment2[] = []; | ||
const matches: NodeListOf<HTMLElement> = context.querySelectorAll( | ||
common.getSelectors(endless, [ | ||
`X:not(.comment--submit) > .comment__parent`, | ||
'X:not(.comment--submit) > .comment__parent', | ||
'X.comment__child', | ||
'X.comment_inner', | ||
]) | ||
); | ||
sourceLink = mainContext.querySelector( | ||
`.page__heading__breadcrumbs a[href*="/giveaway/"], .page__heading__breadcrumbs a[href*="/discussion/"], .page__heading__breadcrumbs a[href*="/ticket/"], .page_heading_breadcrumbs a[href*="/trade/"]` | ||
const sourceLink: HTMLElement | null = mainContext.querySelector( | ||
'.page__heading__breadcrumbs a[href*="/giveaway/"], .page__heading__breadcrumbs a[href*="/discussion/"], .page__heading__breadcrumbs a[href*="/ticket/"], .page_heading_breadcrumbs a[href*="/trade/"]' | ||
); | ||
for (i = matches.length - 1; i >= 0; --i) { | ||
for (let i = matches.length - 1; i >= 0; --i) { | ||
if (!sourceLink) { | ||
continue; | ||
} | ||
comment = await this.comments_getInfo( | ||
matches[i], | ||
Scope.current?.sourceLink || sourceLink, | ||
|
@@ -124,68 +163,105 @@ class Comments extends Module { | |
} | ||
} | ||
return comments; | ||
} | ||
}; | ||
|
||
async comments_getInfo(context, sourceLink, savedUsers, main) { | ||
let matches, n, source; | ||
const comment = {}; | ||
comments_getInfo = async ( | ||
context: HTMLElement, | ||
sourceLink: HTMLElement, | ||
_savedUsers: unknown, | ||
main: boolean | ||
) => { | ||
let matches: NodeListOf<HTMLElement>, | ||
n: number, | ||
source: string | null | undefined, | ||
element: HTMLElement | null, | ||
reMatches: string[] | null, | ||
attr: string | null; | ||
const comment: Comment2 = {}; | ||
comment.comment = context; | ||
comment.outerWrap = comment.comment; | ||
comment.parent = comment.comment.parentElement; | ||
const author = comment.comment.querySelector(`.comment__author, .author_name`); | ||
element = comment.comment.parentElement; | ||
if (element) { | ||
comment.parent = element; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
const author = comment.comment.querySelector('.comment__author, .author_name'); | ||
if (!author) { | ||
return; | ||
return {}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This messes with the logic, because of:
So the empty object will be added to the array and might cause issues with features that rely on this array for actual comment objects. Better to return |
||
} | ||
comment.author = author.textContent.trim(); | ||
comment.summary = comment.comment.querySelector('.comment__summary, .comment_body'); | ||
element = comment.comment.querySelector('.comment__summary, .comment_body'); | ||
if (element) { | ||
comment.summary = element; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
comment.isOp = | ||
(comment.summary && !comment.summary.id) || (comment.parent && !comment.parent.id); | ||
comment.displayState = comment.comment.querySelector( | ||
`.comment__display-state, .comment_body_default` | ||
); | ||
element = comment.comment.querySelector('.comment__display-state, .comment_body_default'); | ||
if (element) { | ||
comment.displayState = element; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
comment.text = comment.displayState | ||
? comment.displayState.textContent.trim().replace(/View\sattached\simage\./, '') | ||
: ''; | ||
comment.bump = comment.text | ||
reMatches = comment.text | ||
.replace(/[^A-Za-z]/g, '') | ||
.match(/^(havea|takea|thanksand|thankyou)?bump(ing|ity|o)?$/i); | ||
if (reMatches) { | ||
comment.bump = reMatches; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
comment.length = comment.text.length; | ||
comment.words = Array.from(new Set(comment.text.split(/\s/))); | ||
comment.actions = comment.comment.querySelector(`.comment__actions, .action_list`); | ||
matches = comment.actions.querySelectorAll(`[href*="/comment/"]`); | ||
element = comment.comment.querySelector('.comment__actions, .action_list'); | ||
if (element) { | ||
comment.actions = element; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
if (!comment.actions) { | ||
return {}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better to return |
||
} | ||
matches = comment.actions.querySelectorAll('[href*="/comment/"]'); | ||
n = matches.length; | ||
if (n > 0) { | ||
comment.permalink = matches[n - 1]; | ||
} | ||
comment.id = comment.permalink | ||
? comment.permalink.getAttribute('href').match(/\/comment\/(.+)/)[1] | ||
: ''; | ||
comment.timestamp = parseInt( | ||
comment.actions.querySelector(`[data-timestamp]`).getAttribute('data-timestamp') | ||
); | ||
comment.id = ''; | ||
if (comment.permalink) { | ||
attr = comment.permalink.getAttribute('href'); | ||
if (attr) { | ||
reMatches = attr.match(/\/comment\/(.+)/); | ||
if (reMatches) { | ||
comment.id = reMatches[1]; | ||
} | ||
} | ||
} | ||
matches = comment.actions.querySelectorAll('[data-timestamp]'); | ||
n = matches.length; | ||
if (n > 0) { | ||
attr = matches[n - 1].getAttribute('data-timestamp'); | ||
if (attr) { | ||
comment.timestamp = parseInt(attr); | ||
} | ||
} | ||
if (!main || Shared.common.isCurrentPath('Messages')) { | ||
if (this.esgst.sg) { | ||
try { | ||
source = comment.comment | ||
.closest('.comments') | ||
.previousElementSibling.firstElementChild.firstElementChild.getAttribute('href'); | ||
} catch (e) { | ||
/**/ | ||
} | ||
source = comment.comment | ||
.closest('.comments') | ||
?.previousElementSibling?.firstElementChild?.firstElementChild?.getAttribute('href'); | ||
} else { | ||
source = comment.actions.querySelector(`[href*="/trade/"]`).getAttribute('href'); | ||
source = comment.actions.querySelector('[href*="/trade/"]')?.getAttribute('href'); | ||
} | ||
} | ||
if (!source && sourceLink) { | ||
source = sourceLink.getAttribute('href'); | ||
} | ||
if (source) { | ||
source = source.match(/(giveaway|discussion|ticket|trade)\/(.+?)(\/.*)?$/); | ||
comment.type = `${source[1]}s`; | ||
comment.code = source[2]; | ||
reMatches = source.match(/(giveaway|discussion|ticket|trade)\/(.+?)(\/.*)?$/); | ||
if (reMatches) { | ||
comment.type = `${reMatches[1]}s`; | ||
comment.code = reMatches[2]; | ||
} | ||
return comment; | ||
} | ||
} | ||
return {}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better to return |
||
}; | ||
} | ||
|
||
const commentsModule = new Comments(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't make much sense here, because
sourceLink
is queried outside of the loop, so if it doesn't exist, we can return before the loop instead of evaluating it again for each match.However, I'm not sure that it's a good idea to add this check, as I'm not sure that
sourceLink
will always exist. This might break the feature in some places. Better to makesourceLink
acceptHTMLElement | undefined
.