-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Minecraft Wiki): add presence (#8300)
- Loading branch information
Showing
3 changed files
with
231 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
{ | ||
"$schema": "https://schemas.premid.app/metadata/1.10", | ||
"author": { | ||
"id": "193714715631812608", | ||
"name": "theusaf" | ||
}, | ||
"service": "Minecraft Wiki", | ||
"description": { | ||
"en": "Welcome to the most comprehensive wiki about the Minecraft franchise! We are a community-run, publicly accessible and editable website that can be improved by everyone.", | ||
"pt": "Seja bem-vindo(a) à wiki mais compreensiva sobre a franquia de Minecraft! Nós somos um site administrado pela comunidade, acessível ao público, e que pode ser melhorado por qualquer pessoa.", | ||
"de": "Dieses Wiki ist eine von Wikipedia inspirierte Enzyklopädie, in der hilfreiche und ausführliche Informationen zu dem Open-World-Spiel Minecraft bereitgestellt werden. Das Wiki mit seinen 4.592 Artikeln (siehe Inhaltsverzeichnis) und 20.949 Dateien wird von 50 aktiven Autoren und Administratoren aktuell gehalten. Jeder kann mit seinem Wissen beitragen.", | ||
"es": "La wiki con la mayor cantidad de información acerca de la franquicia de Minecraft. Tenemos información sobre criaturas, bloques, encantamientos y mucho más, organizado en páginas agradables a la vista.", | ||
"fr": "Bienvenue sur le wiki le plus complet sur la franchise Minecraft! Nous sommes un site web géré par la communauté, accessible et éditable par tous.", | ||
"ja_JP": "Minecraft Wiki日本語版にようこそ!このWikiはコミュニティによって運営されている、一般に公開され、編集可能なウェブサイトです。", | ||
"ko_KR": "Minecraft 위키에 오신 걸 환영합니다! Minecraft 위키는 Minecraft에 관한 최대한의 정보를 담고, 여러분과 함께 만들어지는 사전입니다.현재 Minecraft 위키에는 1,286개의 문서와 10,383개의 파일이 있고, 16명의 사용자가 활동적으로 기여하고 있습니다. 지금 시작해 보세요!", | ||
"zh_CN": "掠夺者是一种装配弩的灾厄村民。", | ||
"ru": "Добро пожаловать на Minecraft Wiki — самую обширную вики о франшизе Minecraft! Мы являемся общедоступным и редактируемым веб-сайтом, управляемым сообществом, который может быть улучшен каждым. ", | ||
"th": "ยินดีต้อนรับเข้าสู่วิกิที่มีเนื้อหาครอบคลุมที่สุดเกี่ยวกับแฟรนไชส์ Minecraft! วิกิแห่งนี้เป็นเว็บไซต์ที่ขับเคลื่อนโดยชุมชน เข้าถึงได้อย่างสาธารณะ และสามารถแก้ไขได้ ทุกคนสามารถมีส่วนร่วมในการพัฒนาวิกิแห่งนี้" | ||
}, | ||
"url": "minecraft.wiki", | ||
"matches": [ | ||
"*://minecraft.wiki/*", | ||
"*://*.minecraft.wiki/*" | ||
], | ||
"version": "1.0.0", | ||
"logo": "https://i.imgur.com/SPgKjjJ.png", | ||
"thumbnail": "https://i.imgur.com/ojVB30O.png", | ||
"color": "#3776A9", | ||
"category": "games", | ||
"tags": [ | ||
"minecraft", | ||
"community", | ||
"encyclopedia" | ||
], | ||
"settings": [ | ||
{ | ||
"multiLanguage": [ | ||
"google classroom", | ||
"youtube", | ||
"kahoot", | ||
"apple" | ||
], | ||
"id": "lang" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
import { getUserNamespace, getTalkNamespace } from "./util"; | ||
|
||
const presence = new Presence({ | ||
clientId: "1232903356025143297", | ||
}), | ||
browsingTimestamp = Math.floor(Date.now() / 1000); | ||
|
||
function hasPermissions(): boolean { | ||
return !document.querySelector(".permissions-errors"); | ||
} | ||
|
||
presence.on("UpdateData", async () => { | ||
const presenceData: PresenceData = { | ||
startTimestamp: browsingTimestamp, | ||
}, | ||
{ href, pathname, search } = document.location, | ||
searchParams = new URLSearchParams(search), | ||
strings = await presence.getStrings({ | ||
viewHome: "general.viewHome", | ||
viewUser: "general.viewUser", | ||
viewAThread: "general.viewAThread", | ||
buttonViewProfile: "general.buttonViewProfile", | ||
editing: "general.editing", | ||
advancedSettings: "google classroom.settings", | ||
viewAPage: "general.viewAPage", | ||
buttonViewPage: "general.buttonViewPage", | ||
readingAbout: "general.readingAbout", | ||
moving: "minecraft wiki.moving", | ||
viewSourceOf: "minecraft wiki.viewSourceOf", | ||
viewHistory: "minecraft wiki.viewHistory", | ||
changeProtection: "minecraft wiki.changeProtection", | ||
viewProtection: "minecraft wiki.viewProtection", | ||
search: "general.search", | ||
upload: "youtube.upload", | ||
viewContributionsOf: "minecraft wiki.viewContributionsOf", | ||
viewRecentChanges: "minecraft wiki.viewRecentChanges", | ||
login: "kahoot.login", | ||
btnViewThread: "apple.btnViewThread", | ||
viewWatchlist: "minecraft wiki.viewWatchlist", | ||
}), | ||
mainPath = pathname.split("/").filter(Boolean)[1] ?? "/", | ||
pageTitle = document.querySelector<HTMLMetaElement>( | ||
"meta[property='og:title']" | ||
)?.content, | ||
specialNamespace = new URL( | ||
document.querySelector<HTMLAnchorElement>("#t-specialpages a").href | ||
).pathname | ||
.split("/") | ||
.filter(Boolean)[1] | ||
.match(/.*(?=:[^_])/)?.[0], | ||
userNamespace = await getUserNamespace(), | ||
talkNamespace = await getTalkNamespace(), | ||
currentNamespace = mainPath.match(/.*(?=:[^_])/)?.[0] ?? ""; | ||
|
||
presenceData.largeImageKey = getComputedStyle( | ||
document.querySelector<HTMLAnchorElement>(".mw-wiki-logo") | ||
).backgroundImage.match(/url\("(.+)"\)/)[1]; | ||
|
||
if ( | ||
searchParams.get("action") === "edit" || | ||
searchParams.get("veaction") === "edit" | ||
) { | ||
presenceData.details = hasPermissions() | ||
? strings.editing | ||
: strings.viewSourceOf; | ||
presenceData.state = pageTitle; | ||
} else if (searchParams.get("action") === "history") { | ||
presenceData.details = strings.viewHistory; | ||
presenceData.state = pageTitle; | ||
} else if ( | ||
searchParams.get("action") === "protect" || | ||
searchParams.get("action") === "unprotect" | ||
) { | ||
presenceData.details = hasPermissions() | ||
? strings.changeProtection | ||
: strings.viewProtection; | ||
presenceData.state = pageTitle; | ||
} else if (searchParams.get("search")) { | ||
presenceData.details = strings.search; | ||
presenceData.state = searchParams.get("search"); | ||
} else if (mainPath === "/") presenceData.details = strings.viewHome; | ||
else if (currentNamespace === userNamespace) { | ||
presenceData.details = strings.viewUser; | ||
presenceData.state = pageTitle.slice( | ||
decodeURIComponent(userNamespace).length + 1 | ||
); | ||
presenceData.buttons = [{ label: strings.buttonViewProfile, url: href }]; | ||
} else if ( | ||
currentNamespace.toLowerCase().includes(talkNamespace.toLowerCase()) | ||
) { | ||
presenceData.details = strings.viewAThread; | ||
presenceData.state = | ||
currentNamespace === talkNamespace | ||
? document.querySelector<HTMLSpanElement>(".mw-page-title-main") | ||
: pageTitle; | ||
presenceData.buttons = [{ label: strings.btnViewThread, url: href }]; | ||
} else if (currentNamespace === specialNamespace) { | ||
if (document.querySelector<HTMLFormElement>("#mw-prefs-form")) | ||
// Preferences (Special:Preferences) | ||
presenceData.details = strings.advancedSettings; | ||
else if (document.querySelector<HTMLFormElement>("#mw-watchlist-form")) | ||
// Subscriptions (Special:Watchlist) | ||
presenceData.details = strings.viewWatchlist; | ||
else if (document.querySelector<HTMLUListElement>(".mw-rcfilters-head")) { | ||
// Recent changes (Special:RecentChanges, Special:RecentChangesLinked) | ||
presenceData.details = strings.viewRecentChanges; | ||
presenceData.state = document.querySelector<HTMLAnchorElement>( | ||
"#mw-content-subtitle a" | ||
); | ||
} else if (document.querySelector<HTMLFormElement>("#movepage")) { | ||
// Moving a page (Special:MovePage) | ||
presenceData.details = strings.moving; | ||
presenceData.state = document.querySelector<HTMLAnchorElement>( | ||
"#mw-content-subtitle a" | ||
); | ||
} else if (document.querySelector<HTMLDivElement>("#userloginForm")) | ||
// Logging in (Special:UserLogin, Special:CreateAccount) | ||
presenceData.details = strings.login; | ||
else if (document.querySelector<HTMLFormElement>("#mw-upload-form")) | ||
// Upload a file (Special:Upload) | ||
presenceData.details = strings.upload; | ||
else if ( | ||
document.querySelector<HTMLDivElement>(".mw-contributions-user-tools") | ||
) { | ||
// Contributions (Special:Contributions) | ||
presenceData.details = strings.viewContributionsOf; | ||
presenceData.state = pageTitle.split("/").slice(1).join("/"); | ||
} else { | ||
presenceData.details = strings.viewAPage; | ||
presenceData.state = pageTitle; | ||
} | ||
} else if (currentNamespace) { | ||
const namespace = decodeURIComponent(currentNamespace); | ||
presenceData.details = `${strings.readingAbout} ${namespace}`; | ||
presenceData.state = pageTitle.slice(namespace.length + 1); | ||
presenceData.buttons = [{ label: strings.buttonViewPage, url: href }]; | ||
} else { | ||
presenceData.details = strings.viewAPage; | ||
presenceData.state = pageTitle; | ||
presenceData.buttons = [{ label: strings.buttonViewPage, url: href }]; | ||
} | ||
|
||
presence.setActivity(presenceData); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
const promiseCache = new Map<string, Promise<Response>>(); | ||
|
||
export async function getUserNamespace(): Promise<string> { | ||
const cached = sessionStorage.getItem("PMD_UserNamespace"); | ||
if (cached) return cached; | ||
let response: Response; | ||
const promise = promiseCache.get("getUserNamespace"); | ||
if (promise) response = await promise; | ||
else { | ||
const promise = fetch( | ||
`https://${document.location.hostname}/w/User:Example` | ||
); | ||
promiseCache.set("getUserNamespace", promise); | ||
response = await promise; | ||
} | ||
sessionStorage.setItem( | ||
"PMD_UserNamespace", | ||
new URL(response.url).pathname.split("/").filter(Boolean)[1].split(":")[0] | ||
); | ||
return sessionStorage.getItem("PMD_UserNamespace"); | ||
} | ||
|
||
export async function getTalkNamespace(): Promise<string> { | ||
const cached = sessionStorage.getItem("PMD_TalkNamespace"); | ||
if (cached) return cached; | ||
let response: Response; | ||
const promise = promiseCache.get("getTalkNamespace"); | ||
if (promise) response = await promise; | ||
else { | ||
const promise = fetch( | ||
`https://${document.location.hostname}/w/Talk:Example` | ||
); | ||
promiseCache.set("getTalkNamespace", promise); | ||
response = await promise; | ||
} | ||
sessionStorage.setItem( | ||
"PMD_TalkNamespace", | ||
new URL(response.url).pathname.split("/").filter(Boolean)[1].split(":")[0] | ||
); | ||
return sessionStorage.getItem("PMD_TalkNamespace"); | ||
} |