diff --git a/.env.example b/.env.example index 4696477..3da6734 100644 --- a/.env.example +++ b/.env.example @@ -4,5 +4,11 @@ GITHUB_USERNAME=name GITHUB_TOKEN=token with public repo access BASE_URL=https://name.io/ CACHE_DURATION=10 +CACHE_DURATION_CURRENT=1 IGNORED_REPOS=["name","name.github.io"] -PUBLIC_BIRTHDAY=YYYY-MM-DD \ No newline at end of file +PUBLIC_BIRTHDAY=YYYY-MM-DD +TRAEWELLING_USERNAME=name +STEAM_USERID=12345678901234567 +STEAM_TOKEN=token +TRAKT_CLIENT_ID=client_id +TRAKT_USERNAME=name \ No newline at end of file diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 3ccf435..0000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = { - root: true, - parser: '@typescript-eslint/parser', - extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], - plugins: ['svelte3', '@typescript-eslint'], - ignorePatterns: ['*.cjs'], - overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], - settings: { - 'svelte3/typescript': () => require('typescript') - }, - parserOptions: { - sourceType: 'module', - ecmaVersion: 2020 - }, - env: { - browser: true, - es2017: true, - node: true - } -}; diff --git a/.github/workflows/checker.yml b/.github/workflows/checker.yml index cc25b94..aceb050 100644 --- a/.github/workflows/checker.yml +++ b/.github/workflows/checker.yml @@ -14,9 +14,9 @@ jobs: - name: Setup Node.js environment uses: actions/setup-node@v3.0.0 with: - node-version: '19' + node-version: '18' - name: Install dependencies - run: npm install --global pnpm && pnpm install --frozen-lockfile + run: npm ci - name: Run the formatter run: npm run format - name: Run the linter diff --git a/.vscode/settings.json b/.vscode/settings.json index 73e3d15..7e41e97 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -28,7 +28,7 @@ ], "explorer.fileNesting.enabled": true, "explorer.fileNesting.patterns": { - "package.json": "package-lock.json, .npmrc, yarn.lock, .yarnrc, playwright.config.ts, pnpm-lock.yaml, .eslintrc.cjs, .prettierrc, postcss.config.cjs, svelte.config.js, tailwind.config.cjs, tsconfig.json, vite.config.js", + "package.json": "package-lock.json, .npmrc, yarn.lock, .yarnrc, playwright.config.ts, pnpm-lock.yaml, eslint.config.cjs, .prettierrc, postcss.config.cjs, svelte.config.js, tailwind.config.cjs, tsconfig.json, vite.config.js", "Dockerfile": ".dockerignore, docker_start.sh, docker-compose.yml", "*.html": "$(capture).css, $(capture).d.ts, $(capture).ts, $(capture).js", ".gitignore": ".gitmodules", diff --git a/README.md b/README.md index b8a760e..4862b31 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ - Auto generated GitHub event log - Auto generated OpenStreepMap event log +- Indicator for current activity on Träwelling, Steam and Trakt - Easy to use contact options - i18n support - Dark and light mode support diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..4546325 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,61 @@ +import typescriptEslint from '@typescript-eslint/eslint-plugin'; +import globals from 'globals'; +import tsParser from '@typescript-eslint/parser'; +import parser from 'svelte-eslint-parser'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import js from '@eslint/js'; +import { FlatCompat } from '@eslint/eslintrc'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all +}); + +export default [ + { + ignores: ['*.mjs', '*.cjs'] + }, + ...compat.extends( + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:svelte/recommended', + 'prettier' + ), + { + plugins: { + '@typescript-eslint': typescriptEslint + }, + + languageOptions: { + globals: { + ...globals.browser, + ...globals.node + }, + + parser: tsParser, + ecmaVersion: 2020, + sourceType: 'module', + + parserOptions: { + extraFileExtensions: ['.svelte'] + } + } + }, + { + files: ['**/*.svelte'], + + languageOptions: { + parser: parser, + ecmaVersion: 5, + sourceType: 'script', + + parserOptions: { + parser: '@typescript-eslint/parser' + } + } + } +]; diff --git a/package-lock.json b/package-lock.json index 01bc38b..c44f447 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,13 +25,13 @@ "@sveltejs/adapter-node": "^5.2.9", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0", - "@types/eslint": "^9.6.0", + "@types/eslint": "^9.6.1", "@types/luxon": "^3.4.2", "@types/papaparse": "^5.3.15", "autoprefixer": "^10.4.20", - "eslint": "^9.7.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-svelte": "^2.36.0", + "eslint": "^9.18.0", + "eslint-config-prettier": "^10.0.1", + "eslint-plugin-svelte": "^2.46.1", "globals": "^15.0.0", "postcss": "^8.4.49", "postcss-import": "^16.1.0", @@ -46,7 +46,7 @@ "tailwindcss": "^3.4.9", "tailwindcss-global-dark": "^1.0.1", "typescript": "^5.0.0", - "typescript-eslint": "^8.0.0", + "typescript-eslint": "^8.20.0", "vite": "^5.0.3" } }, @@ -581,13 +581,13 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", - "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", + "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.4", + "@eslint/object-schema": "^2.1.5", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -596,19 +596,22 @@ } }, "node_modules/@eslint/core": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", - "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", + "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, "license": "MIT", "dependencies": { @@ -643,9 +646,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", - "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", + "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", "dev": true, "license": "MIT", "engines": { @@ -653,9 +656,9 @@ } }, "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", + "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -663,12 +666,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.2.tgz", - "integrity": "sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", + "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", "dev": true, "license": "Apache-2.0", "dependencies": { + "@eslint/core": "^0.10.0", "levn": "^0.4.1" }, "engines": { @@ -1855,21 +1859,21 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.14.0.tgz", - "integrity": "sha512-tqp8H7UWFaZj0yNO6bycd5YjMwxa6wIHOLZvWPkidwbgLCsBMetQoGj7DPuAlWa2yGO3H48xmPwjhsSPPCGU5w==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.20.0.tgz", + "integrity": "sha512-naduuphVw5StFfqp4Gq4WhIBE2gN1GEmMUExpJYknZJdRnc+2gDzB8Z3+5+/Kv33hPQRDGzQO/0opHE72lZZ6A==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.14.0", - "@typescript-eslint/type-utils": "8.14.0", - "@typescript-eslint/utils": "8.14.0", - "@typescript-eslint/visitor-keys": "8.14.0", + "@typescript-eslint/scope-manager": "8.20.0", + "@typescript-eslint/type-utils": "8.20.0", + "@typescript-eslint/utils": "8.20.0", + "@typescript-eslint/visitor-keys": "8.20.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1880,25 +1884,21 @@ }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.14.0.tgz", - "integrity": "sha512-2p82Yn9juUJq0XynBXtFCyrBDb6/dJombnz6vbo6mgQEtWHfvHbQuEa9kAOVIt1c9YFwi7H6WxtPj1kg+80+RA==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.20.0.tgz", + "integrity": "sha512-gKXG7A5HMyjDIedBi6bUrDcun8GIjnI8qOwVLiY3rx6T/sHP/19XLJOnIq/FgQvWLHja5JN/LSE7eklNBr612g==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.14.0", - "@typescript-eslint/types": "8.14.0", - "@typescript-eslint/typescript-estree": "8.14.0", - "@typescript-eslint/visitor-keys": "8.14.0", + "@typescript-eslint/scope-manager": "8.20.0", + "@typescript-eslint/types": "8.20.0", + "@typescript-eslint/typescript-estree": "8.20.0", + "@typescript-eslint/visitor-keys": "8.20.0", "debug": "^4.3.4" }, "engines": { @@ -1909,23 +1909,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.14.0.tgz", - "integrity": "sha512-aBbBrnW9ARIDn92Zbo7rguLnqQ/pOrUguVpbUwzOhkFg2npFDwTgPGqFqE0H5feXcOoJOfX3SxlJaKEVtq54dw==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.20.0.tgz", + "integrity": "sha512-J7+VkpeGzhOt3FeG1+SzhiMj9NzGD/M6KoGn9f4dbz3YzK9hvbhVTmLj/HiTp9DazIzJ8B4XcM80LrR9Dm1rJw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.14.0", - "@typescript-eslint/visitor-keys": "8.14.0" + "@typescript-eslint/types": "8.20.0", + "@typescript-eslint/visitor-keys": "8.20.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1936,16 +1932,16 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.14.0.tgz", - "integrity": "sha512-Xcz9qOtZuGusVOH5Uk07NGs39wrKkf3AxlkK79RBK6aJC1l03CobXjJbwBPSidetAOV+5rEVuiT1VSBUOAsanQ==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.20.0.tgz", + "integrity": "sha512-bPC+j71GGvA7rVNAHAtOjbVXbLN5PkwqMvy1cwGeaxUoRQXVuKCebRoLzm+IPW/NtFFpstn1ummSIasD5t60GA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.14.0", - "@typescript-eslint/utils": "8.14.0", + "@typescript-eslint/typescript-estree": "8.20.0", + "@typescript-eslint/utils": "8.20.0", "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1954,16 +1950,15 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.14.0.tgz", - "integrity": "sha512-yjeB9fnO/opvLJFAsPNYlKPnEM8+z4og09Pk504dkqonT02AyL5Z9SSqlE0XqezS93v6CXn49VHvB2G7XSsl0g==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.20.0.tgz", + "integrity": "sha512-cqaMiY72CkP+2xZRrFt3ExRBu0WmVitN/rYPZErA80mHjHx/Svgp8yfbzkJmDoQ/whcytOPO9/IZXnOc+wigRA==", "dev": true, "license": "MIT", "engines": { @@ -1975,20 +1970,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.14.0.tgz", - "integrity": "sha512-OPXPLYKGZi9XS/49rdaCbR5j/S14HazviBlUQFvSKz3npr3NikF+mrgK7CFVur6XEt95DZp/cmke9d5i3vtVnQ==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.20.0.tgz", + "integrity": "sha512-Y7ncuy78bJqHI35NwzWol8E0X7XkRVS4K4P4TCyzWkOJih5NDvtoRDW4Ba9YJJoB2igm9yXDdYI/+fkiiAxPzA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.14.0", - "@typescript-eslint/visitor-keys": "8.14.0", + "@typescript-eslint/types": "8.20.0", + "@typescript-eslint/visitor-keys": "8.20.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1997,10 +1992,8 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { @@ -2030,16 +2023,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.14.0.tgz", - "integrity": "sha512-OGqj6uB8THhrHj0Fk27DcHPojW7zKwKkPmHXHvQ58pLYp4hy8CSUdTKykKeh+5vFqTTVmjz0zCOOPKRovdsgHA==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.20.0.tgz", + "integrity": "sha512-dq70RUw6UK9ei7vxc4KQtBRk7qkHZv447OUZ6RPQMQl71I3NZxQJX/f32Smr+iqWrB02pHKn2yAdHBb0KNrRMA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.14.0", - "@typescript-eslint/types": "8.14.0", - "@typescript-eslint/typescript-estree": "8.14.0" + "@typescript-eslint/scope-manager": "8.20.0", + "@typescript-eslint/types": "8.20.0", + "@typescript-eslint/typescript-estree": "8.20.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2049,18 +2042,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.14.0.tgz", - "integrity": "sha512-vG0XZo8AdTH9OE6VFRwAZldNc7qtJ/6NLGWak+BtENuEUXGZgFpihILPiBvKXvJ2nFu27XNGC6rKiwuaoMbYzQ==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.20.0.tgz", + "integrity": "sha512-v/BpkeeYAsPkKCkR8BDwcno0llhzWVqPOamQrAEMdpZav2Y9OVjd9dwJyBLJWwf335B5DmlifECIkZRJCaGaHA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.14.0", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "8.20.0", + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2070,19 +2064,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -2517,9 +2498,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz", - "integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -2760,27 +2741,27 @@ } }, "node_modules/eslint": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", - "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz", + "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.7.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.14.0", - "@eslint/plugin-kit": "^0.2.0", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.10.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.18.0", + "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.0", + "@humanwhocodes/retry": "^0.4.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", @@ -2799,8 +2780,7 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" @@ -2837,22 +2817,22 @@ } }, "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.0.1.tgz", + "integrity": "sha512-lZBts941cyJyeaooiKxAtzoPHTN+GbQTJFAIdQbRhA4/8whaAraEh47Whw/ZFfrjNSnlAxqfm9i0XVAEkULjCw==", "dev": true, "license": "MIT", "bin": { - "eslint-config-prettier": "bin/cli.js" + "eslint-config-prettier": "build/bin/cli.js" }, "peerDependencies": { "eslint": ">=7.0.0" } }, "node_modules/eslint-plugin-svelte": { - "version": "2.46.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.46.0.tgz", - "integrity": "sha512-1A7iEMkzmCZ9/Iz+EAfOGYL8IoIG6zeKEq1SmpxGeM5SXmoQq+ZNnCpXFVJpsxPWYx8jIVGMerQMzX20cqUl0g==", + "version": "2.46.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.46.1.tgz", + "integrity": "sha512-7xYr2o4NID/f9OEYMqxsEQsCsj4KaMy4q5sANaKkAb6/QeCjYFxRmDm2S3YC3A3pl1kyPZ/syOx/i7LcWYSbIw==", "dev": true, "license": "MIT", "dependencies": { @@ -6166,13 +6146,6 @@ "node": ">=8.10.0" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT" - }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -6251,16 +6224,16 @@ } }, "node_modules/ts-api-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", - "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", + "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/ts-interface-checker": { @@ -6298,15 +6271,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.14.0.tgz", - "integrity": "sha512-K8fBJHxVL3kxMmwByvz8hNdBJ8a0YqKzKDX6jRlrjMuNXyd5T2V02HIq37+OiWXvUUOXgOOGiSSOh26Mh8pC3w==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.20.0.tgz", + "integrity": "sha512-Kxz2QRFsgbWj6Xcftlw3Dd154b3cEPFqQC+qMZrMypSijPd4UanKKvoKDrJ4o8AIfZFKAF+7sMaEIR8mTElozA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.14.0", - "@typescript-eslint/parser": "8.14.0", - "@typescript-eslint/utils": "8.14.0" + "@typescript-eslint/eslint-plugin": "8.20.0", + "@typescript-eslint/parser": "8.20.0", + "@typescript-eslint/utils": "8.20.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6315,10 +6288,9 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/undici-types": { diff --git a/package.json b/package.json index c826786..475388e 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,8 @@ "check": "svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch", "dev": "vite dev", - "format": "prettier --write --plugin-search-dir=. .", - "lint": "prettier --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .", + "format": "prettier --write .", + "lint": "prettier --check . && eslint .", "preview": "vite preview", "git": "npm ci && npx prisma migrate deploy && npx prisma generate" }, @@ -30,13 +30,13 @@ "@sveltejs/adapter-node": "^5.2.9", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0", - "@types/eslint": "^9.6.0", + "@types/eslint": "^9.6.1", "@types/luxon": "^3.4.2", "@types/papaparse": "^5.3.15", "autoprefixer": "^10.4.20", - "eslint": "^9.7.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-svelte": "^2.36.0", + "eslint": "^9.18.0", + "eslint-config-prettier": "^10.0.1", + "eslint-plugin-svelte": "^2.46.1", "globals": "^15.0.0", "postcss": "^8.4.49", "postcss-import": "^16.1.0", @@ -51,7 +51,7 @@ "tailwindcss": "^3.4.9", "tailwindcss-global-dark": "^1.0.1", "typescript": "^5.0.0", - "typescript-eslint": "^8.0.0", + "typescript-eslint": "^8.20.0", "vite": "^5.0.3" } } diff --git a/prisma/migrations/20250118015403_add_current_activity/migration.sql b/prisma/migrations/20250118015403_add_current_activity/migration.sql new file mode 100644 index 0000000..d5d96de --- /dev/null +++ b/prisma/migrations/20250118015403_add_current_activity/migration.sql @@ -0,0 +1,14 @@ +-- CreateTable +CREATE TABLE "CurrentActivity" ( + "id" SERIAL NOT NULL, + "title" TEXT NOT NULL, + "titleUrl" TEXT, + "subtitle" TEXT, + "image" TEXT, + "imageAlt" TEXT, + "imageRounded" BOOLEAN NOT NULL DEFAULT true, + "start" TIMESTAMP(3), + "end" TIMESTAMP(3), + + CONSTRAINT "CurrentActivity_pkey" PRIMARY KEY ("id") +); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 5d76251..0776e5b 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -99,3 +99,15 @@ model GithubRepo { updatedAt DateTime detailPage Boolean @default(false) } + +model CurrentActivity { + id Int @id @default(autoincrement()) + title String + titleUrl String? + subtitle String? + image String? + imageAlt String? + imageRounded Boolean @default(true) + start DateTime? + end DateTime? +} diff --git a/src/app.css b/src/app.css index 0d9212f..f40de80 100644 --- a/src/app.css +++ b/src/app.css @@ -2,4 +2,3 @@ @tailwind base; @tailwind components; @tailwind utilities; - diff --git a/src/app.html b/src/app.html index dcb2c0a..977c8b9 100644 --- a/src/app.html +++ b/src/app.html @@ -1,4 +1,4 @@ - +
diff --git a/src/lib/@types/steam.ts b/src/lib/@types/steam.ts new file mode 100644 index 0000000..fec8266 --- /dev/null +++ b/src/lib/@types/steam.ts @@ -0,0 +1,132 @@ +export interface PlayerSummaryAPIResponse { + response: { + players: PlayerSummary[]; + }; +} + +interface PlayerSummary { + /** + * 64-bit SteamID of the user + */ + steamid: string; + + communityvisibilitystate: number; + + profilestate: number; + + profileurl: string; + + avatar: string; + + avatarmedium: string; + + avatarfull: string; + + avatarhash: string; + + lastlogoff: number; + + /** + * User's display name + */ + realname: string; + + primaryclanid: string; + + timecreated: number; + + personastateflags: number; + + /** + * If in-game, the user's current game (if available) + */ + gameextrainfo?: string; + + /** + * If in-game, the user's current game's appid (if available) + */ + gameid?: string; + + /** + * User's country code (ISO 3166-1 alpha-2) + * Private information + */ + loccountrycode: string; + + /** + * User's state code, uses steam_location + * Private information + */ + locstatecode: string; + + /** + * User's city id, uses steam_location + * Private information + */ + loccityid: number; +} + +export interface OwnedGamesAPIResponse { + response: { + game_count: number; + games: OwnedGame[]; + }; +} + +export interface OwnedGame { + /** + * The game's appid + */ + appid: number; + + /** + * The game's name + */ + name: string; + + /** + * Total playtime of the game (in minutes) + */ + playtime_forever: number; + + /** + * Hash for the icon URL + * https://media.steampowered.com/steamcommunity/public/images/apps/{appid}/{hash}.jpg + */ + img_icon_url: string; + + has_community_visible_stats: boolean; + + /** + * Total playtime of the game (in minutes) on Windows + */ + playtime_windows_forever: number; + + /** + * Total playtime of the game (in minutes) on Mac + */ + playtime_mac_forever: number; + + /** + * Total playtime of the game (in minutes) on Linux, + * note that this obviously includes Steam Deck playtime + */ + playtime_linux_forever: number; + + /** + * Total playtime of the game (in minutes) on Steam Deck + * This is part of the playtime_linux_forever value + */ + playtime_deck_forever: number; + + /** + * Unix timestamp of the last time the user played the game (in seconds) + * Refers to the start of the last session, so can be used to calculate the duration so far + */ + rtime_last_played: number; + + /** + * Total playtime of the game (in minutes) while playing offline + */ + playtime_disconnected: number; +} diff --git a/src/lib/@types/traewelling.ts b/src/lib/@types/traewelling.ts new file mode 100644 index 0000000..8c0078c --- /dev/null +++ b/src/lib/@types/traewelling.ts @@ -0,0 +1,616 @@ +export interface StatusAPIResponse { + data: Status[]; + links: Links; + meta: PaginationMeta; +} + +interface Status { + /** + * @example 12345 + */ + id: number; + + /** + * @example "Hello world!" + */ + body: string; + + /** + * Mentions in the status body + */ + bodyMentions: Mention[]; + + /** + * @example 1 + */ + user: number; + + /** + * @example "Gertrud123" + */ + username: string; + + /** + * @example "https://traewelling.de/@Gertrud123/picture" + */ + profilePicture: string; + + /** + * @example false + */ + preventIndex: boolean; + + /** + * Business + * What type of travel (0 = private, 1 = business, 2 = commute) did the user specify? + * @example 0 + */ + business: 0 | 1 | 2; + + /** + * Visibility + * What type of visibility (0 = public, 1 = unlisted, 2 = followers, 3 = private, 4 = authenticated) did the user specify? + */ + visibility: 0 | 1 | 2 | 3 | 4; + + /** + * How many people have liked this status + * @example 12 + */ + likes: number; + + /** + * Did the currently authenticated user like this status? (if unauthenticated = false) + * @example true + */ + liked: boolean; + + /** + * Do the author of this status and the currently authenticated user allow liking of statuses? Only show the like UI if set to true. + * @example true + */ + isLikable: boolean; + + client: Client; + + /** + * Creation date of this status + * @example "2022-07-17T13:37:00+02:00" + */ + createdAt: string; + + train: TransportResource; + + event: Event | null; + + userDetails: LightUser; + + tags: StatusTagResource[]; +} + +/** + * Mentioned user and position in status body + */ +interface Mention { + user: User; + + /** + * Position + * @example 0 + */ + position: number; + + /** + * Length + * @example 4 + */ + length: number; +} + +/** + * User model + */ +interface User { + /** + * @example 12345 + */ + id: number; + + /** + * Display name of the user + * @example "Gertrud" + */ + displayName: string; + + /** + * Username of user + * @example "Gertrud123" + */ + username: string; + + /** + * @example "https://traewelling.de/@Gertrud123/picture" + */ + profilePicture: string; + + /** + * Distance travelled by train in meters + * @example 12345 + */ + trainDistance: number; + + /** + * Duration travelled by train in minutes + * @example 6 + */ + trainDuration: number; + + /** + * @example 300 + */ + points: number; + + /** + * @example "https://chaos.social/@traewelling" + */ + mastodonUrl: string | null; + + /** + * @example false + */ + privateProfile: boolean; + + /** + * Does this profile allow likes? + * Only offer the UI to like any status if this setting is set to true. + * If set to false, the likes API will return 403. + * @example true + */ + likes_enabled: boolean; + + /** + * Can the currently authenticated user see the statuses of this user? + * @example false + */ + userInvisibleToMe: boolean; + + /** + * Is this user muted by the currently authenticated user? + * @example false + */ + muted: boolean; + + /** + * Does the currently authenticated user follow this user? + * @example false + */ + following: boolean; + + /** + * Is there a currently pending follow request? + * @example false + */ + followPending: boolean; + + /** + * Is the user following you? + * @example false + */ + followedBy: boolean; + + /** + * Did the user choose to prevent search engines from indexing their profile? + * @example false + */ + preventIndex: boolean; +} + +interface Client { + /** + * @example 1 + */ + id: number; + + /** + * @example "Träwelling App" + */ + name: string; + + /** + * @example "https://traewelling.de/privacy-policy" + */ + privacyPolicyUrl: string; +} + +interface TransportResource { + /** + * @example 4711 + */ + trip: number; + + /** + * @example "1|1234|567" + */ + hafasId: string; + + /** + * Category of transport + * @example "suburban" + */ + category: + | 'nationalExpress' + | 'national' + | 'regionalExp' + | 'regional' + | 'suburban' + | 'bus' + | 'ferry' + | 'subway' + | 'tram' + | 'taxi' + | 'plane'; + + /** + * Internal number of the journey + * @example "4-a6s8-8" + */ + number: string; + + /** + * @example "S 1" + */ + lineName: string; + + /** + * @example "85639" + */ + journeyNumber: number; + + /** + * Distance in meters + * @example 10000 + */ + distance: number; + + /** + * @example 37 + */ + points: number; + + /** + * Duration in minutes + * @example 30 + */ + duration: number; + + /** + * @example "2022-07-17T13:37:00+02:00" + */ + manualDeparture: string | null; + + /** + * @example "2022-07-17T13:37:00+02:00" + */ + manualArrival: string | null; + + origin: StopoverResource; + + destination: StopoverResource; + + operator: OperatorResource; +} + +interface StopoverResource { + /** + * @example 12345 + */ + id: number; + + /** + * Name of the station + * @example "Karlsruhe Hbf" + */ + name: string; + + /** + * Identifier specified in 'Richtlinie 100' of the Deutsche Bahn + * @example "RK" + */ + rilIdentifier: string | null; + + /** + * IBNR identifier of Deutsche Bahn + * @example "8000191" + */ + evaIdentifier: string | null; + + /** + * Currently known arrival time. Equal to arrivalReal if known. Else equal to arrivalPlanned. + * @example "2022-07-17T13:37:00+02:00" + */ + arrival: string | null; + + /** + * Planned arrival according to timetable records + * @example "2022-07-17T13:37:00+02:00" + */ + arrivalPlanned: string | null; + + /** + * Real arrival according to live data + * @example "2022-07-17T13:37:00+02:00" + */ + arrivalReal: string | null; + + /** + * Planned arrival platform according to timetable records + * @example "5" + */ + arrivalPlatformPlanned: string | null; + + /** + * Real arrival platform according to live data + * @example "5 A-F" + */ + arrivalPlatformReal: string | null; + + /** + * Currently known departure time. Equal to departureReal if known. Else equal to departurePlanned. + * @example "2022-07-17T13:37:00+02:00" + */ + departure: string | null; + + /** + * Planned departure according to timetable records + * @example "2022-07-17T13:37:00+02:00" + */ + departurePlanned: string | null; + + /** + * Real departure according to live data + * @example "2022-07-17T13:37:00+02:00" + */ + departureReal: string | null; + + /** + * Planned departure platform according to timetable records + * @example "5" + */ + departurePlatformPlanned: string | null; + + /** + * Real departure platform according to live data + * @example "5 A-F" + */ + departurePlatformReal: string | null; + + /** + * @example "5 A-F" + */ + plaform: string | null; + + /** + * Is there a delay in the arrival time? + * @example false + */ + isArrivalDelayed: boolean; + + /** + * Is there a delay in the departure time? + * @example false + */ + isDepartureDelayed: boolean; + + /** + * Is this stopover cancelled? + * @example false + */ + cancelled: boolean; +} + +interface OperatorResource { + /** + * @example 1 + */ + id: number; + + /** + * @example "db-regio-ag-nord" + */ + identifier: string; + + /** + * @example "DB Regio AG Nord" + */ + name: string; +} + +interface Event { + /** + * @example 39 + */ + id: number; + + /** + * @example "9-Euro-Ticket" + */ + name: string; + + /** + * @example "9_euro_ticket" + */ + slug: string; + + /** + * @example "NeunEuroTicket" + */ + hashtag: string; + + /** + * @example "9-Euro-Ticket GmbH" + */ + host: string; + + /** + * @example "https://9-euro-ticket.de" + */ + url: string; + + /** + * @example "2022-01-02T00:00:00+00:00" + */ + begin: string; + + /** + * @example "2022-01-02T00:00:00+00:00" + */ + end: string; + + station: Station; +} + +interface Station { + /** + * @example 4711 + */ + id: number; + + /** + * @example "Karlsruhe Hbf" + */ + name: string; + + /** + * @example 48.991591 + */ + latitude: number; + + /** + * @example 8.400538 + */ + longitude: number; + + /** + * @example 8000191 + */ + ibnr: number; + + /** + * Identifier specified in 'Richtlinie 100' of the Deutsche Bahn + * @example "RK" + */ + rilIdentifier: string | null; +} + +interface LightUser { + /** + * @example 1 + */ + id: number; + + /** + * @example "Gertrud" + */ + displayName: string; + + /** + * @example "Gertrud123" + */ + username: string; + + /** + * @example "https://traewelling.de/@Gertrud123/picture" + */ + profilePicture: string; + + /** + * @example "https://chaos.social/@traewelling" + */ + mastodonUrl: string; + + /** + * @example false + */ + preventIndex: boolean; +} + +interface StatusTagResource { + /** + * @example "trwl:vehicle_number" + */ + key: string; + + /** + * @example "94 80 0450 921 D-AVG" + */ + value: string; + + /** + * @example 1 + */ + visibility: 0 | 1 | 2 | 3 | 4; +} + +/** + * Pagination links + */ +interface Links { + /** + * URL to the first page of this pagination + * @example "https://api.traewelling.de/api/v1/ENDPOINT?page=1" + */ + first: string | null; + + /** + * URL to the last page of this pagination (mostly null) + * @example "https://api.traewelling.de/api/v1/ENDPOINT?page=2" + */ + last: string | null; + + /** + * URL to the previous page of this pagination (mostly null) + * @example "https://api.traewelling.de/api/v1/ENDPOINT?page=1" + */ + prev: string | null; + + /** + * URL to the next page of this pagination (mostly null) + * @example "https://api.traewelling.de/api/v1/ENDPOINT?page=3" + */ + next: string | null; +} + +/** + * Pagination meta data + */ +interface PaginationMeta { + /** + * Currently displayed page in the pagination + * @example 2 + */ + current_page: number; + + /** + * The first element on this page is the nth element of the query + * @example 16 + */ + from: number; + + /** + * The path of this pagination + * @example "https://api.traewelling.de/api/v1/ENDPOINT" + */ + path: string; + + /** + * The amount of items per page in this pagination + * @example 15 + */ + per_page: number; + + /** + * The last element on this page is the nth element of the query + * @example 30 + */ + to: number; +} diff --git a/src/lib/@types/trakt.ts b/src/lib/@types/trakt.ts new file mode 100644 index 0000000..b09ab31 --- /dev/null +++ b/src/lib/@types/trakt.ts @@ -0,0 +1,40 @@ +export interface WatchingAPIResponse { + expires_at: string; + started_at: string; + action: string; + type: 'episode' | 'movie'; + episode?: { + season: number; + number: number; + title: string; + ids: { + trakt: number; + tvdb: unknown; + imdb: unknown; + tmdb: number; + tvrage: unknown; + }; + }; + show?: { + title: string; + year: number; + ids: { + trakt: number; + slug: string; + tvdb: number; + imdb: string; + tmdb: number; + tvrage: number; + }; + }; + movie?: { + title: string; + year: number; + ids: { + trakt: number; + slug: string; + imdb: string; + tmdb: number; + }; + }; +} diff --git a/src/lib/api/currentActivity/index.ts b/src/lib/api/currentActivity/index.ts new file mode 100644 index 0000000..ad4f70b --- /dev/null +++ b/src/lib/api/currentActivity/index.ts @@ -0,0 +1,59 @@ +import Traewelling from './traewelling'; +import Steam from './steam'; +import Trakt from './trakt'; +import type { RemoteI18nData } from '../helper'; +import type { CurrentActivity as CurrentActivityPrisma } from '@prisma/client'; +import { t } from '$lib/i18n'; + +/** + * Provider of activity items + */ +export default interface ActivitySource { + /** + * Unique identifier of the source + */ + id: string; + + /** + * Human readable name of the source + */ + name: string; + + getActivities(): Promise+ {formatSubtitle(activity.subtitle, activity.start.toString(), activity.end.toString())} +
+ {/snippet} +{Math.round(progress * 100)}%
+ + {/if} + + + + diff --git a/src/lib/i18n/en/activity.json b/src/lib/i18n/en/activity.json new file mode 100644 index 0000000..8fb63ad --- /dev/null +++ b/src/lib/i18n/en/activity.json @@ -0,0 +1,14 @@ +{ + "steam": { + "subtitle": "Playing for {durationReadable}, {{totalTime}} hours total" + }, + "traewelling": { + "subtitle": "{{line}} - 🚩 {{distance}}km - ⏱️ {durationReadable} - 🟠 {{points}}pts." + }, + "trakt": { + "subtitle": { + "movie": "🗓️{ {year}} - ⏱️ {timeLeft}", + "episode": "{{season}}x{{episode}} - 🗓️ {{year}} - ⏱️ {timeLeft} left" + } + } +} diff --git a/src/lib/i18n/index.ts b/src/lib/i18n/index.ts index 410ec37..c5cf758 100644 --- a/src/lib/i18n/index.ts +++ b/src/lib/i18n/index.ts @@ -27,6 +27,10 @@ const keys: key[] = [ key: 'OsmActivity', routes: ['/'] }, + { + key: 'activity', + routes: ['/api/activity'] + }, { key: 'projects', routes: ['/projects'] diff --git a/src/lib/i18n/nl/activity.json b/src/lib/i18n/nl/activity.json new file mode 100644 index 0000000..bc75a50 --- /dev/null +++ b/src/lib/i18n/nl/activity.json @@ -0,0 +1,14 @@ +{ + "steam": { + "subtitle": "Spelend voor {durationReadable}, {{totalTime}} uur in totaal" + }, + "traewelling": { + "subtitle": "{{line}} - 🚩 {{distance}}km - ⏱️ {durationReadable} - 🟠 {{points}}pt." + }, + "trakt": { + "subtitle": { + "movie": "🗓️ {{year}} - ⏱️ {timeLeft}", + "episode": "{{season}}x{{episode}} - 🗓️ {{year}} - ⏱️ {timeLeft} over" + } + } +} diff --git a/src/routes/[lang]/+page.svelte b/src/routes/[lang]/+page.svelte index cb61c29..30caef1 100644 --- a/src/routes/[lang]/+page.svelte +++ b/src/routes/[lang]/+page.svelte @@ -3,6 +3,7 @@ import Profile from '$lib/components/home/Profile.svelte'; import { t } from '$lib/i18n'; import { env } from '$env/dynamic/public'; + import ActivityLoader from '$lib/components/home/ActivityLoader.svelte';