Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions websites/T/Typersguild/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"$schema": "https://schemas.premid.app/metadata/1.16",
"apiVersion": 1,
"author": {
"id": "620949166604156955",
"name": "heydathan"
},
"service": "Typersguild",
"description": {
"en": "Practice typing by retyping entire books. Improve your speed with 100+ classics and real-time WPM tracking"
},
"url": "typersguild.com",
"regExp": "^https?[:][/][/]([a-z0-9-]+[.])*typersguild[.]com[/]",
"version": "1.0.0",
"logo": "https://typersguild.com/android-chrome-512x512.png",
"thumbnail": "https://typersguild.com/books.webp",
"color": "#6366f1",
"category": "other",
"tags": [
"typing",
"books",
"learning",
"productivity",
"practice",
"speed",
"reading",
"education"
]
}
107 changes: 107 additions & 0 deletions websites/T/Typersguild/presence.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { StatusDisplayType } from 'premid'

const presence = new Presence({
clientId: '1459578800223420416',
})

const browsingTimestamp = Math.floor(Date.now() / 1000)

enum ActivityAssets {
Logo = 'https://typersguild.com/android-chrome-512x512.png',
}

enum ContentType {
Book = 'book',
Wiki = 'wiki',
Browsing = 'browsing',
}

enum ActivityStates {
Typing = 'Typing on Typersguild',
Browsing = 'Browsing',
}

function getBookName(): string {
const presenceName = document
.querySelector('[data-presence-book-name]')
?.getAttribute('data-presence-book-name')
?.trim()

return presenceName || 'a book'
}

function getBookAuthor(): string {
const authorName = document
.querySelector('[data-presence-book-author]')
?.getAttribute('data-presence-book-author')
?.trim()

return authorName || 'Unknown Author'
}

function getBookCover(): string | null {
const coverUrl = document
.querySelector('[data-presence-book-cover]')
?.getAttribute('data-presence-book-cover')
?.trim()

return coverUrl || null
}

function getContentType(path: string): ContentType {
if (/^\/books\/[^/]+\/chapter\/\d+/.test(path)) {
return ContentType.Book
}

if (/^\/my-books\/[^/]+\/chapter\/\d+/.test(path)) {
return ContentType.Book
}

if (/^\/wiki\/[^/]+\/[^/]+/.test(path)) {
return ContentType.Wiki
}

return ContentType.Browsing
}

presence.on('UpdateData', async () => {
const { pathname } = document.location
const contentType = getContentType(pathname)

const presenceData: PresenceData = {
statusDisplayType: StatusDisplayType.Name,
largeImageKey: ActivityAssets.Logo,
largeImageUrl: 'https://typersguild.com/books',
stateUrl: 'https://typersguild.com/books',
startTimestamp: browsingTimestamp,
}

switch (contentType) {
case ContentType.Book:
{ const bookCover = getBookCover()
if (bookCover)
presenceData.largeImageKey = bookCover

presenceData.name = getBookName()
presenceData.details = `by ${getBookAuthor()}`
presenceData.state = ActivityStates.Typing
break
}
case ContentType.Wiki:
presenceData.name = getBookName()
presenceData.details = 'Wikipedia'
presenceData.state = ActivityStates.Typing
break
case ContentType.Browsing:
presenceData.details = 'Books, Wikis, and more'
presenceData.state = ActivityStates.Browsing
break
}

if (presenceData.state) {
presence.setActivity(presenceData)
}
else {
presence.clearActivity()
}
})
Loading