MTT Rating Pool
Add your pokernow.com tournaments to a shared pool, so players can be rated across communities and not just inside one host's games. You send tournament IDs; the pool fetches the public standings itself.
Your submission
- Fetched
- –
- Waiting
- –
- Not finished
- –
- Failed
- –
01Bookmark button desktop
Best option. Reads the list of tournaments you've played and hosted from your logged-in pokernow session, shows you what it found, and sends it only when you click Send.
Send my tournaments- Drag the blue button onto your bookmarks bar.
- Open www.pokernow.com and make sure you're logged in.
- Click the bookmark. It takes about a minute for a few hundred tournaments.
It sends, for each tournament: its ID, name, host and status, plus your entry ID and where you finished. Never your password, cookies, chat or anything else on the page.
Show the bookmark's code
This is the exact code the button runs. __PORTAL_ORIGIN__ is replaced with this
site's address when the button is made.
"use strict";
(() => {
// src/client/bookmarklet.ts
var PORTAL = "__PORTAL_ORIGIN__";
var DELAY_MS = 2500;
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
function overlay() {
const host = document.createElement("div");
host.style.cssText = "position:fixed;inset:auto 16px 16px auto;z-index:2147483647";
const root = host.attachShadow({ mode: "open" });
root.innerHTML = `<style>
.box{font:14px/1.45 system-ui,-apple-system,sans-serif;background:#16181d;color:#eef0f3;border:1px solid #343944;
border-radius:10px;padding:14px 16px;width:min(340px,calc(100vw - 32px));box-shadow:0 8px 28px rgba(0,0,0,.35)}
b{font-weight:650} p{margin:6px 0} .muted{color:#a5acb8;font-size:12.5px}
.row{display:flex;gap:8px;margin-top:10px} button,a.btn{font:inherit;border-radius:7px;padding:7px 12px;cursor:pointer;
border:1px solid #4a5160;background:transparent;color:inherit;text-decoration:none}
.go{background:#3d8bfd;border-color:#3d8bfd;color:#fff} button:focus-visible,a:focus-visible{outline:2px solid #8ab4ff;outline-offset:2px}
</style><div class="box" role="dialog" aria-live="polite"></div>`;
document.body.append(host);
const box = root.querySelector(".box");
return {
set(html) {
box.innerHTML = html;
},
on(sel, fn) {
root.querySelector(sel)?.addEventListener("click", fn);
},
close() {
host.remove();
}
};
}
var esc = (s) => s.replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]);
async function getJSON(path) {
for (let attempt = 1; attempt <= 5; attempt++) {
await sleep(DELAY_MS);
const res = await fetch(path, { headers: { Accept: "application/json" }, credentials: "same-origin" });
const text = await res.text();
if (res.status === 429 || text.startsWith("Too many")) {
await sleep(15e3 * attempt);
continue;
}
if (res.status === 401 || res.status === 403) throw new Error("not logged in");
if (!res.ok) throw new Error(`pokernow answered HTTP ${res.status}`);
try {
return JSON.parse(text);
} catch {
throw new Error("not logged in");
}
}
throw new Error("pokernow kept rate limiting; try again in a few minutes");
}
async function allPages(path, progress) {
const rows = [];
for (let page = 1, total = 1; page <= total; page++) {
const j = await getJSON(`${path}?page=${page}`);
total = j.pagesQuantity ?? 0;
rows.push(...j.data ?? []);
progress(page, total);
}
return rows;
}
async function main() {
const ui = overlay();
const close = '<div class="row"><button class="x">Close</button></div>';
if (location.hostname !== "www.pokernow.com") {
ui.set(`<p><b>Open pokernow.com first.</b></p><p>Log in at www.pokernow.com, then click the bookmark again on that page.</p>${close}`);
ui.on(".x", ui.close);
return;
}
try {
ui.set("<p><b>Reading your tournament list\u2026</b></p><p class='muted'>Starting.</p>");
const parts = await allPages("/api/mtt/my-participations", (p, n) => ui.set(`<p><b>Reading your tournament list\u2026</b></p><p class="muted">Page ${p} of ${n || 1}. Pausing between pages so pokernow isn't flooded.</p>`));
const hosted = await allPages("/api/mtt/my-tournaments", (p, n) => ui.set(`<p><b>Reading tournaments you hosted\u2026</b></p><p class="muted">Page ${p} of ${n || 1}.</p>`));
const claims = [];
for (const p of parts) {
const t = p.mTTTournament;
if (!t?.slug) continue;
claims.push({
slug: t.slug,
role: "player",
name: t.name ?? null,
status: t.status ?? null,
host: t.ownerPlayer?.networkUsername ?? null,
registeredPlayersCount: t.registeredPlayersCount ?? null,
entryId: p.id,
entryStatus: p.status ?? null,
position: p.position ?? null,
registeredAt: p.createdAt ?? null
});
}
for (const h of hosted) {
if (h.slug) claims.push({ slug: h.slug, role: "host", name: h.name ?? null, status: h.status ?? null, registeredAt: h.createdAt ?? null });
}
const played = claims.filter((c) => c.role === "player").length;
const nHosted = claims.length - played;
if (claims.length === 0) {
ui.set(`<p><b>No tournaments found.</b></p><p>This account hasn't played or hosted any tournaments yet.</p>${close}`);
ui.on(".x", ui.close);
return;
}
ui.set(`<p><b>Found ${played} tournaments played and ${nHosted} hosted.</b></p>
<p>Send them to <b>${esc(new URL(PORTAL).host)}</b>? It receives each tournament's ID, your entry ID and where you
finished. Nothing else leaves this page: no password, no cookies, no chat.</p>
<div class="row"><button class="go">Send</button><button class="x">Cancel</button></div>`);
ui.on(".x", ui.close);
ui.on(".go", async () => {
ui.set("<p><b>Sending\u2026</b></p>");
try {
const res = await fetch(`${PORTAL}/api/submissions`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ via: "bookmarklet", claims })
});
const body = await res.json();
if (!res.ok) throw new Error(body.error ?? `portal answered HTTP ${res.status}`);
ui.set(`<p><b>Sent. Thanks!</b></p><p>${body.newTournaments} of ${body.accepted} tournaments were new to the pool.
Standings are fetched in the background over the next while.</p>
<div class="row"><a class="btn go" target="_blank" rel="noopener" href="${PORTAL}/?s=${encodeURIComponent(body.submissionId)}">View progress</a>
<button class="x">Close</button></div>`);
ui.on(".x", ui.close);
} catch (e) {
ui.set(`<p><b>Couldn't send.</b></p><p>${esc(String(e.message))}</p>${close}`);
ui.on(".x", ui.close);
}
});
} catch (e) {
const msg = e.message === "not logged in" ? "You don't seem to be logged in. Log in to pokernow.com, then click the bookmark again." : esc(e.message);
ui.set(`<p><b>Couldn't read your tournaments.</b></p><p>${msg}</p>${close}`);
ui.on(".x", ui.close);
}
}
void main();
})();
02Paste tournament links phone friendly
Paste any text that contains tournament links, such as a Discord announcement or a list of URLs. Hosts: this is the fastest way to add a whole series.