Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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"
]
}
110 changes: 110 additions & 0 deletions websites/T/Typersguild/presence.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { ActivityType, 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',
}

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 = {
type: ActivityType.Playing,
name: 'Typing on Typersguild',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name field should just be the name of the activity. Actions like "typing on..." should be in the details field.
You can use the statusDisplayType field to change which string appears as the main one in Discord if you like

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the "typing on" action to the state. And updated the screenshots

statusDisplayType: StatusDisplayType.Details,
largeImageKey: ActivityAssets.Logo,
largeImageUrl: 'https://typersguild.com/books',
detailsUrl: 'https://typersguild.com/books',
startTimestamp: browsingTimestamp,
}

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

presenceData.details = bookName
presenceData.state = `by ${getBookAuthor()}`

break
}

case ContentType.Wiki:
presenceData.details = getBookName()
presenceData.state = 'Typing Wikipedia'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe remove the line between the break statements for readability

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, updated

break

case ContentType.Browsing:
presenceData.name = 'Browsing Typersguild'
presenceData.details = 'Typersguild'
presenceData.state = 'Books, Wikis, and more'

break
}

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