Skip to content

Commit

Permalink
refactor(MarkBlocked): add global block & global lock query (qiuwenba…
Browse files Browse the repository at this point in the history
…ike#1630)

* refactor(MarkBlocked): add global block & global lock query

* add G-Block and G-lock query
* add ApiQueryGlobalBlocksParams and ApiQueryGlobalUserInfoResponse
* exclude elements with .ext-discussiontools-init-timestamplink
* add new i18n messages
* add new CSS class
  • Loading branch information
WaitSpringQW authored Jan 3, 2025
1 parent 44a132d commit b3e3327
Show file tree
Hide file tree
Showing 7 changed files with 295 additions and 70 deletions.
8 changes: 7 additions & 1 deletion dist/MarkBlocked/MarkBlocked.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

182 changes: 139 additions & 43 deletions dist/MarkBlocked/MarkBlocked.js

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions src/MarkBlocked/modules/MarkBlocked.module.less
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@
font-style: italic;
opacity: 0.4;
}

.userlinkLock {
text-decoration: line-through double;
font-style: italic;
opacity: 0.4;
}
10 changes: 10 additions & 0 deletions src/MarkBlocked/modules/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ const getI18nMessages = () => {
'zh-hans': ';由$2$5封禁$1:$3($4前)',
'zh-hant': ';由$2$5封鎖$1:$3($4前)',
}),
'Globally Blocked': localize({
en: '; $5blocked globally ($1) by $2: $3 ($4 ago)',
'zh-hans': ';由$2$5全域封禁$1:$3($4前)',
'zh-hant': ';由$2$5全域封鎖$1:$3($4前)',
}),
Locked: localize({
en: '; Locked',
'zh-hans': ';已全域锁定',
'zh-hant': ';已全域鎖定',
}),
partial: localize({
en: 'partial ',
zh: '部分',
Expand Down
152 changes: 126 additions & 26 deletions src/MarkBlocked/modules/markBlockedUser.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {inHours, parseTS} from './util/parseTime';
import {loading, userlinkIndef, userlinkPartial, userlinkTemp} from './MarkBlocked.module.less';
import {loading, userlinkIndef, userlinkLock, userlinkPartial, userlinkTemp} from './MarkBlocked.module.less';
import {api} from './util/api';
import {generateUserLinks} from './util/generateUserLinks';
import {getMessage} from './i18n';
Expand Down Expand Up @@ -30,44 +30,111 @@ const markBlockedUser = ($content: JQuery): void => {
timestamp: string;
user: string;
}>;
globalblocks?: Array<{
by: string;
expiry: string;
reason: string;
timestamp: string;
target: string;
}>;
globaluserinfo?: {
name?: string;
locked?: boolean;
};
};
};

