From 9c5084edcad258ddd21eba8ce393817d50206624 Mon Sep 17 00:00:00 2001 From: bakonpancakz Date: Sat, 23 May 2026 17:25:30 -0700 Subject: [PATCH] Initial Release --- .gitignore | 3 + LICENSE | 21 +++++ README.md | 53 +++++++++++++ extension.ts | 185 ++++++++++++++++++++++++++++++++++++++++++++ icon.png | Bin 0 -> 8818 bytes package-lock.json | 190 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 105 +++++++++++++++++++++++++ preview.jpg | Bin 0 -> 30470 bytes tsconfig.json | 14 ++++ 9 files changed, 571 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 extension.ts create mode 100644 icon.png create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 preview.jpg create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8d23896 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules +*.vsix +*.js \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6a5decc --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2026 bakonpancakz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..fb80372 --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ +# ⌚ `trackpad` +Visual Studio Code Extension that displays your current [Wakatime](https://wakatime.com/) and Lines of Code as your Discord Activity. So you can finally prove to all your friends that you are, in fact, a 10x dev. + +

+ +

yep thats my profile
+

+ +--- + +### 🚀 Setup +If you trust me, you can grab the compiled extension from the [Releases](/releases) tab. Or if you're rightfully paranoid (respect), you can install dependencies and build it yourself: + +```bash +npm install +npm run build +``` + +After installion search for `Trackpad` in your VS Code settings and paste in your Wakatime API key. +Otherwise, it'll always show **0s**, and everyone will think you're a *pleb*. + +*Note: This extension doesn't actually track anything so you'll still need the [Wakatime Extension](https://wakatime.com/vs-code)* + +*Double Note: Your Discord activity updates every five minutes in order to keep overhead low. If it's too slow, open the Command Palette and run `Trackpad: Refresh Discord Rich Presence`* + + +### 🔧 Configuration +You can customize the Discord Activity Details and State fields using simple templates: +```yaml +{workspace.name} : trackpad +{workspace.loc} : 1,234 +{wakatime.decimal} : 1.5 +{wakatime.digital} : 1:30 +{wakatime.seconds} : 5400 +{wakatime.text} : 1hr 30mins +``` +All configuration can be done in your VS Code settings UI or directly in settings.json. + +Heres the defaults in-case you lost them: +```json +"trackpad.activityDetails": "Project: {workspace.name}", +"trackpad.activityState": "{workspace.loc} LOC - {wakatime.text}", +``` + +--- + +### 💡 Bonus +If you also stan Teto, throw this in your settings.json: + +```json +"trackpad.overrideSmallText": "Science!", +"trackpad.overrideSmallIcon": "https://c.pancakz.net/images/teto_science.gif", +``` \ No newline at end of file diff --git a/extension.ts b/extension.ts new file mode 100644 index 0000000..ff9b355 --- /dev/null +++ b/extension.ts @@ -0,0 +1,185 @@ +import discord from "discord-rpc"; +import vscode from "vscode"; +import fs from "fs/promises"; +import path from "path"; + +type WakatimeTotal = { + decimal: string; // 1.23 + digital: string; // 1:23 + seconds: number; // 123.456 + text: string; // 1 hr 4 mins +} + +const + DISCORD_CLIENT_ID = "1323609388442849280", + DISCORD_RPC = new discord.Client({ transport: "ipc" }), + APP_CONFIG = vscode.workspace.getConfiguration("trackpad"), + APP_CACHE_LOC: Record = {}, + DEFAULT_WAKATIME_DATA: WakatimeTotal = { + "decimal": "0", + "digital": "0:00", + "seconds": 0.00, + "text": "0s", + } + +discord.register(DISCORD_CLIENT_ID) + +/** Calculate the Lines of Code for a Given Directory */ +async function directoryCountLOC( + rootDirectory: string, + allowedExtensions: Set, + ignoredDirectories: Set, +): Promise { + + // Scan Directory Recursively + let totalCount = 0 + async function checkDirectory(directory: string) { + const entries = await fs.readdir(directory, { withFileTypes: true }) + for await (const file of entries) { + const filepath = path.join(directory, file.name) + + // Sanity Checks + if (file.isSymbolicLink()) continue + if (file.isDirectory()) { + if (ignoredDirectories.has(file.name)) continue + await checkDirectory(filepath) + continue + } + if (!file.isFile()) continue + if (!allowedExtensions.has(path.extname(file.name))) continue + + // Use Cache if file was unmodified + const filestat = await fs.stat(filepath) + const cached = APP_CACHE_LOC[filepath] + if (cached && cached.modtime == filestat.mtimeMs) { + totalCount += cached.count + continue + } + + // Calculate LOC for Document + const lineCount = (await fs.readFile(filepath, "utf8")) + .replaceAll(/\/\*[\s\S]*?\*\//g, "") // Ignore Comments: Multiline + .split("\n") + .filter(l => l.length !== 0) // Ignore Empty Lines + .filter(l => !l.startsWith("#")) // Ignore Comments: Python + .filter(l => !l.startsWith("//")) // Ignore Comments: JavaScript + .filter(l => !l.startsWith("--")) // Ignore Comments: SQL + .filter(l => !l.startsWith("@REM")) // Ignore Comments: Batch + .length + + // Cache and Append Result + APP_CACHE_LOC[filepath] = { + modtime: filestat.mtimeMs, + count: lineCount, + } + totalCount += lineCount + } + } + + await checkDirectory(rootDirectory) + return totalCount +} + +/** Fetch Todays Cummulative Time from Wakatime API */ +async function wakatimeFetchSummary(apiKey?: string): Promise { + if (!apiKey) return DEFAULT_WAKATIME_DATA + try { + // Fetch Data from API + const today = new Date() + const range = `${today.getFullYear()}-${today.getMonth() + 1}-${today.getDate()}` + const response = await fetch( + `https://wakatime.com/api/v1/users/current/summaries?start=${range}&end=${range}`, { + headers: { + "Authorization": `Basic ${btoa(apiKey)}` + }, + }) + if (response.status >= 200 && response.status <= 299) { + // Parse Content + const data: any = await response.json() + return data?.cumulative_total ?? DEFAULT_WAKATIME_DATA + } else { + vscode.window.showErrorMessage(`Wakatime API Returned Status Code ${response.status}\n`) + return DEFAULT_WAKATIME_DATA + } + + } catch (err) { + // Fatal Network Error + vscode.window.showErrorMessage(`Wakatime Error: ${err}`) + return DEFAULT_WAKATIME_DATA + } +} + +/** Use Templates and Setup Discord Rich Presence */ +async function updateRPC() { + let activityDetails = "Idle" + let activityState: string | undefined + + const workspaceFolders = vscode.workspace.workspaceFolders + if (workspaceFolders && workspaceFolders.length > 0) { + + // Prepare Template Data + const workspaceName = vscode.workspace.name ?? path.basename(workspaceFolders[0].uri.fsPath) + let workspaceLOC = 0 + for await (const folder of workspaceFolders) { + workspaceLOC += await directoryCountLOC( + folder.uri.fsPath, + new Set(APP_CONFIG.get("allowedExtensions")), + new Set(APP_CONFIG.get("ignoredDirectories")), + ) + } + const wakatimeData = await wakatimeFetchSummary( + APP_CONFIG.get("wakatimeKey"), + ) + + // Apply Template + function useTemplate(givenText: string): string { + return givenText + .replaceAll("{workspace.name}", workspaceName) + .replaceAll("{workspace.loc}", workspaceLOC.toLocaleString()) + .replaceAll("{wakatime.decimal}", wakatimeData.decimal) + .replaceAll("{wakatime.digital}", wakatimeData.digital) + .replaceAll("{wakatime.seconds}", (wakatimeData.seconds | 0).toString()) + .replaceAll("{wakatime.text}", wakatimeData.text) + } + activityDetails = useTemplate(APP_CONFIG.get("activityDetails", "")) + activityState = useTemplate(APP_CONFIG.get("activityState", "")) + } + + // Update Activity + DISCORD_RPC.setActivity({ + details: activityDetails, + state: activityState, + largeImageKey: "vscode", + largeImageText: "Visual Studio Code", + smallImageKey: APP_CONFIG.get("overrideSmallIcon") || undefined, + smallImageText: APP_CONFIG.get("overrideSmallText") || undefined, + instance: false + }) +} + +/** Extension Entrypoints */ +export async function activate(context: vscode.ExtensionContext) { + + // Setup Discord Presence + DISCORD_RPC.login({ clientId: DISCORD_CLIENT_ID }).catch(error => { + vscode.window.showErrorMessage("Discord RPC Error: " + String(error)) + }) + DISCORD_RPC.on("ready", () => { + setInterval(updateRPC, 300_000) + updateRPC() + }) + + // Setup Extension + vscode.commands.registerCommand("trackpad.refresh", () => { + vscode.window.showInformationMessage("Refreshing Discord Rich Presence!") + updateRPC() + }) + context.subscriptions.push( + vscode.Disposable.from({ + dispose: () => DISCORD_RPC.destroy() + }) + ) +} +export async function deactivate() { + if (DISCORD_RPC) DISCORD_RPC.destroy() +} diff --git a/icon.png b/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ca493e736ef3f9b90d557ee7d2f5ffd9ea1eb7c7 GIT binary patch literal 8818 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 CU(GE5 literal 0 HcmV?d00001 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c8485b8 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,190 @@ +{ + "name": "trackpad", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "trackpad", + "version": "1.0.0", + "dependencies": { + "discord-rpc": "^4.0.1" + }, + "devDependencies": { + "@types/discord-rpc": "^4.0.8", + "@types/node": "^22.10.2", + "@types/vscode": "^1.96.0", + "typescript": "^5.9.3" + }, + "engines": { + "vscode": "^1.96.0" + } + }, + "node_modules/@types/discord-rpc": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/discord-rpc/-/discord-rpc-4.0.8.tgz", + "integrity": "sha512-1tZf217Natkj+TziNXRRLwNmdm5GNa1bnrQr8VWowquo/Su5hMjdhobj8URxW1COMk2da28XCU1ahsYCAlxirA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/events": "*" + } + }, + "node_modules/@types/events": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.3.tgz", + "integrity": "sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", + "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/vscode": { + "version": "1.96.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.96.0.tgz", + "integrity": "sha512-qvZbSZo+K4ZYmmDuaodMbAa67Pl6VDQzLKFka6rq+3WUTY4Kro7Bwoi0CuZLO/wema0ygcmpwow7zZfPJTs5jg==", + "dev": true, + "license": "MIT" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/discord-rpc": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/discord-rpc/-/discord-rpc-4.0.1.tgz", + "integrity": "sha512-HOvHpbq5STRZJjQIBzwoKnQ0jHplbEWFWlPDwXXKm/bILh4nzjcg7mNqll0UY7RsjFoaXA7e/oYb/4lvpda2zA==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.1", + "ws": "^7.3.1" + }, + "optionalDependencies": { + "register-scheme": "github:devsnek/node-register-scheme" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT", + "optional": true + }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "license": "MIT", + "optional": true + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/register-scheme": { + "version": "0.0.2", + "resolved": "git+ssh://git@github.com/devsnek/node-register-scheme.git#e7cc9a63a1f512565da44cb57316d9fb10750e17", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bindings": "^1.3.0", + "node-addon-api": "^1.3.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true, + "license": "MIT" + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..a91d7c8 --- /dev/null +++ b/package.json @@ -0,0 +1,105 @@ +{ + "name": "trackpad", + "displayName": "Discord Trackpad", + "description": "Showcase your Wakatime and Lines of Code on Discord", + "version": "1.0.0", + "main": "./extension.js", + "publisher": "bakonpancakz", + "icon": "icon.png", + "files": [ + "node_modules", + "extension.js", + "README.md", + "icon.png", + "LICENSE" + ], + "repository": { + "url": "https://github.com/bakonpancakz/trackpad" + }, + "scripts": { + "build": "npm install && npx tsc && npm prune --omit=dev && npx @vscode/vsce package" + }, + "engines": { + "vscode": "^1.96.0" + }, + "categories": [ + "Other" + ], + "activationEvents": [ + "onStartupFinished" + ], + "dependencies": { + "discord-rpc": "^4.0.1" + }, + "devDependencies": { + "@types/discord-rpc": "^4.0.8", + "@types/node": "^22.10.2", + "@types/vscode": "^1.96.0", + "typescript": "^5.9.3" + }, + "contributes": { + "configuration": { + "title": "Trackpad", + "properties": { + "trackpad.allowedExtensions": { + "description": "Allowed File Extensions for Line Counter", + "type": "array", + "uniqueItems": true, + "default": [ + ".js", + ".ts", + ".pug", + ".html", + ".css", + ".sql", + ".xml", + ".yml", + ".md", + ".go" + ] + }, + "trackpad.ignoredDirectories": { + "type": "array", + "description": "Ignored Directory Names for Line Counter", + "uniqueItems": true, + "default": [ + "node_modules", + ".git", + "dist", + "build", + "out" + ] + }, + "trackpad.activityDetails": { + "type": "string", + "description": "Activity Details (Upper) with template literal support", + "default": "Project: {workspace.name}" + }, + "trackpad.activityState": { + "type": "string", + "description": "Activity State (Lower) with template literal support", + "default": "{workspace.loc} LOC - {wakatime.text}" + }, + "trackpad.overrideSmallIcon": { + "type": "string", + "description": "Set Small Icon URL for Activity" + }, + "trackpad.overrideSmallText": { + "description": "Set Small Text for Activity", + "type": "string" + }, + "trackpad.wakatimeKey": { + "type": "string", + "description": "", + "ignoreSync": true + } + } + }, + "commands": [ + { + "command": "trackpad.refresh", + "title": "Trackpad: Refresh Discord Rich Presence" + } + ] + } +} \ No newline at end of file diff --git a/preview.jpg b/preview.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e4e1bb2ea6719c375828a1031c6f7cbb761f36f6 GIT binary patch literal 30470 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 JPxE``KLFAz^ZNh* literal 0 HcmV?d00001 diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..708a05a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "module": "Node16", + "target": "ES2022", + "lib": [ + "ES2022" + ], + "sourceMap": false, + "strict": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "noUnusedParameters": true, + } +} \ No newline at end of file