From c0724efeb21e1eaa9c8d2a3dc5adfa0f965d48ec Mon Sep 17 00:00:00 2001 From: Konstantina07 <71346111+Konstantina07@users.noreply.github.com> Date: Fri, 20 Dec 2024 18:07:30 +0200 Subject: [PATCH 1/4] Update es, critical dict --- modules/shutup/src/main/Dictionary.scala | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/shutup/src/main/Dictionary.scala b/modules/shutup/src/main/Dictionary.scala index a28bcc003955..4fab2564df67 100644 --- a/modules/shutup/src/main/Dictionary.scala +++ b/modules/shutup/src/main/Dictionary.scala @@ -9,7 +9,6 @@ private object Dictionary: def en = dict(""" (burn|die) in hell (f++|ph)(u++|e++|a++)c?k(er|r|u|k|t|ing?|ign|en|tard?|face|off?|e?d|) -(f|ph)a++gg?([oi]t|) (kill|hang|neck) my ?self [ck]um(shot|) [ck]unt(ing|) @@ -256,9 +255,11 @@ est[úu]pid[ao] gilipollas hdp hijo de (put\w*|per+a) +hijueputa idiota imbecil madre +malparid[ao] maric[oó]na? maric[ao] mierda @@ -267,6 +268,7 @@ payas[ao] pendejo po(ll|y)a put[ao] +putica trampa trampos[ao] tu eres put\w* @@ -352,11 +354,12 @@ yar+ak kafa(l[iı]|s[iı]) """) def critical = dict(""" -cancer +(die|burn)s? irl +(f|ph)a++gg?([oi]t|) (go|pl(ea)?[sz]e?) (a?nd)? ?(die|burn|suicide) (ho?pe|wish) ((yo?)?[uy](r (famil[yi]|m[ou]m|mother))?( and )?)++ (die|burn)s? -(die|burn)s? irl (kill|hang|neck) ?(yo?)?[uyi]r? ?(self|famil[yi]|m[ou]m|mother) +cancer gas the g?kys get bombed From 1a2a745fd0e77bf88270ddf4fc528262a1340375 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Fri, 20 Dec 2024 17:26:21 +0100 Subject: [PATCH 2/4] delete broken translation --- translation/dest/activity/ta-IN.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/translation/dest/activity/ta-IN.xml b/translation/dest/activity/ta-IN.xml index 93fac056f1b5..5c214954e62c 100644 --- a/translation/dest/activity/ta-IN.xml +++ b/translation/dest/activity/ta-IN.xml @@ -42,10 +42,6 @@ %s பிளேயரைப் பின்தொடரத் தொடங்கியது %s வீரர்களைப் பின்தொடரத் தொடங்கியது - - %ஒரு புதிய பின்தொடர்பவர் கிடைத்தது - %s புதிய பின்தொடர்பவர்களைப் பெற்றார் - %s ஒரே நேரத்தில் கண்காட்சி நடத்தப்பட்டது %s ஒரே நேரத்தில் கண்காட்சிகள் நடத்தப்பட்டன From 897d88648e5d37182caba706e24f6c32f26f6e7b Mon Sep 17 00:00:00 2001 From: Jonathan Gamble Date: Fri, 20 Dec 2024 11:23:56 -0600 Subject: [PATCH 3/4] import api rather than window.lichess --- pnpm-lock.yaml | 15 +++++++++++++++ ui/@types/lichess/index.d.ts | 21 --------------------- ui/analyse/src/ctrl.ts | 2 +- ui/api/package.json | 23 +++++++++++++++++++++++ ui/{site => api}/src/api.ts | 27 ++++++++++++++++++++++++--- ui/api/tsconfig.json | 3 +++ ui/bits/package.json | 1 + ui/bits/src/bits.challengePage.ts | 3 ++- ui/bits/src/bits.infiniteScroll.ts | 3 ++- ui/bits/src/bits.tvGames.ts | 13 +++++++------ ui/bits/src/bits.user.ts | 3 ++- ui/chat/package.json | 1 + ui/chat/src/ctrl.ts | 3 ++- ui/chat/src/moderation.ts | 4 ++-- ui/common/src/pubsub.ts | 4 ++++ ui/lobby/src/lobby.ts | 6 +++--- ui/mod/src/mod.user.ts | 3 ++- ui/notify/src/view.ts | 3 ++- ui/round/src/round.ts | 4 ++-- ui/simul/src/simul.home.ts | 4 ++-- ui/site/package.json | 1 + ui/site/src/announce.ts | 3 ++- ui/site/src/friends.ts | 3 ++- ui/site/src/powertip.ts | 3 ++- ui/site/src/site.ts | 8 ++------ 25 files changed, 109 insertions(+), 55 deletions(-) create mode 100644 ui/api/package.json rename ui/{site => api}/src/api.ts (76%) create mode 100644 ui/api/tsconfig.json diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8e7616a82759..64cb7d24316f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -131,6 +131,12 @@ importers: specifier: workspace:* version: link:../tree + ui/api: + dependencies: + common: + specifier: workspace:* + version: link:../common + ui/bits: dependencies: '@fnando/sparkline': @@ -166,6 +172,9 @@ importers: '@yaireo/tagify': specifier: 4.17.9 version: 4.17.9(prop-types@15.8.1) + api: + specifier: workspace:* + version: link:../api canvas-confetti: specifier: ^1.9.3 version: 1.9.3 @@ -277,6 +286,9 @@ importers: ui/chat: dependencies: + api: + specifier: workspace:* + version: link:../api common: specifier: workspace:* version: link:../common @@ -591,6 +603,9 @@ importers: ui/site: dependencies: + api: + specifier: workspace:* + version: link:../api chat: specifier: workspace:* version: link:../chat diff --git a/ui/@types/lichess/index.d.ts b/ui/@types/lichess/index.d.ts index 8365674fd3d6..17d6e682d13c 100644 --- a/ui/@types/lichess/index.d.ts +++ b/ui/@types/lichess/index.d.ts @@ -155,29 +155,8 @@ interface Events { off(key: string, cb: (...args: any[]) => void): void; } -interface Api { - initializeDom: (root?: HTMLElement) => void; - events: Events; - socket: { - subscribeToMoveLatency: () => void; - events: Events; - }; - onlineFriends: { - request: () => void; - events: Events; - }; - chat: { - post: (text: string) => void; - }; - overrides: { - [key: string]: (...args: any[]) => unknown; - }; - analysis?: any; -} - interface Window { site: Site; - lichess: Api; fipr: Fipr; i18n: I18n; $as(cash: Cash): T; diff --git a/ui/analyse/src/ctrl.ts b/ui/analyse/src/ctrl.ts index 802da249fdb9..7c93e687c2a0 100644 --- a/ui/analyse/src/ctrl.ts +++ b/ui/analyse/src/ctrl.ts @@ -195,7 +195,7 @@ export default class AnalyseCtrl { }); pubsub.on('board.change', redraw); this.persistence?.merge(); - window.lichess.analysis = api(this); + (window as any).lichess.analysis = api(this); } initialize(data: AnalyseData, merge: boolean): void { diff --git a/ui/api/package.json b/ui/api/package.json new file mode 100644 index 000000000000..ab364fbcc068 --- /dev/null +++ b/ui/api/package.json @@ -0,0 +1,23 @@ +{ + "name": "api", + "version": "2.0.0", + "private": true, + "description": "lichess.org browser extension API", + "author": "Thibault Duplessis", + "license": "AGPL-3.0-or-later", + "typings": "api", + "typesVersions": { + "*": { + "*": [ + "dist/*" + ] + } + }, + "exports": { + ".": "./src/api.ts", + "./*": "./src/*.ts" + }, + "dependencies": { + "common": "workspace:*" + } +} diff --git a/ui/site/src/api.ts b/ui/api/src/api.ts similarity index 76% rename from ui/site/src/api.ts rename to ui/api/src/api.ts index 4039e43c0ad7..4c7a65926744 100644 --- a/ui/site/src/api.ts +++ b/ui/api/src/api.ts @@ -1,4 +1,4 @@ -import type { Pubsub, PubsubCallback, PubsubEvent } from 'common/pubsub'; +import { type PubsubCallback, type PubsubEvent, pubsub, initializeDom } from 'common/pubsub'; // #TODO document these somewhere const publicEvents = ['ply', 'analysis.change', 'chat.resize', 'analysis.closeAll']; @@ -6,8 +6,29 @@ const socketEvents = ['lag', 'close']; const socketInEvents = ['mlat', 'fen', 'notifications', 'endData']; const friendsEvents = ['playing', 'stopped_playing', 'onlines', 'enters', 'leaves']; -export const api = (pubsub: Pubsub): Api => ({ - initializeDom: (root?: HTMLElement) => pubsub.emit('content-loaded', root), +export interface Api { + initializeDom: (root?: HTMLElement) => void; + events: Events; + socket: { + subscribeToMoveLatency: () => void; + events: Events; + }; + onlineFriends: { + request: () => void; + events: Events; + }; + chat: { + post: (text: string) => void; + }; + overrides: { + [key: string]: (...args: any[]) => unknown; + }; + analysis?: any; +} + +// this object is available to extensions as window.lichess +export const api: Api = ((window as any).lichess = { + initializeDom, events: { on(name: PubsubEvent, cb: PubsubCallback): void { if (!publicEvents.includes(name)) throw 'This event is not part of the public API'; diff --git a/ui/api/tsconfig.json b/ui/api/tsconfig.json new file mode 100644 index 000000000000..4eb37fee05c6 --- /dev/null +++ b/ui/api/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../tsconfig.base.json" +} diff --git a/ui/bits/package.json b/ui/bits/package.json index bc4b1813d406..470a8533b2eb 100644 --- a/ui/bits/package.json +++ b/ui/bits/package.json @@ -27,6 +27,7 @@ "@types/yaireo__tagify": "4.27.0", "@types/zxcvbn": "^4.4.5", "@yaireo/tagify": "4.17.9", + "api": "workspace:*", "canvas-confetti": "^1.9.3", "chat": "workspace:*", "chess": "workspace:*", diff --git a/ui/bits/src/bits.challengePage.ts b/ui/bits/src/bits.challengePage.ts index 7bfebe5cd745..22bc2be7304e 100644 --- a/ui/bits/src/bits.challengePage.ts +++ b/ui/bits/src/bits.challengePage.ts @@ -2,6 +2,7 @@ import * as xhr from 'common/xhr'; import { wsConnect, wsSend } from 'common/socket'; import { userComplete } from 'common/userComplete'; import { isTouchDevice, isIos } from 'common/device'; +import { initializeDom } from 'common/pubsub'; interface ChallengeOpts { xhrUrl: string; @@ -19,7 +20,7 @@ export function initModule(opts: ChallengeOpts): void { xhr.text(opts.xhrUrl).then(html => { $(selector).replaceWith($(html).find(selector)); init(); - window.lichess.initializeDom($(selector)[0]); + initializeDom($(selector)[0]); }); }, }, diff --git a/ui/bits/src/bits.infiniteScroll.ts b/ui/bits/src/bits.infiniteScroll.ts index 1e0e9613f51b..5fec3fb85d31 100644 --- a/ui/bits/src/bits.infiniteScroll.ts +++ b/ui/bits/src/bits.infiniteScroll.ts @@ -1,5 +1,6 @@ import * as xhr from 'common/xhr'; import { spinnerHtml } from 'common/spinner'; +import { initializeDom } from 'common/pubsub'; export function initModule(selector: string = '.infinite-scroll'): void { $(selector).each(function (this: HTMLElement) { @@ -36,7 +37,7 @@ function register(el: HTMLElement, selector: string, backoff = 500) { nav.remove(); $(el).append(($(html).is(selector) ? $(html) : $(html).find(selector)).html()); dedupEntries(el); - window.lichess.initializeDom(el); + initializeDom(el); setTimeout(() => register(el, selector, backoff * 1.05), backoff); // recursion with backoff }, e => { diff --git a/ui/bits/src/bits.tvGames.ts b/ui/bits/src/bits.tvGames.ts index e73687040076..672abae9f54f 100644 --- a/ui/bits/src/bits.tvGames.ts +++ b/ui/bits/src/bits.tvGames.ts @@ -1,5 +1,6 @@ import * as xhr from 'common/xhr'; -import { pubsub } from 'common/pubsub'; +import { pubsub, initializeDom } from 'common/pubsub'; +import { api } from 'api'; interface ReplacementResponse { id: string; @@ -28,8 +29,8 @@ const requestReplacementGame = () => { .json(url.toString()) .then((data: ReplacementResponse) => { main.find(`.mini-game[href^="/${oldId}"]`).replaceWith(data.html); - if (data.html.includes('mini-game__result')) window.lichess.overrides.tvGamesOnFinish(data.id); - window.lichess.initializeDom(); + if (data.html.includes('mini-game__result')) api.overrides.tvGamesOnFinish(data.id); + initializeDom(); }) .then(done, done); }); @@ -40,17 +41,17 @@ const done = () => { requestReplacementGame(); }; -window.lichess.overrides.tvGamesOnFinish = (id: string) => +api.overrides.tvGamesOnFinish = (id: string) => setTimeout(() => { finishedIdQueue.push(id); requestReplacementGame(); }, 7000); // 7000 matches the rematch wait duration in /modules/tv/main/Tv.scala site.load.then(() => { - pubsub.on('socket.in.finish', ({ id }) => window.lichess.overrides.tvGamesOnFinish(id)); + pubsub.on('socket.in.finish', ({ id }) => api.overrides.tvGamesOnFinish(id)); $('main.tv-games') .find('.mini-game') .each((_i, el) => { - if ($(el).find('.mini-game__result').length > 0) window.lichess.overrides.tvGamesOnFinish(getId(el)!); + if ($(el).find('.mini-game__result').length > 0) api.overrides.tvGamesOnFinish(getId(el)!); }); }); diff --git a/ui/bits/src/bits.user.ts b/ui/bits/src/bits.user.ts index 31d5d7494679..ab32efa78017 100644 --- a/ui/bits/src/bits.user.ts +++ b/ui/bits/src/bits.user.ts @@ -1,6 +1,7 @@ import * as xhr from 'common/xhr'; import { makeLinkPopups } from 'common/linkPopup'; import { alert } from 'common/dialog'; +import { initializeDom } from 'common/pubsub'; export function initModule(): void { makeLinkPopups($('.social_links')); @@ -47,7 +48,7 @@ export function initModule(): void { browseTo = (path: string) => xhr.text(path).then(html => { $content.html(html); - window.lichess.initializeDom($content[0]); + initializeDom($content[0]); history.replaceState({}, '', path); site.asset.loadEsm('bits.infiniteScroll'); }); diff --git a/ui/chat/package.json b/ui/chat/package.json index 4263cbc39719..63dbfaeb97e7 100644 --- a/ui/chat/package.json +++ b/ui/chat/package.json @@ -10,6 +10,7 @@ ".": "./src/chat.ts" }, "dependencies": { + "api": "workspace:*", "common": "workspace:*", "palantir": "workspace:*" } diff --git a/ui/chat/src/ctrl.ts b/ui/chat/src/ctrl.ts index 0e568909968c..0bb5128c2ed9 100644 --- a/ui/chat/src/ctrl.ts +++ b/ui/chat/src/ctrl.ts @@ -18,6 +18,7 @@ import { prop } from 'common'; import { storage, type LichessStorage } from 'common/storage'; import { pubsub, type PubsubEvent, type PubsubCallback } from 'common/pubsub'; import { alert } from 'common/dialog'; +import { api } from 'api'; export default class ChatCtrl { data: ChatData; @@ -102,7 +103,7 @@ export default class ChatCtrl { alert('Max length: 140 chars. ' + text.length + ' chars used.'); return false; } - window.lichess.chat.post(text); + api.chat.post(text); return true; }; diff --git a/ui/chat/src/moderation.ts b/ui/chat/src/moderation.ts index d05a177e0c76..b105ced56fb6 100644 --- a/ui/chat/src/moderation.ts +++ b/ui/chat/src/moderation.ts @@ -6,7 +6,7 @@ import type { ModerationCtrl, ModerationOpts, ModerationData, ModerationReason } import { numberFormat } from 'common/number'; import { userModInfo, flag, timeout } from './xhr'; import type ChatCtrl from './ctrl'; -import { pubsub } from 'common/pubsub'; +import { pubsub, initializeDom } from 'common/pubsub'; import { confirm } from 'common/dialog'; export function moderationCtrl(opts: ModerationOpts): ModerationCtrl { @@ -158,7 +158,7 @@ export function moderationView(ctrl?: ModerationCtrl): VNode[] | undefined { { hook: { insert() { - window.lichess.initializeDom(); + initializeDom(); }, }, }, diff --git a/ui/common/src/pubsub.ts b/ui/common/src/pubsub.ts index 52bf39da00e8..ca622dc0ac8a 100644 --- a/ui/common/src/pubsub.ts +++ b/ui/common/src/pubsub.ts @@ -99,6 +99,10 @@ export class Pubsub { export const pubsub: Pubsub = new Pubsub(); +export function initializeDom(root?: HTMLElement): void { + pubsub.emit('content-loaded', root); +} + interface OneTimeHandler { promise: Promise; resolve?: () => void; diff --git a/ui/lobby/src/lobby.ts b/ui/lobby/src/lobby.ts index d49dd6372c88..15a170b0e429 100644 --- a/ui/lobby/src/lobby.ts +++ b/ui/lobby/src/lobby.ts @@ -2,7 +2,7 @@ import * as xhr from 'common/xhr'; import main from './main'; import type { LobbyOpts } from './interfaces'; import { wsConnect, wsPingInterval } from 'common/socket'; -import { pubsub } from 'common/pubsub'; +import { pubsub, initializeDom } from 'common/pubsub'; export function initModule(opts: LobbyOpts) { opts.appElement = document.querySelector('.lobby__app') as HTMLElement; @@ -35,12 +35,12 @@ export function initModule(opts: LobbyOpts) { reload_timeline() { xhr.text('/timeline').then(html => { $('.timeline').html(html); - window.lichess.initializeDom(); + initializeDom(); }); }, featured(o: { html: string }) { $('.lobby__tv').html(o.html); - window.lichess.initializeDom(); + initializeDom(); }, redirect(e: RedirectTo) { lobbyCtrl.setRedirecting(); diff --git a/ui/mod/src/mod.user.ts b/ui/mod/src/mod.user.ts index 1602689d3f1f..d3949cc3538c 100644 --- a/ui/mod/src/mod.user.ts +++ b/ui/mod/src/mod.user.ts @@ -6,6 +6,7 @@ import tablesort from 'tablesort'; import { expandCheckboxZone, shiftClickCheckboxRange, selector } from './checkBoxes'; import { spinnerHtml } from 'common/spinner'; import { confirm } from 'common/dialog'; +import { initializeDom } from 'common/pubsub'; site.load.then(() => { const $toggle = $('.mod-zone-toggle'), @@ -63,7 +64,7 @@ site.load.then(() => { const getLocationHash = (a: HTMLAnchorElement) => a.href.replace(/.+(#\w+)$/, '$1'); function userMod($inZone: Cash) { - window.lichess.initializeDom($inZone[0]); + initializeDom($inZone[0]); const makeReady = (selector: string, f: (el: HTMLElement, i: number) => void, cls = 'ready') => { $inZone.find(selector + `:not(.${cls})`).each(function (this: HTMLElement, i: number) { diff --git a/ui/notify/src/view.ts b/ui/notify/src/view.ts index 0dcc68716ec3..677f50e36995 100644 --- a/ui/notify/src/view.ts +++ b/ui/notify/src/view.ts @@ -3,6 +3,7 @@ import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { spinnerVdom as spinner } from 'common/spinner'; import makeRenderers from './renderers'; +import { initializeDom } from 'common/pubsub'; const renderers = makeRenderers(); @@ -73,7 +74,7 @@ function clickHook(f: () => void) { }; } -const contentLoaded = (vnode: VNode) => window.lichess.initializeDom(vnode.elm as HTMLElement); +const contentLoaded = (vnode: VNode) => initializeDom(vnode.elm as HTMLElement); function recentNotifications(d: NotifyData, scrolling: boolean): VNode { return h( diff --git a/ui/round/src/round.ts b/ui/round/src/round.ts index 67d1f4253d28..d3387e1d50de 100644 --- a/ui/round/src/round.ts +++ b/ui/round/src/round.ts @@ -11,7 +11,7 @@ import { wsConnect, wsDestroy } from 'common/socket'; import { storage } from 'common/storage'; import { setClockWidget } from 'common/clock'; import { makeChat } from 'chat'; -import { pubsub } from 'common/pubsub'; +import { pubsub, initializeDom } from 'common/pubsub'; import { myUserId } from 'common'; import { alert } from 'common/dialog'; @@ -76,7 +76,7 @@ async function boot( $meta.length && $('.game__meta').replaceWith($meta); $('.crosstable').replaceWith($html.find('.crosstable')); startTournamentClock(); - window.lichess.initializeDom(); + initializeDom(); }); }, tourStanding(s: TourPlayer[]) { diff --git a/ui/simul/src/simul.home.ts b/ui/simul/src/simul.home.ts index 966de3fde2d9..ff8634d9f692 100644 --- a/ui/simul/src/simul.home.ts +++ b/ui/simul/src/simul.home.ts @@ -1,5 +1,5 @@ import { wsConnect } from 'common/socket'; -import { pubsub } from 'common/pubsub'; +import { pubsub, initializeDom } from 'common/pubsub'; site.load.then(() => { wsConnect(`/socket/v5`, false, { params: { flag: 'simul' } }); @@ -7,6 +7,6 @@ site.load.then(() => { const rsp = await fetch('/simul/reload'); const html = await rsp.text(); $('.simul-list__content').html(html); - window.lichess.initializeDom(); + initializeDom(); }); }); diff --git a/ui/site/package.json b/ui/site/package.json index e42e067372e6..b5249b7f274c 100644 --- a/ui/site/package.json +++ b/ui/site/package.json @@ -6,6 +6,7 @@ "author": "Thibault Duplessis", "license": "AGPL-3.0-or-later", "dependencies": { + "api": "workspace:*", "chat": "workspace:*", "chess": "workspace:*", "common": "workspace:*", diff --git a/ui/site/src/announce.ts b/ui/site/src/announce.ts index 7866c06219bd..1f2c95e48771 100644 --- a/ui/site/src/announce.ts +++ b/ui/site/src/announce.ts @@ -1,4 +1,5 @@ import { escapeHtml } from 'common'; +import { initializeDom } from 'common/pubsub'; let timeout: Timeout | undefined; @@ -24,7 +25,7 @@ const announce = (d: LichessAnnouncement) => { const millis = d.date ? new Date(d.date).getTime() - Date.now() : 5000; if (millis > 0) timeout = setTimeout(kill, millis); else kill(); - if (d.date) window.lichess.initializeDom(); + if (d.date) initializeDom(); } }; diff --git a/ui/site/src/friends.ts b/ui/site/src/friends.ts index 999ba251a932..49d9bdb25236 100644 --- a/ui/site/src/friends.ts +++ b/ui/site/src/friends.ts @@ -1,5 +1,6 @@ import { notNull } from 'common/common'; import * as licon from 'common/licon'; +import { api as lichess } from 'api'; type TitleName = string; @@ -17,7 +18,7 @@ export default class OnlineFriends { users: Map; constructor(readonly el: HTMLElement) { - const api = window.lichess.onlineFriends; + const api = lichess.onlineFriends; this.titleEl = this.el.querySelector('.friend_box_title') as HTMLElement; this.titleEl.addEventListener('click', () => { this.el.querySelector('.content_wrap')?.classList.toggle('none'); diff --git a/ui/site/src/powertip.ts b/ui/site/src/powertip.ts index ee4ac94aabe2..30abb103c160 100644 --- a/ui/site/src/powertip.ts +++ b/ui/site/src/powertip.ts @@ -2,6 +2,7 @@ import * as licon from 'common/licon'; import { text as xhrText } from 'common/xhr'; import { requestIdleCallback, $as } from 'common'; import { spinnerHtml } from 'common/spinner'; +import { initializeDom } from 'common/pubsub'; // Thanks Steven Benner! - adapted from https://github.com/stevenbenner/jquery-powertip @@ -13,7 +14,7 @@ const onPowertipPreRender = (id: string, preload?: (url: string) => void) => (el xhrText(url + '/mini').then(html => { const el = document.getElementById(id) as HTMLElement; el.innerHTML = html; - window.lichess.initializeDom(el); + initializeDom(el); }); }; diff --git a/ui/site/src/site.ts b/ui/site/src/site.ts index 24f2bf360222..e8e97a0043f4 100644 --- a/ui/site/src/site.ts +++ b/ui/site/src/site.ts @@ -7,14 +7,13 @@ import { unload, redirect, reload } from './reload'; import announce from './announce'; import { displayLocale } from 'common/i18n'; import sound from './sound'; -import { api } from './api'; -import { pubsub } from 'common/pubsub'; const site = window.site; // site.load is initialized in site.inline.ts (body script) // site.manifest is fetched // site.info, site.debug are populated by ui/build -// site.quietMode, site.analysis are set elsewhere +// site.quietMode is set elsewhere +// window.lichess is initialized in ui/api/src/api.ts site.sri = randomToken(); site.displayLocale = displayLocale; site.blindMode = document.body.classList.contains('blind-mode'); @@ -27,6 +26,3 @@ site.reload = reload; site.announce = announce; site.sound = sound; site.load.then(boot); - -// public API -window.lichess = api(pubsub); From 2d86ba44c2b127478ccbe45380379ef92df8e956 Mon Sep 17 00:00:00 2001 From: Niklas Fiekas Date: Fri, 20 Dec 2024 18:45:44 +0100 Subject: [PATCH 4/4] directly use pwned k-anonymity api --- conf/base.conf | 2 +- modules/security/src/main/Env.scala | 2 +- modules/security/src/main/Pwned.scala | 12 ++++++------ modules/security/src/main/SecurityConfig.scala | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/conf/base.conf b/conf/base.conf index cf0058a107c6..68fadbaf11c6 100644 --- a/conf/base.conf +++ b/conf/base.conf @@ -215,7 +215,7 @@ security { enabled = false url = "http://ip2proxy.lichess.ovh:1929" } - pwned.url = "" + pwned.range_url = "https://api.pwnedpasswords.com/range/" hcaptcha = ${hcaptcha} lame_name_check = true password.bpass.secret = ${user.password.bpass.secret} diff --git a/modules/security/src/main/Env.scala b/modules/security/src/main/Env.scala index dfb91eba0527..9c33f2c5ffc4 100644 --- a/modules/security/src/main/Env.scala +++ b/modules/security/src/main/Env.scala @@ -147,7 +147,7 @@ final class Env( lazy val ipTrust: IpTrust = wire[IpTrust] - lazy val pwned: Pwned = Pwned(ws, config.pwnedUrl) + lazy val pwned: Pwned = Pwned(ws, config.pwnedRangeUrl) lazy val proxy2faSetting: SettingStore[Strings] @@ Proxy2faSetting = settingStore[Strings]( "proxy2fa", diff --git a/modules/security/src/main/Pwned.scala b/modules/security/src/main/Pwned.scala index bb37b5ac4e17..22acbae9963c 100644 --- a/modules/security/src/main/Pwned.scala +++ b/modules/security/src/main/Pwned.scala @@ -6,21 +6,21 @@ import play.api.libs.ws.DefaultBodyReadables.* import play.api.libs.ws.JsonBodyReadables.* import play.api.libs.ws.StandaloneWSClient -// https://github.com/lichess-org/lila-pwned -final class Pwned(ws: StandaloneWSClient, url: String)(using Executor): +final class Pwned(ws: StandaloneWSClient, rangeUrl: String)(using Executor): def apply(pass: lila.core.security.ClearPassword): Fu[Boolean] = - url.nonEmpty.so( + rangeUrl.nonEmpty.so: + val (prefix, suffix) = pass.value.sha1.hex.toUpperCase.splitAt(5) + val url = s"${rangeUrl}${prefix}" ws.url(url) - .addQueryStringParameters("sha1" -> pass.value.sha1) + .addHttpHeaders("Add-Padding" -> "true") .withRequestTimeout(1.second) .get() .map: case res if res.status == 200 => - (res.body[JsValue] \ "n").asOpt[Int].exists(_ > 0) + res.body[String].contains(suffix) case res => logger.warn(s"Pwnd ${url} ${res.status} ${res.body[String].take(200)}") false .monValue: result => _.security.pwned.get(result) - ) diff --git a/modules/security/src/main/SecurityConfig.scala b/modules/security/src/main/SecurityConfig.scala index 74e0ec224e64..e388e184cc20 100644 --- a/modules/security/src/main/SecurityConfig.scala +++ b/modules/security/src/main/SecurityConfig.scala @@ -24,7 +24,7 @@ final private class SecurityConfig( val hcaptcha: Hcaptcha.Config, @ConfigName("ip2proxy") val ip2Proxy: Ip2Proxy, @ConfigName("lame_name_check") val lameNameCheck: LameNameCheck, - @ConfigName("pwned.url") val pwnedUrl: String, + @ConfigName("pwned.range_url") val pwnedRangeUrl: String, @ConfigName("password.bpass.secret") val passwordBPassSecret: Secret )