// Callback: receive data and mark links
const markLinks = (response: Response): void => {
if (!response['query']?.blocks) {
return;
}
if (response['query']?.blocks) {
for (const block of response['query'].blocks) {
const isPartialBlcok: boolean = typeof block.restrictions === 'string' && block.restrictions !== ''; // Partial block

let className: string = userlinkPartial as string;
let blockTime: string = '';
if (block.expiry.startsWith('in')) {
if (!isPartialBlcok) {
className = userlinkIndef as string;
}
blockTime = getMessage('infinity');
} else {
if (!isPartialBlcok) {
className = userlinkTemp as string;
}
blockTime = inHours(parseTS(block.expiry) - parseTS(block.timestamp));
}

for (const block of response['query'].blocks) {
const isPartialBlcok: boolean = typeof block.restrictions === 'string' && block.restrictions !== ''; // Partial block
let tip: string = getMessage('Blocked')
.replace('$1', blockTime)
.replace('$2', block.by)
.replace('$3', block.reason)
.replace('$4', inHours(Date.now() - parseTS(block.timestamp)));
tip = isPartialBlcok ? tip.replace('$5', getMessage('partial')) : tip.replace('$5', '');

let className: string = userlinkPartial as string;
let blockTime: string = '';
if (block.expiry.startsWith('in')) {
if (!isPartialBlcok) {
className = userlinkIndef as string;
const $links: JQuery[] | undefined = userLinks[block.user];
if (!$links) {
continue;
}
blockTime = getMessage('infinity');
} else {
if (!isPartialBlcok) {

for (const $link of $links) {
// The following classes are used here:
// * see ./Markblocked.module.less
// * for more information
$link.addClass(className).attr('title', $link.attr('title') + tip);
}
}
}

if (response['query']?.globalblocks) {
for (const block of response['query'].globalblocks) {
let className: string = userlinkPartial as string;
let blockTime: string = '';
if (block.expiry.startsWith('in')) {
className = userlinkIndef as string;
blockTime = getMessage('infinity');
} else {
className = userlinkTemp as string;
blockTime = inHours(parseTS(block.expiry) - parseTS(block.timestamp));
}

let tip: string = getMessage('Globally Blocked')
.replace('$1', blockTime)
.replace('$2', block.by)
.replace('$3', block.reason)
.replace('$4', inHours(Date.now() - parseTS(block.timestamp)));
tip = tip.replace('$5', '');

const $links: JQuery[] | undefined = userLinks[block.target];
if (!$links) {
continue;
}
blockTime = inHours(parseTS(block.expiry) - parseTS(block.timestamp));

for (const $link of $links) {
// The following classes are used here:
// * see ./Markblocked.module.less
// * for more information
$link.addClass(className).attr('title', $link.attr('title') + tip);
}
}
}

if (response['query']?.globaluserinfo) {
const user = response['query'].globaluserinfo?.name;
const locked = response['query'].globaluserinfo?.locked;

if (!locked || !user) {
return;
}

let tip: string = getMessage('Blocked')
.replace('$1', blockTime)
.replace('$2', block.by)
.replace('$3', block.reason)
.replace('$4', inHours(Date.now() - parseTS(block.timestamp)));
tip = isPartialBlcok ? tip.replace('$5', getMessage('partial')) : tip.replace('$5', '');
const tip: string = getMessage('Locked');

const $links: JQuery[] | undefined = userLinks[block.user];
const $links: JQuery[] | undefined = userLinks[user];
if (!$links) {
continue;
return;
}

const className = userlinkLock as string;

for (const $link of $links) {
// The following classes are used here:
// * see ./Markblocked.module.less
Expand All @@ -79,21 +146,54 @@ const markBlockedUser = ($content: JQuery): void => {

const promises: (() => Promise<void>)[] = [];

type Bgprop = 'address' | 'by' | 'expiry' | 'id' | 'range' | 'reason' | 'target' | 'timestamp';

type ApiQueryGlobalBlocksParamsRedefined = Omit<ApiQueryGlobalBlocksParams, 'bgprop'> & {
bgtargets?: string | string[];
bgprop?: Bgprop | Bgprop[];
};

// Local and Global Lock
for (let i = 0; i < users.length; i++) {
const bkusers = users.splice(0, 25);
if (!bkusers.length) {
continue;
}

promises[promises.length] = async (): Promise<void> => {
const params: ApiQueryBlocksParams = {
bkusers,
const params: ApiQueryBlocksParams & ApiQueryGlobalBlocksParamsRedefined = {
action: 'query',
format: 'json',
formatversion: '2',
list: 'blocks',
list: ['blocks', 'globalblocks'],
bkusers,
bgtargets: bkusers,
bklimit: 100,
bglimit: 100,
bkprop: ['by', 'expiry', 'reason', 'restrictions', 'timestamp', 'user'],
bgprop: ['by', 'expiry', 'reason', 'timestamp'],
smaxage: 600,
maxage: 600,
};

try {
const response = await api.get(params);
markLinks(response as Response);
} catch (error: unknown) {
console.error('[MarkBlocked] Ajax error:', error);
}
};
}

// Global Lock
for (const guiuser of users) {
promises[promises.length] = async (): Promise<void> => {
const params: ApiQueryGlobalUserInfoResponse = {
action: 'query',
format: 'json',
formatversion: '2',
meta: ['globaluserinfo'],
guiuser,
smaxage: 600,
maxage: 600,
};
Expand Down
1 change: 1 addition & 0 deletions src/MarkBlocked/modules/util/generateUserLinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const generateUserLinks = ($content: JQuery): Record<string, JQuery[]> => {
const $element: JQuery<HTMLAnchorElement> = $(element);
if (
$element.hasClass('mw-changeslist-date') ||
$element.hasClass('ext-discussiontools-init-timestamplink') ||
$element.parent('span').hasClass('mw-history-undo') ||
$element.parent('span').hasClass('mw-rollback-link')
) {
Expand Down
6 changes: 6 additions & 0 deletions src/MwApiParams.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ type ApiQueryContributorsParams = import('types-mediawiki-renovate/api_params').
import('types-mediawiki-renovate/api_params').ApiFormatJsonParams;
type ApiEditPageParams = import('types-mediawiki-renovate/api_params').ApiEditPageParams &
import('types-mediawiki-renovate/api_params').ApiFormatJsonParams;
type ApiQueryGlobalBlocksParams =
import('types-mediawiki-renovate/api_params').GlobalBlockingApiQueryGlobalBlocksParams &
import('types-mediawiki-renovate/api_params').ApiFormatJsonParams;
type ApiQueryGlobalUserInfoResponse =
import('types-mediawiki-renovate/api_params').CentralAuthApiQueryGlobalUserInfoParams &
import('types-mediawiki-renovate/api_params').ApiFormatJsonParams;
type ApiImportParams = import('types-mediawiki-renovate/api_params').ApiImportParams &
import('types-mediawiki-renovate/api_params').ApiFormatJsonParams;
type ApiOpenSearchParams = import('types-mediawiki-renovate/api_params').ApiOpenSearchParams &
Expand Down

0 comments on commit b3e3327

Please sign in to comment.