feat(plugins/steam): add plugin (#1400) [skip ci]
This commit is contained in:
20
.github/actions/spelling/allow.txt
vendored
20
.github/actions/spelling/allow.txt
vendored
@@ -1,11 +1,23 @@
|
|||||||
|
appid
|
||||||
|
apikey
|
||||||
|
apiname
|
||||||
|
appdetails
|
||||||
|
appids
|
||||||
|
appinfo
|
||||||
deno
|
deno
|
||||||
gpgarmor
|
gpgarmor
|
||||||
github
|
github
|
||||||
githubassets
|
githubassets
|
||||||
https
|
https
|
||||||
|
IPlayer
|
||||||
|
ISteam
|
||||||
leetcode
|
leetcode
|
||||||
|
Nie
|
||||||
npx
|
npx
|
||||||
|
personaname
|
||||||
pgn
|
pgn
|
||||||
|
playerstats
|
||||||
|
rtime
|
||||||
scm
|
scm
|
||||||
shas
|
shas
|
||||||
splatoon
|
splatoon
|
||||||
@@ -13,5 +25,13 @@ Splatnet
|
|||||||
ssh
|
ssh
|
||||||
statink
|
statink
|
||||||
STATINK
|
STATINK
|
||||||
|
steamcommunity
|
||||||
|
steamid
|
||||||
|
steamids
|
||||||
|
steampowered
|
||||||
|
timecreated
|
||||||
ubuntu
|
ubuntu
|
||||||
|
unlocktime
|
||||||
|
userid
|
||||||
yargsparser
|
yargsparser
|
||||||
|
webtoken
|
||||||
|
|||||||
1
.github/actions/spelling/excludes.txt
vendored
1
.github/actions/spelling/excludes.txt
vendored
@@ -55,3 +55,4 @@ ignore$
|
|||||||
^\Qsource/templates/terminal/partials/screenshot.ejs\E$
|
^\Qsource/templates/terminal/partials/screenshot.ejs\E$
|
||||||
^\Qtests/mocks/api/github/rest/emojis/get.mjs\E$
|
^\Qtests/mocks/api/github/rest/emojis/get.mjs\E$
|
||||||
^\Qtests/mocks/api/axios/get/lichess.mjs\E$
|
^\Qtests/mocks/api/axios/get/lichess.mjs\E$
|
||||||
|
^\Qtests/mocks/api/axios/get/steam.mjs\E$
|
||||||
BIN
.github/readme/imgs/plugin_steam_userid.png
vendored
Normal file
BIN
.github/readme/imgs/plugin_steam_userid.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
BIN
.github/readme/imgs/plugin_steam_webtoken.png
vendored
Normal file
BIN
.github/readme/imgs/plugin_steam_webtoken.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 221 KiB |
@@ -1035,6 +1035,104 @@
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
: null),
|
: null),
|
||||||
|
//Steam
|
||||||
|
...(set.plugins.enabled.steam
|
||||||
|
? ({
|
||||||
|
steam: {
|
||||||
|
sections: options["anilist.sections"].split(",").map(x => x.trim()).filter(x => x),
|
||||||
|
player: {
|
||||||
|
level: faker.datatype.number(100),
|
||||||
|
avatar: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mOcOnfpfwAGfgLYttYINwAAAABJRU5ErkJggg==",
|
||||||
|
created: 1366386002,
|
||||||
|
name: faker.internet.userName(),
|
||||||
|
},
|
||||||
|
games: {
|
||||||
|
count: 2,
|
||||||
|
playtime: 89.23333333333333,
|
||||||
|
achievements: 0,
|
||||||
|
"most-played": [
|
||||||
|
{
|
||||||
|
id: 524220,
|
||||||
|
name: "NieR:Automata™",
|
||||||
|
icon:
|
||||||
|
"data:image/jpg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCABAAEADASIAAhEBAxEB/8QAHAAAAgMBAQEBAAAAAAAAAAAABgcFCAkEAwEA/8QAMBAAAQMDAwEGBQQDAAAAAAAAAQIDBAAFEQYHITESExQiQVEjMkJhcQhSobEVgcH/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8ArPebk9cpIW+U8D0FcJUTj39q+Kxnjp6VN6N0zcdV3xi12lpTjzqgCoDIQPc0EKlZ6YJI6Yrvt1oudwIRAhPPqV+1NXb252F01pmHGfuDHjLoPMtazlGfbsmmoxZbXHwI9uhN4/aykH+qDNa5afvNsBE+3vsgj6k1EqKgeRhXTmtQXbTb3jh6BEcT7LZSo/yKXevNktKaqbkOGGIk5acNuMnsJSfwKCgXbUlWfqrpts12DLS8zgqB5yKJNydDXLQl9ct9xQe7J+G5jhQ9KEU/MMUH5XUZOR9qu1+l7Q8fS+jDfLk0lufLyVLWPlb6giqdaYgpueorfDI8rzoSRWhGpbZKe20MK15D6YiEoSnqSAKCMTuzZv8AMeFUy6Ifb7vx2fhAjqKYTD7chpDzCgttYCkqHQikM3fbEnbB6yqhpevThU34NKfi9vI82cUz9EKfs+lILd+eS24oAISRykY4BoC5RwCSQPzS9uu6tmgXZcRCHJEdo4elIPkb980R3iWLvZp8ayS21TO78uOopC27VtqsGjLzpm/2l1m8rU4UhxIKpBUrjBxQMHfPSkDX+3L8yEEPSmGy9GcQOSeOKoU60piQ404PM2opUPYjitDNl7XPg6Ebau6VBTqlLS2vqlB6CqQbsWtFn3AusZsdlJcLmPyTQRGkZibfqq2ynD5Wngo1ou5Pks6et8yE33iCyhS04z5SkVmecpWCnqORV7/0266Z1ZoliHJfQq5RPI40evYHAoCKdqvR0BwyViCLljPd9gBeag7rutF75pk2N98k+TBHP4rx3F2YiX68qvlqfVGuSQMIUSUEj7UAzdtNwo0pl+LLjPOtqzgNelAwY+58W3zA2rT8lhx35jkDipuJrLRV5mI8aICbik5Sh5sKXn84pSx9ttwrhOW7cJUdBUAAe66Ue6G2WhWq6ovF+f8AG3JGCgtkpQD9x60DMtEp+WHHFoCI2MN4GOKz73lnouW410eRyAstjHuCauzvNrGLonQ81/vEty3GyiMgcEqrPSXJXMmyJLxy68srJ+5OaDxX81EOhNWXHR1/YudsdUlTagVIB4UPYioi4wZEJ/upCCleM1yhJ59KC/8AtzvRpnV8NhLstuFcSACw6rlSvXFM5JT84UCFDg54rLZpx1hxLsdS2lJ6KScEf7ootm4OqbatCmLvJV2eneOFQ/ug0jzzyefzQDr3dfTOjWHRMnNPTUDiM2rzVR27bjaruR7Ui7SEk8ZbWU/9oXlyZEt0uS3nH3T9S1FR/mgLd0df3LXl9cmTVqEYKIaazwkenFBaeo9K+dk56V7w4zsqQGWkFS1dAKD/2Q==",
|
||||||
|
playtime: 44.88333333333333,
|
||||||
|
played: 1582407120,
|
||||||
|
description: "NieR: Automata tells the story of androids 2B, 9S and A2 and their battle to reclaim the machine-driven dystopia overrun by powerful machines.",
|
||||||
|
genres: [
|
||||||
|
"Action",
|
||||||
|
"RPG",
|
||||||
|
],
|
||||||
|
achievements: [
|
||||||
|
{
|
||||||
|
icon:
|
||||||
|
"data:image/jpg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAgACADASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAUGBwP/xAAmEAABAgQDCQAAAAAAAAAAAAABAAIDBAUGBxIUFiMxNVNhc5Gx/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAME/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8A6XVcM5QqlppTK+G4GJvSXEEngOyT7d1TpwPRRiVz5niH0qTWNVWbd1TpwPRTi1bhnK7UtNN5WQ2gRN0S0kg8D2Wdqsw158/xH6EBiVz5niH0qTWiXVb05XalqZTKyG0GHvQWkkHiOyT7CVTqQPZQSarMNefP8R+hGwlU6kD2U4tW3pyhVLUzeV8NwEPdAuIJPE9kH//Z",
|
||||||
|
achieved: true,
|
||||||
|
unlocked: 1565976624,
|
||||||
|
name: "Transcendent Being",
|
||||||
|
description: "",
|
||||||
|
id: "ACH_BAD_END",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon:
|
||||||
|
"data:image/jpg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAgACADASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAABQQDAAL/xAAtEAABAwMCBAQGAwAAAAAAAAABAgMEAAURBiISITFBExQjMlFhcYGRsRXB0f/EABcBAQEBAQAAAAAAAAAAAAAAAAABAwT/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwC3UF7lWeeY8bc2rLnqKJIJPT6VhE1BdpCgAhtORy2qJ/ArxqprxtRIB7IH7pixMJZfZWOQPEB+DXG1FSL/AHhj3soB64IINU6evMm8TvLytqEYX6aikkg9D8vlSmomEPcK8hWEYIznuaE0uz4N/cx3R/dQdqdt3+cDkfgUtLZ2LOAr4DPaqbOiDeZrcW4w5cd2Mkq3HiQVBW4Ajl7eX3OOlb3W2yLjMMiPxJSklO9JByDjP0q+2tzIiAlyO27j4k1QfdotvsD7zjEOa9Hkoy64yBhrh6de2P1U2mXmpN2W8wh5Dakjh8UYKh3OKcuKZUpspbitNkjBOT/tHWu3yLfN8xJClpWQnYkqIyeX2oP/2Q==",
|
||||||
|
achieved: true,
|
||||||
|
unlocked: 1565976316,
|
||||||
|
name: "A Round by the Pond",
|
||||||
|
description: "20 different kinds of fish caught.",
|
||||||
|
id: "ACH_FISHING",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
rate: {
|
||||||
|
total: 47,
|
||||||
|
achieved: 47,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"recently-played": [
|
||||||
|
{
|
||||||
|
id: 1113560,
|
||||||
|
name: "NieR Replicant ver.1.22474487139...",
|
||||||
|
icon:
|
||||||
|
"data:image/jpg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCABAAEADASIAAhEBAxEB/8QAHAAAAgIDAQEAAAAAAAAAAAAABgcDBQEECAIA/8QAMBAAAQMDAgUCBgEFAQAAAAAAAQIDBAAFERIhBhMxQVEHYRQiIzJCcRUIJFJigcH/xAAYAQADAQEAAAAAAAAAAAAAAAABAgMABP/EAB8RAAICAwACAwAAAAAAAAAAAAABAhEDEiEEQSIxYf/aAAwDAQACEQMRAD8A6m228CgT1PmN/DtMDd1s6z+jRfebg3abVJnSN2mEa1fqubeKOOBxNcBYoTwTcpaylxfX6Z+0DwaWT9FsMbezNluY5e3Jdpt0hoMqRh94jIx4HvV9ZbVHs0NMa3r5YTuvmb6vcV9Bsjdkt6GorJ0gfMvuVd81aWpUfWEqBKldSqpHV+lhHZCmNTbqSfyFYdjoQgKdSS0fzHQVOuGIriXUk8rqfet55DcVkTYg5jB+9pW9YWynjKkR5BcjFL7H+o3o1tPEbbiEtyxy1dM0K3S2amhMthUjI1AZ2J8YrUtt6DTyBcGg2UnAKhso0U6BKCmi09dLkm3cEvLdUUtuZSrfqKQ/oPbbchM6+SAVzHCUoKznAB2xTj/qVZMn08faQkqdVnTjzQF6dQmWOD4fKQOcjdxI/VNJ0LiXxDNy5FlvXo5jRPzHskeTUciNFmR0vwZCQ71Tg7ZoUeW6J5nWtZkxSdDzIOdGKEo/FlxmcQqZiwHmilWFJ7Y84qd2X1G1br4/8O7BeSEuDrqGc/qpLZc+RJMaUfpObJBPehlm6KU+0uc1yXBsVEdRUvEENu5RNKlrQtr6jC0Kxk1vsDjQfEKjRgw25g5K0at+teNUG5RXTIbCHEjC09/2KHrRc0XaAwlSyHUfTO++1ef5Q2+4FqajY7ax0Ioi6tBd6o2r+QjxtassqUQR2G1IK4sXPh65MXC3zELjh0pcjAbhI710h6gsvOWlHJISkElRPakTxE6yxqclIPwh+Vah296M+MGDsFZZw1CU4LjDQYsh0AOxldFjyBWxHgMc9UlLaQ6vZeBUMN2JCjMhb6dKkhSD3welbLMqDJePwMlLjgGVpT2qTtnSlqZlRfiHmFLwW0KyoeR4qJUpLbHORlbTSjgf+VsPvKDiUspKlDqmhuXJ+HYfLSgVJJOj/I+KMX6Fkm+klhuTFr4mXHQomPJwUgncKO5ovvqorrzSJK0pc/An8vakxeHC1Li3SM5qTHXrUQe/cVf8cX1f8FAfOdThyhwHocU9E2unQ/EUkXO3PvNqKYUdOvmdnD4pK8ZRFOfGW6WOWmUyChRGwB3FP3iRtL1qctkZCUuSRpAA2T7mgj1UtammLNISxzQkhp9SR9oCetPJeyGGdcOd/TG4G7zXbBc1KE2EsqjLUdl74A99qawZgWNouTHWoh/LVjKjSC9WZbNt4nactWuNNbOoqScZHagGVcrlOK3JEyS7k5IU4SKDx7O0Os+q1as6Ru/FYkkpgILLWcKWo/cPY0u+LuNmYrzTMJfMcZOsqB2UT2pdyOILm+xyVu4RpCfl2OKqMkryrJPcmtHHTthyeTaqKDnh3idtiW9FkkqgSDqyo50LO5/5RFd7wzcOCp0DX/cxAXU7/iemKUmQVbZx4qQOuDOHFZIwd+o8GncVdkFmdas//9k=",
|
||||||
|
playtime: 44.35,
|
||||||
|
played: 1625611102,
|
||||||
|
description: "The upgraded prequel of NieR:Automata. A kind young man sets out with Grimoire Weiss, a strange talking book, to search for the "Sealed verses" in order to save his sister Yonah, who fell terminally ill to the Black Scrawl.",
|
||||||
|
genres: [
|
||||||
|
"Action",
|
||||||
|
"Adventure",
|
||||||
|
"RPG",
|
||||||
|
],
|
||||||
|
achievements: [
|
||||||
|
{
|
||||||
|
icon:
|
||||||
|
"data:image/jpg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAgACADASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAwUGBAL/xAAsEAACAgEDAwMDAwUAAAAAAAABAgMEBQAGERIhMSJBUQdhkRMUoRVDUnGz/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/xAAYEQEBAQEBAAAAAAAAAAAAAAABACERMf/aAAwDAQACEQMRAD8AsL+R3Jkd+5LEYnIrSr1Yo2QGFGDcqpJLEE88t4+2rbA08hXQDJ5N70jEDkxIgX/XSBzoWMxpr5vK3XPa08ZUD2CoF/PY6lZs7uaDaW9LmTr16NnHGT9nJGvVwvSCOxPq4DDhu3f21fcJ5a89nb8eKwVqKZ68mTtCoqxlAFLu3Qx6lbn0qPHzrNHlM5S3thcdcumercezDIpVCrGOIOGUhVIIblSD8ffSjIY3LZPZGzYzXS3LjpoLd4GRY1SJULBT1Hu3Qy/Y9/GqLH4dpc7jrP8ASWoVcfLI9UGRWLCVGMh4UkKvUV4HnudXCk+x+XisZ3IYz+9VCNz8hlB/jn+dSP1ZuGrs/dNeM8SW3pRIB5P6pCH/AJnXGWo7mxu/psvhKAvU7CKsimRF6V4UMOGYEN6fPfzphujZ1rPSLPDk7UD8wSiKZ+tVkicsvt7Bm4+CffUOCMYONyd/IboyG344QsVXJdVtyhCrVijjWNAf8pGX8Bu3fVVdz9SvuOhhnk5u3EeQIO5CgE8n8HSXBbZtbeny08Vy1dSy5siL9YiWWXjv1sex5+dI8Bh9yZL6hRbg3Jj4aaVYmihCOpBUhgPDE8+s8nto8Zt//9k=",
|
||||||
|
achieved: true,
|
||||||
|
unlocked: 1625610706,
|
||||||
|
name: "e8 a8 98 e6 86 b6 e3 82 b5 e3 83 bc e3 83 90 e3 83 bc",
|
||||||
|
description: "",
|
||||||
|
id: "ACHIEVEMENT_0230",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon:
|
||||||
|
"data:image/jpg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAgACADASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAABgQFBwP/xAAsEAACAQQBAwIFBAMAAAAAAAABAgMEBQYRABIhMSJBBxMUUaEVIzJhUnGC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQAC/8QAGhEAAwEBAQEAAAAAAAAAAAAAAAERIUExMv/aAAwDAQACEQMRAD8AXZJe7vT5DVJLe1sVvR1hgeeCN4JGIH8pvV0MdghXC/0TxvY6S4UsJ/Urm9fIwBBMSIF/10gb5Gp7LG9wvclZFHPTXAorQyKHR0EYUgg+ffgDNbZk2BWSeuw27O1hh0Xt9SonajUt5iZgT0bIBU9wD7+z9Yi8HGaV60ENKTkMVmknf5MRljV1lc6+4Ovbv4G+/CtFeMnt3xHtljvVfFU09XHI5VIkA0EYqdgAhtr48a4dseE5ZltTb8lya4W2qi6FqKairY2eKRWXYUqmgi999tkHR0eaHHZK2qyS23m809ujq6cMiCjeR+gFWB6mYAMNHQAUd/f244sDWW1vu8VRfbhbN/vUoRt/cMoP43+eTLxQpdLPX2+TulVTyQn/AKUgfnXM9yCgyy3ZrV3fG6GOtiqIgvTI6BV9KgjTMp36B3/vifFbvks88aX/AB40miCZ4qiNl2D/AIhiRzM6hp0+Gc/1Hw7xqQb39BErb9mUdJ/IPJtZfqSmyKgszODW1aNIqDyFAJ2fsPSeVCxX+wYvFQ2e3U1wrIzN8tvniNEBlZkBDaJPSwHkDY88O4xaMpuWd02QZVb4KN6WBoUETp0nYYDQDMd+o8YnWV4f/9k=",
|
||||||
|
achieved: true,
|
||||||
|
unlocked: 1625607419,
|
||||||
|
name: "Daredevil",
|
||||||
|
description: "",
|
||||||
|
id: "ACHIEVEMENT_0460",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
rate: {
|
||||||
|
total: 47,
|
||||||
|
achieved: 44,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
: null),
|
||||||
//LeetCode
|
//LeetCode
|
||||||
...(set.plugins.enabled.leetcode
|
...(set.plugins.enabled.leetcode
|
||||||
? ({
|
? ({
|
||||||
|
|||||||
22
source/plugins/steam/README.md
Normal file
22
source/plugins/steam/README.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<!--header-->
|
||||||
|
<!--/header-->
|
||||||
|
|
||||||
|
## ➡️ Available options
|
||||||
|
|
||||||
|
<!--options-->
|
||||||
|
<!--/options-->
|
||||||
|
|
||||||
|
## 🗝️ Obtaining a *Steam Web API* token
|
||||||
|
|
||||||
|
Go to [steamcommunity.com/dev/apikey](https://steamcommunity.com/dev/apikey) to obtain a Steam Web API token:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
To retrieve your Steam ID, access your user account on [store.steampowered.com/account](https://store.steampowered.com/account) and copy the identifier located behind the header:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## ℹ️ Examples workflows
|
||||||
|
|
||||||
|
<!--examples-->
|
||||||
|
<!--/examples-->
|
||||||
31
source/plugins/steam/examples.yml
Normal file
31
source/plugins/steam/examples.yml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
- name: Recently played games
|
||||||
|
uses: lowlighter/metrics@latest
|
||||||
|
with:
|
||||||
|
filename: metrics.plugin.steam.svg
|
||||||
|
token: NOT_NEEDED
|
||||||
|
base: ""
|
||||||
|
plugin_steam_token: ${{ secrets.STEAM_TOKEN }}
|
||||||
|
plugin_steam: yes
|
||||||
|
plugin_steam_user: 0
|
||||||
|
plugin_steam_sections: recently-played
|
||||||
|
plugin_steam_achievements_limit: 0
|
||||||
|
prod:
|
||||||
|
# ⚠️ Using mocked data for privacy reasons
|
||||||
|
with:
|
||||||
|
plugin_steam_token: MOCKED_TOKEN
|
||||||
|
use_mocked_data: yes
|
||||||
|
|
||||||
|
- name: Profile and detailed game history
|
||||||
|
uses: lowlighter/metrics@latest
|
||||||
|
with:
|
||||||
|
filename: metrics.plugin.steam.full.svg
|
||||||
|
token: NOT_NEEDED
|
||||||
|
base: ""
|
||||||
|
plugin_steam_token: ${{ secrets.STEAM_TOKEN }}
|
||||||
|
plugin_steam: yes
|
||||||
|
plugin_steam_user: 0
|
||||||
|
prod:
|
||||||
|
# ⚠️ Using mocked data for privacy reasons
|
||||||
|
with:
|
||||||
|
plugin_steam_token: MOCKED_TOKEN
|
||||||
|
use_mocked_data: yes
|
||||||
104
source/plugins/steam/index.mjs
Normal file
104
source/plugins/steam/index.mjs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
//Setup
|
||||||
|
export default async function({login, q, imports, data, account}, {token, enabled = false, extras = false} = {}) {
|
||||||
|
//Plugin execution
|
||||||
|
try {
|
||||||
|
//Check if plugin is enabled and requirements are met
|
||||||
|
if ((!q.steam) || (!imports.metadata.plugins.steam.enabled(enabled, {extras})))
|
||||||
|
return null
|
||||||
|
|
||||||
|
//Load inputs
|
||||||
|
let {user, sections, "games.ignored": _games_ignored, "games.limit": _games_limit, "recent.games.limit": _recent_games_limit, "achievements.limit": _achievements_limit, "playtime.threshold": _playtime_threshold} = imports.metadata.plugins.steam.inputs({data, account, q})
|
||||||
|
|
||||||
|
const urls = {
|
||||||
|
games: {
|
||||||
|
owned: `https://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?key=${token}&steamid=${user}&format=json&include_appinfo=1`,
|
||||||
|
schema: `https://api.steampowered.com/ISteamUserStats/GetSchemaForGame/v0002/?key=${token}&format=json`,
|
||||||
|
details: "https://store.steampowered.com/api/appdetails?",
|
||||||
|
},
|
||||||
|
player: {
|
||||||
|
summary: `https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=${token}&steamids=${user}&format=json`,
|
||||||
|
level: `https://api.steampowered.com/IPlayerService/GetSteamLevel/v1/?key=${token}&steamid=${user}&format=json`,
|
||||||
|
achievement: `https://api.steampowered.com/ISteamUserStats/GetPlayerAchievements/v0001/?key=${token}&steamid=${user}&format=json&l=en`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const result = {sections, player: null, games: {count: 0, playtime: 0, achievements: 0}}
|
||||||
|
|
||||||
|
//Fetch owned games
|
||||||
|
console.debug(`metrics/compute/${login}/plugins > steam > fetching owned games`)
|
||||||
|
let {data: {response: {game_count: count, games}}} = await imports.axios.get(urls.games.owned)
|
||||||
|
result.games.count = count
|
||||||
|
result.games.playtime = games.reduce((total, {playtime_forever: playtime}) => (total += playtime), 0) / 60
|
||||||
|
|
||||||
|
//Fetch game achievements and order games by section
|
||||||
|
for (const section of ["most-played", "recently-played"]) {
|
||||||
|
if (!sections.includes(section))
|
||||||
|
continue
|
||||||
|
result.games[section] = await Promise.all(
|
||||||
|
games
|
||||||
|
.map(({appid: id, name, img_icon_url: icon, playtime_forever: playtime, rtime_last_played: played}) => ({id, name, icon: `http://media.steampowered.com/steamcommunity/public/images/apps/${id}/${icon}.jpg`, playtime: playtime / 60, played}))
|
||||||
|
.filter(({playtime}) => (playtime >= _playtime_threshold))
|
||||||
|
.filter(({id}) => (!_games_ignored.includes(`${id}`)))
|
||||||
|
.sort((a, b) => ({"most-played": (b.playtime - a.playtime), "recently-played": (b.played - a.played)}[section]))
|
||||||
|
.slice(0, ({"most-played": _games_limit, "recently-played": _recent_games_limit}[section]) || Infinity)
|
||||||
|
.map(async game => {
|
||||||
|
const schema = {}
|
||||||
|
try {
|
||||||
|
console.debug(`metrics/compute/${login}/plugins > steam > fetching schema for "${game.name}" (${game.id})`)
|
||||||
|
const {data: {game: {availableGameStats: {achievements = []} = {}}}} = await imports.axios.get(`${urls.games.schema}&appid=${game.id}`)
|
||||||
|
Object.assign(schema, Object.fromEntries(achievements.map(({name, icon}) => [name, {icon}])))
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.debug(`metrics/compute/${login}/plugins > steam > failed to get schema for "${game.name}" (${game.id}) > ${error}`)
|
||||||
|
}
|
||||||
|
const about = {}
|
||||||
|
try {
|
||||||
|
console.debug(`metrics/compute/${login}/plugins > steam > fetching details for "${game.name}" (${game.id})`)
|
||||||
|
const {data: {[game.id]: {data}}} = await imports.axios.get(`${urls.games.details}&appids=${game.id}`)
|
||||||
|
about.description = data.short_description ?? ""
|
||||||
|
about.genres = data.genres?.map(({description}) => description) ?? []
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.debug(`metrics/compute/${login}/plugins > steam > failed to get details for "${game.name}" (${game.id}) > ${error}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
let achievements = []
|
||||||
|
const rate = {total: Object.keys(schema).length, achieved: 0}
|
||||||
|
try {
|
||||||
|
console.debug(`metrics/compute/${login}/plugins > steam > fetching player achievements "${game.name}" (${game.id})`)
|
||||||
|
let {data: {playerstats: {achievements: list = []}}} = await imports.axios.get(`${urls.player.achievement}&appid=${game.id}`)
|
||||||
|
achievements = await Promise.all(list.map(async ({apiname: id, achieved, unlocktime: unlocked, name, description}) => ({icon: await imports.imgb64(schema[id]?.icon ?? null, {width: 32, height: 32}), achieved: !!achieved, unlocked, name, description, id})))
|
||||||
|
achievements = achievements.sort((a, b) => (b.unlocked - a.unlocked))
|
||||||
|
rate.achieved = achievements.filter(({achieved}) => achieved).length
|
||||||
|
achievements = achievements.slice(0, _achievements_limit)
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.debug(`metrics/compute/${login}/plugins > steam > failed to get player achievements for "${game.name}" (${game.id}) > ${error}`)
|
||||||
|
}
|
||||||
|
return {...game, ...about, icon: await imports.imgb64(game.icon, {width: 64, height: 64}), achievements, rate}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Fetch player info
|
||||||
|
if (sections.includes("player")) {
|
||||||
|
console.debug(`metrics/compute/${login}/plugins > steam > fetching profile info`)
|
||||||
|
let {data: {response: {players: [info]}}} = await imports.axios.get(urls.player.summary)
|
||||||
|
console.debug(`metrics/compute/${login}/plugins > steam > fetching profile level`)
|
||||||
|
const {data: {response: {player_level: level}}} = await imports.axios.get(urls.player.level)
|
||||||
|
result.player = {
|
||||||
|
level,
|
||||||
|
avatar: await imports.imgb64(info.avatar, {width: 64, height: 64}),
|
||||||
|
created: info.timecreated,
|
||||||
|
name: info.personaname,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Results
|
||||||
|
console.log(JSON.stringify(result))
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
//Handle errors
|
||||||
|
catch (error) {
|
||||||
|
throw imports.format.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
93
source/plugins/steam/metadata.yml
Normal file
93
source/plugins/steam/metadata.yml
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
name: 🕹️ Steam
|
||||||
|
category: social
|
||||||
|
description: |
|
||||||
|
This plugin can display your player profile and played games from your Steam account.
|
||||||
|
disclaimer: |
|
||||||
|
This plugin is not affiliated, associated, authorized, endorsed by, or in any way officially connected with [Steam](https://store.steampowered.com).
|
||||||
|
All product and company names are trademarks™ or registered® trademarks of their respective holders.
|
||||||
|
examples:
|
||||||
|
+Recently played games: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.steam.svg
|
||||||
|
Profile and detailed game history: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.steam.full.svg
|
||||||
|
supports:
|
||||||
|
- user
|
||||||
|
- organization
|
||||||
|
scopes: []
|
||||||
|
inputs:
|
||||||
|
|
||||||
|
plugin_steam:
|
||||||
|
description: |
|
||||||
|
Enable steam plugin
|
||||||
|
type: boolean
|
||||||
|
default: no
|
||||||
|
|
||||||
|
plugin_steam_token:
|
||||||
|
description: |
|
||||||
|
Steam token
|
||||||
|
type: token
|
||||||
|
default: ""
|
||||||
|
extras:
|
||||||
|
- metrics.api.steam
|
||||||
|
|
||||||
|
plugin_steam_sections:
|
||||||
|
description: |
|
||||||
|
Displayed sections
|
||||||
|
|
||||||
|
- `player`: display profile
|
||||||
|
- `most-played`: display most played games
|
||||||
|
- `recently-played`: display recently played games
|
||||||
|
type: array
|
||||||
|
format: comma-separated
|
||||||
|
default: player, most-played, recently-played
|
||||||
|
options:
|
||||||
|
- player
|
||||||
|
- most-played
|
||||||
|
- recently-played
|
||||||
|
|
||||||
|
plugin_steam_user:
|
||||||
|
description: |
|
||||||
|
Steam user id
|
||||||
|
|
||||||
|
This can be found on your Steam user account details
|
||||||
|
type: string
|
||||||
|
preset: no
|
||||||
|
|
||||||
|
plugin_steam_games_ignored:
|
||||||
|
description: |
|
||||||
|
Ignored games
|
||||||
|
|
||||||
|
Use App id as they are referenced in Steam catalog
|
||||||
|
type: array
|
||||||
|
format: comma-separated
|
||||||
|
default: ""
|
||||||
|
example: 400, 620
|
||||||
|
|
||||||
|
plugin_steam_games_limit:
|
||||||
|
description: |
|
||||||
|
Display limit (Most played games)
|
||||||
|
type: number
|
||||||
|
min: 0
|
||||||
|
zero: disable
|
||||||
|
default: 1
|
||||||
|
|
||||||
|
plugin_steam_recent_games_limit:
|
||||||
|
description: |
|
||||||
|
Display limit (Recently played games)
|
||||||
|
type: number
|
||||||
|
min: 0
|
||||||
|
zero: disable
|
||||||
|
default: 1
|
||||||
|
|
||||||
|
plugin_steam_achievements_limit:
|
||||||
|
description: |
|
||||||
|
Display limit (Games achievements)
|
||||||
|
type: number
|
||||||
|
min: 0
|
||||||
|
default: 2
|
||||||
|
|
||||||
|
plugin_steam_playtime_threshold:
|
||||||
|
description: |
|
||||||
|
Display threshold (Game playtime in hours)
|
||||||
|
type: number
|
||||||
|
min: 0
|
||||||
|
default: 2
|
||||||
|
|
||||||
3
source/templates/classic/partials/_.json
vendored
3
source/templates/classic/partials/_.json
vendored
@@ -42,5 +42,6 @@
|
|||||||
"sponsorships",
|
"sponsorships",
|
||||||
"poopmap",
|
"poopmap",
|
||||||
"fortune",
|
"fortune",
|
||||||
"splatoon"
|
"splatoon",
|
||||||
|
"steam"
|
||||||
]
|
]
|
||||||
|
|||||||
108
source/templates/classic/partials/steam.ejs
vendored
Normal file
108
source/templates/classic/partials/steam.ejs
vendored
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
<% if (plugins.steam) { %>
|
||||||
|
<section class="steam">
|
||||||
|
<h2 class="field">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M3.267 1.457c.3.286.312.76.026 1.06A6.475 6.475 0 001.5 7a6.472 6.472 0 001.793 4.483.75.75 0 01-1.086 1.034 8.89 8.89 0 01-.276-.304l.569-.49-.569.49A7.971 7.971 0 010 7c0-2.139.84-4.083 2.207-5.517a.75.75 0 011.06-.026zm9.466 0a.75.75 0 011.06.026A7.975 7.975 0 0116 7c0 2.139-.84 4.083-2.207 5.517a.75.75 0 11-1.086-1.034A6.475 6.475 0 0014.5 7a6.475 6.475 0 00-1.793-4.483.75.75 0 01.026-1.06zM8.75 8.582a1.75 1.75 0 10-1.5 0v5.668a.75.75 0 001.5 0V8.582zM5.331 4.736a.75.75 0 10-1.143-.972A4.983 4.983 0 003 7c0 1.227.443 2.352 1.177 3.222a.75.75 0 001.146-.967A3.483 3.483 0 014.5 7c0-.864.312-1.654.831-2.264zm6.492-.958a.75.75 0 00-1.146.967c.514.61.823 1.395.823 2.255 0 .86-.31 1.646-.823 2.255a.75.75 0 101.146.967A4.983 4.983 0 0013 7a4.983 4.983 0 00-1.177-3.222z"></path></svg>
|
||||||
|
Steam
|
||||||
|
</h2>
|
||||||
|
<% if (plugins.steam.error) { %>
|
||||||
|
<div class="row">
|
||||||
|
<section>
|
||||||
|
<div class="field error">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2.343 13.657A8 8 0 1113.657 2.343 8 8 0 012.343 13.657zM6.03 4.97a.75.75 0 00-1.06 1.06L6.94 8 4.97 9.97a.75.75 0 101.06 1.06L8 9.06l1.97 1.97a.75.75 0 101.06-1.06L9.06 8l1.97-1.97a.75.75 0 10-1.06-1.06L8 6.94 6.03 4.97z"></path></svg>
|
||||||
|
<%= plugins.steam.error.message %>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<% } else { %>
|
||||||
|
<% if ((plugins.steam.sections.includes("player"))&&(plugins.steam.player)) { %>
|
||||||
|
<div class="row">
|
||||||
|
<section>
|
||||||
|
<div class="field">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M10.561 8.073a6.005 6.005 0 0 1 3.432 5.142.75.75 0 1 1-1.498.07 4.5 4.5 0 0 0-8.99 0 .75.75 0 0 1-1.498-.07 6.004 6.004 0 0 1 3.431-5.142 3.999 3.999 0 1 1 5.123 0ZM10.5 5a2.5 2.5 0 1 0-5 0 2.5 2.5 0 0 0 5 0Z"></path></svg>
|
||||||
|
<%= plugins.steam.player.name %>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="m10.41.24 4.711 2.774c.544.316.878.897.879 1.526v5.01a1.77 1.77 0 0 1-.88 1.53l-7.753 4.521-.002.001a1.769 1.769 0 0 1-1.774 0H5.59L.873 12.85A1.761 1.761 0 0 1 0 11.327V6.292c0-.304.078-.598.22-.855l.004-.005.01-.019c.15-.262.369-.486.64-.643L8.641.239a1.752 1.752 0 0 1 1.765 0l.002.001ZM9.397 1.534l-7.17 4.182 4.116 2.388a.27.27 0 0 0 .269 0l7.152-4.148-4.115-2.422a.252.252 0 0 0-.252 0Zm-7.768 10.02 4.1 2.393V9.474a1.807 1.807 0 0 1-.138-.072L1.5 7.029v4.298c0 .095.05.181.129.227Zm8.6.642 1.521-.887v-4.45l-1.521.882ZM7.365 9.402h.001c-.044.026-.09.049-.136.071v4.472l1.5-.875V8.61Zm5.885 1.032 1.115-.65h.002a.267.267 0 0 0 .133-.232V5.264l-1.25.725Z"></path></svg>
|
||||||
|
<%= plugins.steam.games.count %> game<%= s(plugins.steam.games.count) %>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<div class="field">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Zm0 2.445L6.615 5.5a.75.75 0 0 1-.564.41l-3.097.45 2.24 2.184a.75.75 0 0 1 .216.664l-.528 3.084 2.769-1.456a.75.75 0 0 1 .698 0l2.77 1.456-.53-3.084a.75.75 0 0 1 .216-.664l2.24-2.183-3.096-.45a.75.75 0 0 1-.564-.41L8 2.694Z"></path></svg>
|
||||||
|
Steam level <%= plugins.steam.player.level %>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg>
|
||||||
|
<%= f(parseInt(plugins.steam.games.playtime)) %> hour<%= s(plugins.steam.games.playtime) %> played
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
<% for (const section of ["most-played", "recently-played"]) { if (plugins.steam.sections.includes(section)) { %>
|
||||||
|
<div class="games">
|
||||||
|
<h2 class="field">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2 4a1 1 0 100-2 1 1 0 000 2zm3.75-1.5a.75.75 0 000 1.5h8.5a.75.75 0 000-1.5h-8.5zm0 5a.75.75 0 000 1.5h8.5a.75.75 0 000-1.5h-8.5zm0 5a.75.75 0 000 1.5h8.5a.75.75 0 000-1.5h-8.5zM3 8a1 1 0 11-2 0 1 1 0 012 0zm-1 6a1 1 0 100-2 1 1 0 000 2z"></path></svg>
|
||||||
|
<%= {"most-played":"Most played", "recently-played":"Recently played"}[section] %>
|
||||||
|
</h2>
|
||||||
|
<div class="medias largeable-flex-wrap">
|
||||||
|
<% for (const {name, icon, playtime, played, achievements, rate, genres, description} of plugins.steam.games[section]) { %>
|
||||||
|
<div class="media largeable-width-half">
|
||||||
|
<img src="<%= icon %>" alt="" />
|
||||||
|
<div class="about">
|
||||||
|
<div class="name"><%= name %></div>
|
||||||
|
<div class="infos">
|
||||||
|
<div>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2.5 7.775V2.75a.25.25 0 01.25-.25h5.025a.25.25 0 01.177.073l6.25 6.25a.25.25 0 010 .354l-5.025 5.025a.25.25 0 01-.354 0l-6.25-6.25a.25.25 0 01-.073-.177zm-1.5 0V2.75C1 1.784 1.784 1 2.75 1h5.025c.464 0 .91.184 1.238.513l6.25 6.25a1.75 1.75 0 010 2.474l-5.026 5.026a1.75 1.75 0 01-2.474 0l-6.25-6.25A1.75 1.75 0 011 7.775zM6 5a1 1 0 100 2 1 1 0 000-2z"></path></svg>
|
||||||
|
<%= genres.join(", ") %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="infos">
|
||||||
|
<div>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"></path></svg>
|
||||||
|
<%= f(parseInt(playtime)) %> hour<%= s(playtime) %> played
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="infos">
|
||||||
|
<div>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5Zm10.75-4H2.75a.25.25 0 0 0-.25.25V6h11V3.75a.25.25 0 0 0-.25-.25Z"></path></svg>
|
||||||
|
Last played on <%= f.date(played*1000, {date:true, timeZone:config.timezone?.name}) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="achievements">
|
||||||
|
<div class="infos">
|
||||||
|
<div>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M3.217 6.962A3.75 3.75 0 0 1 0 3.25v-.5C0 1.784.784 1 1.75 1h1.356c.228-.585.796-1 1.462-1h6.864c.647 0 1.227.397 1.462 1h1.356c.966 0 1.75.784 1.75 1.75v.5a3.75 3.75 0 0 1-3.217 3.712 5.014 5.014 0 0 1-2.771 3.117l.144 1.446c.005.05.03.12.114.204.086.087.217.17.373.227.283.103.618.274.89.568.285.31.467.723.467 1.226v.75h1.25a.75.75 0 0 1 0 1.5H2.75a.75.75 0 0 1 0-1.5H4v-.75c0-.503.182-.916.468-1.226.27-.294.606-.465.889-.568.139-.048.266-.126.373-.227.084-.085.109-.153.114-.204l.144-1.446a5.015 5.015 0 0 1-2.77-3.117ZM4.5 1.568V5.5a3.5 3.5 0 1 0 7 0V1.568a.068.068 0 0 0-.068-.068H4.568a.068.068 0 0 0-.068.068Zm2.957 8.902-.12 1.204c-.093.925-.858 1.47-1.467 1.691a.766.766 0 0 0-.3.176c-.037.04-.07.093-.07.21v.75h5v-.75c0-.117-.033-.17-.07-.21a.766.766 0 0 0-.3-.176c-.609-.221-1.374-.766-1.466-1.69l-.12-1.204a5.064 5.064 0 0 1-1.087 0ZM13 2.5v2.872a2.25 2.25 0 0 0 1.5-2.122v-.5a.25.25 0 0 0-.25-.25H13Zm-10 0H1.75a.25.25 0 0 0-.25.25v.5c0 .98.626 1.813 1.5 2.122Z"></path></svg>
|
||||||
|
<%= rate.achieved %> / <%= rate.total %> achievement<%= s(rate.total) %> unlocked
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% { const achieved = achievements.filter(({achieved}) => achieved) %>
|
||||||
|
<% for (const {icon, name, description, unlocked} of achieved) { %>
|
||||||
|
<div class="achievement">
|
||||||
|
<img src="<%= icon %>" alt="" />
|
||||||
|
<div>
|
||||||
|
<div class="name">
|
||||||
|
<div><%= name %></div>
|
||||||
|
<div class="unlocked"><%= f.date(unlocked*1000, {date:true, timeZone:config.timezone?.name}) %></div>
|
||||||
|
</div>
|
||||||
|
<div class="description"><%= description %></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
<% if ((achieved.length)&&(rate.achieved-achieved.length > 0)) { %>
|
||||||
|
<div class="achievement">
|
||||||
|
<div>
|
||||||
|
<div class="description ellipsis">+<%= rate.achieved-achieved.length %> other<%= s(rate.achieved-achieved.length) %>...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% } } %>
|
||||||
|
<% } %>
|
||||||
|
</section>
|
||||||
|
<% } %>
|
||||||
82
source/templates/classic/style.css
vendored
82
source/templates/classic/style.css
vendored
@@ -1049,6 +1049,88 @@
|
|||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Steam */
|
||||||
|
.steam .games {
|
||||||
|
margin-left: 28px;
|
||||||
|
}
|
||||||
|
.steam .media {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
width: 450px;
|
||||||
|
}
|
||||||
|
.steam .media img {
|
||||||
|
margin: 0 10px;
|
||||||
|
border-radius: 7px;
|
||||||
|
}
|
||||||
|
.steam .media > img {
|
||||||
|
height: 32px;
|
||||||
|
width: 32px;
|
||||||
|
}
|
||||||
|
.steam .media .about {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
.steam .media .name {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 14px;
|
||||||
|
color: #58a6ff;
|
||||||
|
}
|
||||||
|
.steam .media .infos {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666666;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.steam .media .infos > div {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
.steam .media .infos svg {
|
||||||
|
fill: currentColor;
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
margin: 0;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
.steam .media .achievement img {
|
||||||
|
height: 22px;
|
||||||
|
width: 22px;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
.steam .media .achievement .name {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.steam .media .achievement .name > div:first-child {
|
||||||
|
max-width: 280px;
|
||||||
|
}
|
||||||
|
.steam .media .achievement .description {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: block;
|
||||||
|
width: 344px;
|
||||||
|
max-height: 38px;
|
||||||
|
font-size: 12px;
|
||||||
|
white-space: normal;
|
||||||
|
/* May not work in all browsers */
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
|
.steam .media .achievement .unlocked {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666666;
|
||||||
|
font-style: italic;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.steam .media .achievement .ellipsis {
|
||||||
|
margin-left: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Licenses */
|
/* Licenses */
|
||||||
.licenses {
|
.licenses {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
2263
tests/mocks/api/axios/get/steam.mjs
Normal file
2263
tests/mocks/api/axios/get/steam.mjs
Normal file
File diff suppressed because one or more lines are too long
@@ -12,6 +12,7 @@
|
|||||||
"GOOGLE_MAP_TOKEN": "MOCKED_TOKEN",
|
"GOOGLE_MAP_TOKEN": "MOCKED_TOKEN",
|
||||||
"STOCK_TOKEN":"MOCKED_TOKEN",
|
"STOCK_TOKEN":"MOCKED_TOKEN",
|
||||||
"CHESS_TOKEN":"MOCKED_TOKEN",
|
"CHESS_TOKEN":"MOCKED_TOKEN",
|
||||||
|
"STEAM_TOKEN":"MOCKED_TOKEN",
|
||||||
"SPLATOON_TOKEN":"{}",
|
"SPLATOON_TOKEN":"{}",
|
||||||
"SPLATOON_STATINK_TOKEN":"MOCKED_TOKEN",
|
"SPLATOON_STATINK_TOKEN":"MOCKED_TOKEN",
|
||||||
"POOPMAP_TOKEN":"MOCKED_TOKEN"
|
"POOPMAP_TOKEN":"MOCKED_TOKEN"
|
||||||
|
|||||||
Reference in New Issue
Block a user