From 1139cfd5f069c831891af30d481feb0be7d8216a Mon Sep 17 00:00:00 2001 From: Mathias Couraud Date: Sun, 12 Oct 2025 22:54:58 +0200 Subject: [PATCH] more extensions --- package-lock.json | 355 ------------------------------- source/app.js | 529 +++++++++++++++++++++++++++++++--------------- 2 files changed, 361 insertions(+), 523 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8973700..38bc4c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,7 +29,6 @@ "import-jsx": "^5.0.0", "ink-testing-library": "^3.0.0", "nodemon": "^3.1.10", - "npm-run-all": "^4.1.5", "prettier": "^2.8.7", "xo": "^0.53.1" }, @@ -5648,13 +5647,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true, - "license": "MIT" - }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -6056,15 +6048,6 @@ "dev": true, "license": "MIT" }, - "node_modules/memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", - "dev": true, - "engines": { - "node": ">= 0.10.0" - } - }, "node_modules/meow": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-11.0.0.tgz", @@ -6257,13 +6240,6 @@ "license": "MIT", "peer": true }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true, - "license": "MIT" - }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -6428,292 +6404,6 @@ "node": ">=0.10.0" } }, - "node_modules/npm-run-all": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", - "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "memorystream": "^0.3.1", - "minimatch": "^3.0.4", - "pidtree": "^0.3.0", - "read-pkg": "^3.0.0", - "shell-quote": "^1.6.1", - "string.prototype.padend": "^3.0.0" - }, - "bin": { - "npm-run-all": "bin/npm-run-all/index.js", - "run-p": "bin/run-p/index.js", - "run-s": "bin/run-s/index.js" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/npm-run-all/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-all/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-all/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/npm-run-all/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/npm-run-all/node_modules/cross-spawn": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", - "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", - "dev": true, - "license": "MIT", - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/npm-run-all/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/npm-run-all/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-all/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true, - "license": "ISC" - }, - "node_modules/npm-run-all/node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-all/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/npm-run-all/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "license": "MIT", - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-all/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-all/node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-all/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-all/node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-all/node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/npm-run-all/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/npm-run-all/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-all/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-all/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-all/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -7203,19 +6893,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pidtree": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", - "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", - "dev": true, - "license": "MIT", - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -8357,19 +8034,6 @@ "node": ">=8" } }, - "node_modules/shell-quote": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", - "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -8646,25 +8310,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.padend": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", - "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/string.prototype.repeat": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", diff --git a/source/app.js b/source/app.js index 96476c8..c23378b 100644 --- a/source/app.js +++ b/source/app.js @@ -3,192 +3,385 @@ import { Text, Box } from 'ink'; import fetch from 'node-fetch'; const locations = { - Nancy: { latitude: 48.6921, longitude: 6.1844 }, - Paris: { latitude: 48.8566, longitude: 2.3522 } + Nancy: { latitude: 48.6921, longitude: 6.1844 }, + Paris: { latitude: 48.8566, longitude: 2.3522 } +}; + +const INTER_ID = 6684; // SC Internacional team id +const PARIS_ID = 1045; // Paris FC team id + +const TASKTROVE_API = 'https://tasktrove.couraud.xyz/api/v1/tasks'; +const TASKTROVE_TOKEN = 'eyJhbGciOiJIUzI1NiIsImtpZCI6InYxIiwidHlwIjoiSldUIn0.eyJuYW1lIjoidGFza3Ryb3ZlIiwiaXNzIjoibWVtb3MiLCJzdWIiOiIzIiwiYXVkIjpbInVzZXIuYWNjZXNzLXRva2VuIl0sImlhdCI6MTc1OTk5MjI0N30.666jJ97j9a3d8c3a2a2a2a2a2a2a2a2a2a2a2a2a2a2'; // From your memo API + +const weatherCodeMap = { + 0: { desc: 'Ciel clair', color: 'yellow' }, + 1: { desc: 'Principalement clair', color: 'yellow' }, + 2: { desc: 'Partiellement nuageux', color: 'cyan' }, + 3: { desc: 'Couvert', color: 'gray' }, + 45: { desc: 'Brouillard', color: 'gray' }, + 48: { desc: 'Brouillard givrant', color: 'gray' }, + 51: { desc: 'Bruine légère', color: 'blue' }, + 53: { desc: 'Bruine modérée', color: 'blue' }, + 55: { desc: 'Bruine dense', color: 'blue' }, + 56: { desc: 'Bruine verglaçante légère', color: 'blue' }, + 57: { desc: 'Bruine verglaçante dense', color: 'blue' }, + 61: { desc: 'Pluie faible', color: 'blue' }, + 63: { desc: 'Pluie modérée', color: 'blue' }, + 65: { desc: 'Pluie forte', color: 'blue' }, + 66: { desc: 'Pluie verglaçante légère', color: 'blue' }, + 67: { desc: 'Pluie verglaçante forte', color: 'blue' }, + 71: { desc: 'Chute de neige légère', color: 'white' }, + 73: { desc: 'Chute de neige modérée', color: 'white' }, + 75: { desc: 'Chute de neige forte', color: 'white' }, + 77: { desc: 'Grains de neige', color: 'white' }, + 80: { desc: 'Averses de pluie faibles', color: 'blue' }, + 81: { desc: 'Averses de pluie modérées', color: 'blue' }, + 82: { desc: 'Averses de pluie violentes', color: 'blue' }, + 85: { desc: 'Averses de neige faibles', color: 'white' }, + 86: { desc: 'Averses de neige fortes', color: 'white' }, + 95: { desc: 'Orage', color: 'magenta' }, + 96: { desc: 'Orage avec faible grêle', color: 'magenta' }, + 99: { desc: 'Orage avec forte grêle', color: 'magenta' } }; function formatTime(date) { - return date.toLocaleTimeString('fr-FR', { hour12: false }); + return date.toLocaleTimeString('fr-FR', { hour12: false }); } function formatDate(date) { - return date.toLocaleDateString('fr-FR', { - weekday: 'long', - year: 'numeric', - month: 'long', - day: 'numeric' - }); + return date.toLocaleDateString('fr-FR', { + weekday: 'long', + year: 'numeric', + month: 'long', + day: 'numeric' + }); } function formatDateTimeUTC(utcString) { - const date = new Date(utcString); - return { - date: formatDate(date), - time: formatTime(date) - }; + const date = new Date(utcString); + return { + date: formatDate(date), + time: formatTime(date) + }; } async function fetchWeather(lat, lon) { - const url = `https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t_weather=true&temperature_unit=celsius&timezone=Europe/Paris`; - const response = await fetch(url); - const data = await response.json(); - return data.current_weather; + const url = `https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t_weather=true&temperature_unit=celsius&timezone=Europe/Paris`; + const response = await fetch(url); + const data = await response.json(); + return data.current_weather; } -const weatherCodeMap = { - 0: { desc: 'Ciel clair', color: 'yellow' }, - 1: { desc: 'Principalement clair', color: 'yellow' }, - 2: { desc: 'Partiellement nuageux', color: 'cyan' }, - 3: { desc: 'Couvert', color: 'gray' }, - 45: { desc: 'Brouillard', color: 'gray' }, - 48: { desc: 'Brouillard givrant', color: 'gray' }, - 51: { desc: 'Bruine légère', color: 'blue' }, - 53: { desc: 'Bruine modérée', color: 'blue' }, - 55: { desc: 'Bruine dense', color: 'blue' }, - 56: { desc: 'Bruine verglaçante légère', color: 'blue' }, - 57: { desc: 'Bruine verglaçante dense', color: 'blue' }, - 61: { desc: 'Pluie faible', color: 'blue' }, - 63: { desc: 'Pluie modérée', color: 'blue' }, - 65: { desc: 'Pluie forte', color: 'blue' }, - 66: { desc: 'Pluie verglaçante légère', color: 'blue' }, - 67: { desc: 'Pluie verglaçante forte', color: 'blue' }, - 71: { desc: 'Chute de neige légère', color: 'white' }, - 73: { desc: 'Chute de neige modérée', color: 'white' }, - 75: { desc: 'Chute de neige forte', color: 'white' }, - 77: { desc: 'Grains de neige', color: 'white' }, - 80: { desc: 'Averses de pluie faibles', color: 'blue' }, - 81: { desc: 'Averses de pluie modérées', color: 'blue' }, - 82: { desc: 'Averses de pluie violentes', color: 'blue' }, - 85: { desc: 'Averses de neige faibles', color: 'white' }, - 86: { desc: 'Averses de neige fortes', color: 'white' }, - 95: { desc: 'Orage', color: 'magenta' }, - 96: { desc: 'Orage avec faible grêle', color: 'magenta' }, - 99: { desc: 'Orage avec forte grêle', color: 'magenta' } +async function fetchScheduledMatches(teamId) { + const url = `https://api.football-data.org/v4/teams/${teamId}/matches?status=SCHEDULED`; + try { + const response = await fetch(url, { + headers: { "X-Auth-Token": "1535f68086e542528841b5e276f50b45" } + }); + const data = await response.json(); + if (!data.matches) return []; + return data.matches.map(match => { + let opponent, homeAway; + if (match.homeTeam.id === teamId) { + opponent = match.awayTeam.name; + homeAway = 'Home'; + } else if (match.awayTeam.id === teamId) { + opponent = match.homeTeam.name; + homeAway = 'Away'; + } else { + return null; + } + const { date, time } = formatDateTimeUTC(match.utcDate); + return { date, time, opponent, homeAway }; + }).filter(Boolean); + } catch { + return []; + } +} +function translateHomeAway(homeAway) { + if (homeAway === 'Home') return 'domicile'; + if (homeAway === 'Away') return 'extérieur'; + return homeAway; +} + +function renderWeather(location, weather) { + if (!weather) return {location}: Loading weather...; + + const weatherInfo = weatherCodeMap[weather.weathercode] || { desc: 'Unknown', color: 'white' }; + + return ( + + {location}: {weatherInfo.desc},{' '} + {weather.temperature}°C (Vent : {weather.windspeed} km/h) + + ); +} + +async function fetchDeviceInfo() { + const url = 'http://192.168.0.19:19837/device-info'; + const response = await fetch(url); + if (!response.ok) throw new Error('Erreur HTTP ' + response.status); + return response.json(); +} + +const LoadingBar = ({ percentage }) => { + const width = 30; + const filledWidth = Math.round((percentage / 100) * width); + const emptyWidth = width - filledWidth; + + return ( + + [ + {'='.repeat(filledWidth)} + {' '.repeat(emptyWidth)} + ] + {percentage}% + + ); }; -export default function App({ name = 'Mathias' }) { - const [now, setNow] = useState(new Date()); - const [weatherNancy, setWeatherNancy] = useState(null); - const [weatherParis, setWeatherParis] = useState(null); - - const [matchesInter, setMatchesInter] = useState(null); - const [matchesParis, setMatchesParis] = useState(null); - - const INTER_ID = 6684; // SC Internacional team id - const PARIS_ID = 1045; // Paris FC team id - - useEffect(() => { - const timer = setInterval(() => { - setNow(new Date()); - }, 1000); - - async function updateWeather() { - try { - const nancyData = await fetchWeather(locations.Nancy.latitude, locations.Nancy.longitude); - const parisData = await fetchWeather(locations.Paris.latitude, locations.Paris.longitude); - setWeatherNancy(nancyData); - setWeatherParis(parisData); - } catch (error) { - // gestion d'erreur météo - } - } - - async function fetchMatches(teamId, setMatches) { - try { - const response = await fetch( - `https://api.football-data.org/v4/teams/${teamId}/matches?status=SCHEDULED`, - { - headers: { "X-Auth-Token": "1535f68086e542528841b5e276f50b45" } // Remplace par ton token - } - ); - const data = await response.json(); - - const filtered = data.matches.map(match => { - let opponent, homeAway; - if (match.homeTeam.id === teamId) { - opponent = match.awayTeam.name; - homeAway = 'Home'; - } else if (match.awayTeam.id === teamId) { - opponent = match.homeTeam.name; - homeAway = 'Away'; - } else { - return null; - } - const { date, time } = formatDateTimeUTC(match.utcDate); - return { date, time, opponent, homeAway }; - }).filter(Boolean); - - setMatches(filtered); - } catch (error) { - setMatches([]); - } - } - - updateWeather(); - fetchMatches(INTER_ID, setMatchesInter); - fetchMatches(PARIS_ID, setMatchesParis); - - const weatherInterval = setInterval(updateWeather, 60000); - - return () => { - clearInterval(timer); - clearInterval(weatherInterval); - }; - }, []); - - const renderWeather = (location, weather) => { - if (!weather) return {location}: Loading weather...; - - const weatherInfo = weatherCodeMap[weather.weathercode] || { desc: 'Unknown', color: 'white' }; - - return ( - - {location}: {weatherInfo.desc},{' '} - {weather.temperature}°C (Vent : {weather.windspeed} km/h) - - ); - }; - - const translateHomeAway = (homeAway) => { - if (homeAway === 'Home') return 'domicile'; - if (homeAway === 'Away') return 'extérieur'; - return homeAway; - }; +function renderDeviceInfo(deviceInfo, deviceError) { + if (deviceError) { + return {deviceError}; + } + if (!deviceInfo) { + return Chargement des informations...; + } + const percentage = deviceInfo.percentage; + if (percentage == null) { + return Status : {deviceInfo.status || 'N/A'}; + } else { return ( - - - Hello, {name} ! - - {formatDate(now)} - {formatTime(now)} - {renderWeather('Nancy', weatherNancy)} - {renderWeather('Paris', weatherParis)} - - - Matches à venir de SC Internacional : - {!matchesInter && Chargement des matchs...} - {matchesInter && matchesInter.length === 0 && Aucun match trouvé.} - {matchesInter && matchesInter.slice(0, 2).map((m, i) => ( - - {m.date} {m.time} - SC Internacional vs {m.opponent} ({translateHomeAway(m.homeAway)}) - - ))} - - - - Matches à venir de Paris FC : - {!matchesParis && Chargement des matchs...} - {matchesParis && matchesParis.length === 0 && Aucun match trouvé.} - {matchesParis && matchesParis.slice(0, 2).map((m, i) => ( - - {m.date} {m.time} - Paris FC vs {m.opponent} ({translateHomeAway(m.homeAway)}) - - ))} - - - Press Ctrl+C to exit. - + + + Temps restant : {deviceInfo.remainingTime || 'N/A'} + Status : {deviceInfo.status || 'N/A'} + ); + } +} + +function formatMemoContent(markdownContent) { + if (!markdownContent) return ""; + return markdownContent.split('\n').map(line => { + const taskItemMatch = line.match(/^-\s*\[( |x|X)\]\s*/); + if (taskItemMatch) { + return '- ' + line.slice(taskItemMatch[0].length); + } + return line; + }).join('\n'); +} + +async function fetchLatestMemo() { + const url = "https://memos.couraud.xyz/api/v1/memos?page=1&perPage=1"; + try { + const response = await fetch(url, { + headers: { + Authorization: "Bearer eyJhbGciOiJIUzI1NiIsImtpZCI6InYxIiwidHlwIjoiSldUIn0.eyJuYW1lIjoiZ3JvY2VyaWVzIiwiaXNzIjoibWVtb3MiLCJzdWIiOiIyIiwiYXVkIjpbInVzZXIuYWNjZXNzLXRva2VuIl0sImlhdCI6MTc2MDI3NzQwMX0.H8m6LSaav7cuiQgt_rrzB7Fx4UM7Un11M2S0L5JJfPc" + } + }); + if (!response.ok) { + throw new Error(`HTTP error ${response.status}`); + } + const json = await response.json(); + + const memosArray = json.memos; + if (memosArray && memosArray.length > 0) { + return formatMemoContent(memosArray[0].content); + } + return "Aucune note trouvée."; + } catch (error) { + return `Erreur lors de la récupération de la note: ${error.message}`; + } +} + +// New function to fetch and render TaskTrove tasks +async function fetchTaskTroveTasks() { + try { + const response = await fetch(TASKTROVE_API, { + headers: { + Authorization: `Bearer ${TASKTROVE_TOKEN}` + } + }); + + if (!response.ok) return []; + + const data = await response.json(); + const tasks = data.tasks || []; + const today = new Date().toISOString().split('T')[0]; + + return tasks + .filter(task => { + if (task.completed) return false; + const isDueToday = task.dueDate === today; + const isP1 = task.priority === 1; + const isP2 = task.priority === 2; + return isDueToday || isP1 || isP2; + }) + .map(task => ({ + title: task.title, + priority: task.priority, + dueDate: task.dueDate + })); + + } catch (err) { + return []; + } +} + +function renderTaskTroveList(tasks) { + if (!tasks) { + return Chargement des tâches...; + } + + if (tasks.length === 0) { + return Aucune tâche à afficher.; + } + + return ( + + {tasks.map((task, index) => { + const color = task.priority === 1 ? 'red' : task.priority === 2 ? 'yellow' : 'white'; + return ( + + - {task.title} + + ); + })} + + ); +} + +export default function App({ name = 'Mathias' }) { + const [now, setNow] = useState(new Date()); + const [weatherNancy, setWeatherNancy] = useState(null); + const [weatherParis, setWeatherParis] = useState(null); + const [matchesInter, setMatchesInter] = useState(null); + const [matchesParis, setMatchesParis] = useState(null); + const [deviceInfo, setDeviceInfo] = useState(null); + const [deviceError, setDeviceError] = useState(null); + const [latestMemo, setLatestMemo] = useState("Chargement de la dernière note..."); + const [taskTroveTasks, setTaskTroveTasks] = useState(null); + + useEffect(() => { + const timer = setInterval(() => setNow(new Date()), 1000); + return () => clearInterval(timer); + }, []); + + async function updateWeatherData() { + try { + const [nancy, paris] = await Promise.all([ + fetchWeather(locations.Nancy.latitude, locations.Nancy.longitude), + fetchWeather(locations.Paris.latitude, locations.Paris.longitude) + ]); + setWeatherNancy(nancy); + setWeatherParis(paris); + } catch (err) {} + } + + async function updateMatchesData() { + try { + const [interMatches, parisMatches] = await Promise.all([ + fetchScheduledMatches(INTER_ID), + fetchScheduledMatches(PARIS_ID) + ]); + setMatchesInter(interMatches); + setMatchesParis(parisMatches); + } catch (err) {} + } + + async function updateDeviceInfo() { + try { + const data = await fetchDeviceInfo(); + setDeviceInfo(data); + setDeviceError(null); + } catch (err) { + setDeviceError("Impossible de récupérer les informations du device"); + setDeviceInfo(null); + } + } + + async function updateLatestMemo() { + const memo = await fetchLatestMemo(); + setLatestMemo(memo); + } + + async function updateTaskTroveTasks() { + const tasks = await fetchTaskTroveTasks(); + setTaskTroveTasks(tasks); + } + + useEffect(() => { + updateWeatherData(); + updateMatchesData(); + updateDeviceInfo(); + updateLatestMemo(); + updateTaskTroveTasks(); + + const weatherInterval = setInterval(updateWeatherData, 60000); + const deviceInterval = setInterval(updateDeviceInfo, 60000); + const memoInterval = setInterval(updateLatestMemo, 60000); + const taskTroveInterval = setInterval(updateTaskTroveTasks, 60000); + + return () => { + clearInterval(weatherInterval); + clearInterval(deviceInterval); + clearInterval(memoInterval); + clearInterval(taskTroveInterval); + }; + }, []); + + return ( + + Hello, {name} ! + {formatDate(now)} + {formatTime(now)} + + {renderWeather('Nancy', weatherNancy)} + {renderWeather('Paris', weatherParis)} + + + Matches à venir de SC Internacional : + {!matchesInter && Chargement des matchs...} + {matchesInter && matchesInter.length === 0 && Aucun match trouvé.} + {matchesInter && matchesInter.slice(0, 2).map((m, i) => ( + + {m.date} {m.time} - SC Internacional vs {m.opponent} ({translateHomeAway(m.homeAway)}) + + ))} + + + + Matches à venir de Paris FC : + {!matchesParis && Chargement des matchs...} + {matchesParis && matchesParis.length === 0 && Aucun match trouvé.} + {matchesParis && matchesParis.slice(0, 2).map((m, i) => ( + + {m.date} {m.time} - Paris FC vs {m.opponent} ({translateHomeAway(m.homeAway)}) + + ))} + + + + Informations du device : + {renderDeviceInfo(deviceInfo, deviceError)} + + + + Liste de courses + {latestMemo.split('\n').map((line, index) => ( + {line} + ))} + + + + To-Do List + {renderTaskTroveList(taskTroveTasks)} + + + Press Ctrl+C to exit. + + ); }