forked from Mastodon/mastoradio-la-radio-di-mastodon
more controls, metadata
This commit is contained in:
parent
3783f0fa3a
commit
7e4038386e
|
@ -847,11 +847,19 @@
|
||||||
"version": "7.7.7",
|
"version": "7.7.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.7.tgz",
|
||||||
"integrity": "sha512-uCnC2JEVAu8AKB5do1WRIsvrdJ0flYx/A/9f/6chdacnEZ7LmavjdsDXr5ksYBegxtuTPR5Va9/+13QF/kFkCA==",
|
"integrity": "sha512-uCnC2JEVAu8AKB5do1WRIsvrdJ0flYx/A/9f/6chdacnEZ7LmavjdsDXr5ksYBegxtuTPR5Va9/+13QF/kFkCA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"regenerator-runtime": "^0.13.2"
|
"regenerator-runtime": "^0.13.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@babel/runtime-corejs2": {
|
||||||
|
"version": "7.7.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.7.7.tgz",
|
||||||
|
"integrity": "sha512-P91T3dFYQL7aj44PxOMIAbo66Ag3NbmXG9fseSYaXxapp3K9XTct5HU9IpTOm2D0AoktKusgqzN5YcSxZXEKBQ==",
|
||||||
|
"requires": {
|
||||||
|
"core-js": "^2.6.5",
|
||||||
|
"regenerator-runtime": "^0.13.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@babel/runtime-corejs3": {
|
"@babel/runtime-corejs3": {
|
||||||
"version": "7.7.7",
|
"version": "7.7.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.7.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.7.7.tgz",
|
||||||
|
@ -1014,6 +1022,14 @@
|
||||||
"integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==",
|
"integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"agent-base": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
|
||||||
|
"requires": {
|
||||||
|
"es6-promisify": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ajv": {
|
"ajv": {
|
||||||
"version": "6.10.2",
|
"version": "6.10.2",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
|
||||||
|
@ -1081,11 +1097,15 @@
|
||||||
"version": "1.0.10",
|
"version": "1.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"sprintf-js": "~1.0.2"
|
"sprintf-js": "~1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"argv": {
|
||||||
|
"version": "0.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz",
|
||||||
|
"integrity": "sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas="
|
||||||
|
},
|
||||||
"arr-diff": {
|
"arr-diff": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
|
||||||
|
@ -1272,8 +1292,7 @@
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"base": {
|
"base": {
|
||||||
"version": "0.11.2",
|
"version": "0.11.2",
|
||||||
|
@ -1376,7 +1395,6 @@
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
|
@ -1761,6 +1779,18 @@
|
||||||
"q": "^1.1.2"
|
"q": "^1.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"codecov": {
|
||||||
|
"version": "3.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/codecov/-/codecov-3.6.1.tgz",
|
||||||
|
"integrity": "sha512-IUJB6WG47nWK7o50etF8jBadxdMw7DmoQg05yIljstXFBGB6clOZsIj6iD4P82T2YaIU3qq+FFu8K9pxgkCJDQ==",
|
||||||
|
"requires": {
|
||||||
|
"argv": "^0.0.2",
|
||||||
|
"ignore-walk": "^3.0.1",
|
||||||
|
"js-yaml": "^3.13.1",
|
||||||
|
"teeny-request": "^3.11.3",
|
||||||
|
"urlgrey": "^0.4.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"collection-visit": {
|
"collection-visit": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
|
||||||
|
@ -1836,8 +1866,7 @@
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"concat-stream": {
|
"concat-stream": {
|
||||||
"version": "1.6.2",
|
"version": "1.6.2",
|
||||||
|
@ -1881,8 +1910,7 @@
|
||||||
"core-js": {
|
"core-js": {
|
||||||
"version": "2.6.11",
|
"version": "2.6.11",
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
|
||||||
"integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==",
|
"integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"core-js-compat": {
|
"core-js-compat": {
|
||||||
"version": "3.6.2",
|
"version": "3.6.2",
|
||||||
|
@ -2662,6 +2690,19 @@
|
||||||
"is-symbol": "^1.0.2"
|
"is-symbol": "^1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"es6-promise": {
|
||||||
|
"version": "4.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
|
||||||
|
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
|
||||||
|
},
|
||||||
|
"es6-promisify": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
|
||||||
|
"integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
|
||||||
|
"requires": {
|
||||||
|
"es6-promise": "^4.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"escape-html": {
|
"escape-html": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||||
|
@ -3949,6 +3990,25 @@
|
||||||
"integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
|
"integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"https-proxy-agent": {
|
||||||
|
"version": "2.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
|
||||||
|
"integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
|
||||||
|
"requires": {
|
||||||
|
"agent-base": "^4.3.0",
|
||||||
|
"debug": "^3.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "3.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
|
||||||
|
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "^2.1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"iconv-lite": {
|
"iconv-lite": {
|
||||||
"version": "0.4.24",
|
"version": "0.4.24",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
|
@ -3970,6 +4030,14 @@
|
||||||
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==",
|
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"ignore-walk": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
|
||||||
|
"requires": {
|
||||||
|
"minimatch": "^3.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"import-fresh": {
|
"import-fresh": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
|
||||||
|
@ -4286,6 +4354,29 @@
|
||||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
|
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"iter-tools": {
|
||||||
|
"version": "7.0.0-rc.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/iter-tools/-/iter-tools-7.0.0-rc.0.tgz",
|
||||||
|
"integrity": "sha512-u5pdY3kERasb9eUiAuVIWoYSpUnKKv7xXol+KpwIT+U+/LUDT+F1xTPdSNLHcNxIxAcjIWG+Adu6jtkgCOKd4Q==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.4.3",
|
||||||
|
"@babel/runtime-corejs2": "^7.4.3",
|
||||||
|
"codecov": "^3.6.1",
|
||||||
|
"decamelize": "^3.2.0",
|
||||||
|
"little-ds-toolkit": "^1.1.0",
|
||||||
|
"typescript-tuple": "^2.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"decamelize": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-4TgkVUsmmu7oCSyGBm5FvfMoACuoh9EOidm7V5/J2X2djAwwt57qb3F2KMP2ITqODTCSwb+YRV+0Zqrv18k/hw==",
|
||||||
|
"requires": {
|
||||||
|
"xregexp": "^4.2.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"js-levenshtein": {
|
"js-levenshtein": {
|
||||||
"version": "1.1.6",
|
"version": "1.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
|
||||||
|
@ -4302,7 +4393,6 @@
|
||||||
"version": "3.13.1",
|
"version": "3.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
||||||
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
|
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"argparse": "^1.0.7",
|
"argparse": "^1.0.7",
|
||||||
"esprima": "^4.0.0"
|
"esprima": "^4.0.0"
|
||||||
|
@ -4311,8 +4401,7 @@
|
||||||
"esprima": {
|
"esprima": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -4453,6 +4542,11 @@
|
||||||
"type-check": "~0.3.2"
|
"type-check": "~0.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"little-ds-toolkit": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/little-ds-toolkit/-/little-ds-toolkit-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-Zl5flhnd5W6nhRCyoL1bNlU8M5CWFp6SItMmK4pj39LKgzQD7LGg591OJ0jwDKat7mjHvJVkOyJT+BXOQH4iXw=="
|
||||||
|
},
|
||||||
"load-script2": {
|
"load-script2": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/load-script2/-/load-script2-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/load-script2/-/load-script2-2.0.4.tgz",
|
||||||
|
@ -4654,7 +4748,6 @@
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
|
@ -4706,8 +4799,7 @@
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"nan": {
|
"nan": {
|
||||||
"version": "2.14.0",
|
"version": "2.14.0",
|
||||||
|
@ -4747,6 +4839,11 @@
|
||||||
"integrity": "sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ==",
|
"integrity": "sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node-fetch": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
|
||||||
|
},
|
||||||
"node-forge": {
|
"node-forge": {
|
||||||
"version": "0.7.6",
|
"version": "0.7.6",
|
||||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz",
|
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz",
|
||||||
|
@ -6514,8 +6611,7 @@
|
||||||
"sprintf-js": {
|
"sprintf-js": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"sshpk": {
|
"sshpk": {
|
||||||
"version": "1.16.1",
|
"version": "1.16.1",
|
||||||
|
@ -6780,6 +6876,16 @@
|
||||||
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
|
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"teeny-request": {
|
||||||
|
"version": "3.11.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-3.11.3.tgz",
|
||||||
|
"integrity": "sha512-CKncqSF7sH6p4rzCgkb/z/Pcos5efl0DmolzvlqRQUNcpRIruOhY9+T1FsIlyEbfWd7MsFpodROOwHYh2BaXzw==",
|
||||||
|
"requires": {
|
||||||
|
"https-proxy-agent": "^2.2.1",
|
||||||
|
"node-fetch": "^2.2.0",
|
||||||
|
"uuid": "^3.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"terser": {
|
"terser": {
|
||||||
"version": "3.17.0",
|
"version": "3.17.0",
|
||||||
"resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz",
|
||||||
|
@ -6942,6 +7048,27 @@
|
||||||
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
|
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"typescript-compare": {
|
||||||
|
"version": "0.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript-compare/-/typescript-compare-0.0.2.tgz",
|
||||||
|
"integrity": "sha512-8ja4j7pMHkfLJQO2/8tut7ub+J3Lw2S3061eJLFQcvs3tsmJKp8KG5NtpLn7KcY2w08edF74BSVN7qJS0U6oHA==",
|
||||||
|
"requires": {
|
||||||
|
"typescript-logic": "^0.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"typescript-logic": {
|
||||||
|
"version": "0.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript-logic/-/typescript-logic-0.0.0.tgz",
|
||||||
|
"integrity": "sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q=="
|
||||||
|
},
|
||||||
|
"typescript-tuple": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript-tuple/-/typescript-tuple-2.2.1.tgz",
|
||||||
|
"integrity": "sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q==",
|
||||||
|
"requires": {
|
||||||
|
"typescript-compare": "^0.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"uncss": {
|
"uncss": {
|
||||||
"version": "0.17.2",
|
"version": "0.17.2",
|
||||||
"resolved": "https://registry.npmjs.org/uncss/-/uncss-0.17.2.tgz",
|
"resolved": "https://registry.npmjs.org/uncss/-/uncss-0.17.2.tgz",
|
||||||
|
@ -7140,6 +7267,11 @@
|
||||||
"tlds": "^1.203.0"
|
"tlds": "^1.203.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"urlgrey": {
|
||||||
|
"version": "0.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-0.4.4.tgz",
|
||||||
|
"integrity": "sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8="
|
||||||
|
},
|
||||||
"use": {
|
"use": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
||||||
|
@ -7182,8 +7314,7 @@
|
||||||
"uuid": {
|
"uuid": {
|
||||||
"version": "3.3.3",
|
"version": "3.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
|
||||||
"integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==",
|
"integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"v8-compile-cache": {
|
"v8-compile-cache": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
|
@ -7357,6 +7488,14 @@
|
||||||
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
|
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"xregexp": {
|
||||||
|
"version": "4.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.2.4.tgz",
|
||||||
|
"integrity": "sha512-sO0bYdYeJAJBcJA8g7MJJX7UrOZIfJPd8U2SC7B2Dd/J24U0aQNoGp33shCaBSWeb0rD5rh6VBUIXOkGal1TZA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime-corejs2": "^7.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"xtend": {
|
"xtend": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
"@babel/runtime-corejs3": "^7.7.7",
|
"@babel/runtime-corejs3": "^7.7.7",
|
||||||
"date-fns": "^2.9.0",
|
"date-fns": "^2.9.0",
|
||||||
"get-urls": "^9.2.0",
|
"get-urls": "^9.2.0",
|
||||||
|
"iter-tools": "^7.0.0-rc.0",
|
||||||
"yt-player": "^3.4.3"
|
"yt-player": "^3.4.3"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
|
|
129
src/App.svelte
129
src/App.svelte
|
@ -1,129 +0,0 @@
|
||||||
<main class="app">
|
|
||||||
<header class="header">
|
|
||||||
<h1>
|
|
||||||
Eldritch Radio
|
|
||||||
</h1>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<section class="player">
|
|
||||||
{#if $selectedEntry}
|
|
||||||
Playing <a href={$selectedEntry.url}>{$selectedEntry.id}</a>
|
|
||||||
<YoutubeViewer bind:videoId={$selectedEntry.id} bind:playing={$playing}></YoutubeViewer>
|
|
||||||
{:else}
|
|
||||||
Loading ...
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button>⏮️</button>
|
|
||||||
<button on:click={() => $playing = !$playing}>{#if $playing}⏸️{:else}▶️{/if}</button>
|
|
||||||
<button on:click={() => selectedEntry.next()}>⏭️</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button>🔇 / 🔊</button>
|
|
||||||
<input type="range" min="0" max="100" value="80">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button>⭐</button>
|
|
||||||
<button>🔁</button>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="queue">
|
|
||||||
<div>
|
|
||||||
{#if $entries}
|
|
||||||
<ul>
|
|
||||||
{#each $entries as entry}
|
|
||||||
<li class="entry" class:active={entry === $selectedEntry} on:click={() => $selectedEntry = entry}>
|
|
||||||
<div>{entry.url}</div>
|
|
||||||
<b>{entry.status.account.acct}</b>
|
|
||||||
<small>{entry.tags}</small>
|
|
||||||
</li>
|
|
||||||
{/each}
|
|
||||||
</ul>
|
|
||||||
{:else}
|
|
||||||
Your queue
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if $loading}
|
|
||||||
LOADING ...
|
|
||||||
{:else}
|
|
||||||
<button on:click={() => entries.load(3)}>LOAD MOAR</button>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<header>
|
|
||||||
<a href="https://{$domain}/">{$domain}</a> - {@html $hashtags.map(hashtag => `<a href="https://${$domain}/tags/${hashtag}">#${hashtag}</a>`)}
|
|
||||||
</header>
|
|
||||||
</section>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { onMount } from 'svelte'
|
|
||||||
import YoutubeViewer from './YoutubeViewer.svelte'
|
|
||||||
import { domain, hashtags, playing, loading, entry as selectedEntry, entries } from './store.js'
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
const unsub = entries.subscribe(async (xs) => {
|
|
||||||
if (xs.length) {
|
|
||||||
const [firstEntry] = xs
|
|
||||||
selectedEntry.set(firstEntry)
|
|
||||||
unsub()
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
entries.load(7)
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.app {
|
|
||||||
display: grid;
|
|
||||||
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
|
|
||||||
grid-template-areas:
|
|
||||||
"header"
|
|
||||||
"player"
|
|
||||||
"queue";
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
grid-area: header;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player {
|
|
||||||
grid-area: player;
|
|
||||||
}
|
|
||||||
|
|
||||||
.queue {
|
|
||||||
grid-area: queue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 992px) {
|
|
||||||
.app {
|
|
||||||
grid-template-columns: 2fr 3fr;
|
|
||||||
grid-template-rows: auto 1fr;
|
|
||||||
|
|
||||||
grid-template-areas:
|
|
||||||
"header queue"
|
|
||||||
"player queue"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.entry {
|
|
||||||
cursor: pointer;
|
|
||||||
border: 1px solid black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.entry:hover {
|
|
||||||
background-color: plum;
|
|
||||||
}
|
|
||||||
|
|
||||||
.entry.active {
|
|
||||||
background-color: plum;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,45 +0,0 @@
|
||||||
<div>
|
|
||||||
<div bind:this={element}></div>
|
|
||||||
|
|
||||||
<button on:click={player.play()}>PLAY UWU</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { onMount } from 'svelte';
|
|
||||||
import YoutubePlayer from 'yt-player'
|
|
||||||
|
|
||||||
export let videoId
|
|
||||||
export let playing
|
|
||||||
|
|
||||||
let element
|
|
||||||
let player
|
|
||||||
|
|
||||||
$: if (player && videoId) {
|
|
||||||
player.load(videoId, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
$: if (player) {
|
|
||||||
if (playing) {
|
|
||||||
player.play()
|
|
||||||
} else {
|
|
||||||
player.pause()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
player = new YoutubePlayer(element, {
|
|
||||||
autoplay: playing,
|
|
||||||
controls: true, // debug only
|
|
||||||
keyboard: false,
|
|
||||||
fullscreen: false,
|
|
||||||
modestBranding: true,
|
|
||||||
related: false
|
|
||||||
})
|
|
||||||
|
|
||||||
player.on('ended', () => console.log('ended u should select next entry now uwu'))
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
<main class="app">
|
||||||
|
<header class="header">
|
||||||
|
<h1>Eldritch Radio</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="viewer">
|
||||||
|
<Viewer></Viewer>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="queue">
|
||||||
|
<div>
|
||||||
|
{#each $entries as entry}
|
||||||
|
<div class="entry" class:active={entry === $currentEntry} on:click={() => $currentEntry = entry}>
|
||||||
|
<div>{entry.metadata.title}</div>
|
||||||
|
<b>{entry.status.account.username} <small>{entry.status.account.acct}</small></b>
|
||||||
|
<small>{entry.tags}</small>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button on:click={() => entries.load(5)}>LOAD MOAR</button>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="controls">
|
||||||
|
<Controls></Controls>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { onMount } from 'svelte'
|
||||||
|
import Controls from '/components/Controls.svelte'
|
||||||
|
import Viewer from '/components/Viewer.svelte'
|
||||||
|
import { playing, loading, entry as currentEntry, entries } from '/store.js'
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
const unsub = entries.subscribe(async (xs) => {
|
||||||
|
if (xs.length) {
|
||||||
|
const [firstEntry] = xs
|
||||||
|
currentEntry.set(firstEntry)
|
||||||
|
unsub()
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
entries.load(7)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.app {
|
||||||
|
min-width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
|
||||||
|
grid-template-areas:
|
||||||
|
"header"
|
||||||
|
"viewer"
|
||||||
|
"queue"
|
||||||
|
"controls";
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
grid-area: header;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
background: blueviolet;
|
||||||
|
color: whitesmoke;
|
||||||
|
|
||||||
|
padding: 0.4rem 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header h1 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewer {
|
||||||
|
grid-area: viewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.queue {
|
||||||
|
grid-area: queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
grid-area: controls;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
position: sticky;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
background: whitesmoke;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
.app {
|
||||||
|
grid-template-columns: 2fr 3fr;
|
||||||
|
grid-template-rows: auto 1fr auto;
|
||||||
|
|
||||||
|
grid-template-areas:
|
||||||
|
"header queue"
|
||||||
|
"viewer queue"
|
||||||
|
"controls controls"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry {
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry:hover {
|
||||||
|
background-color: rgb(219, 184, 219);
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry.active {
|
||||||
|
background-color: plum;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,45 @@
|
||||||
|
<div class="controls">
|
||||||
|
<div class="controls-group">
|
||||||
|
<button on:click={() => $muted = !$muted}>
|
||||||
|
{#if $muted}
|
||||||
|
🔇
|
||||||
|
{:else}
|
||||||
|
{#if $volume < 20}
|
||||||
|
🔈
|
||||||
|
{:else if $volume < 80}
|
||||||
|
🔉
|
||||||
|
{:else}
|
||||||
|
🔊
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<input type="range" min="0" max="100" bind:value={$volume}>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="controls-group">
|
||||||
|
<button on:click={() => entry.previous()}>⏮️</button>
|
||||||
|
<button on:click={() => $playing = !$playing}>{#if $playing}⏸️{:else}▶️{/if}</button>
|
||||||
|
<button on:click={() => entry.next()}>⏭️</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="controls-group">
|
||||||
|
<button>⭐</button>
|
||||||
|
<button>🔁</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { playing, volume, muted, entry } from '/store.js'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.controls {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls-group {
|
||||||
|
margin: 0 1rem;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,54 @@
|
||||||
|
<div>
|
||||||
|
<div bind:this={element}></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { onMount } from 'svelte'
|
||||||
|
import { get } from 'svelte/store'
|
||||||
|
import YoutubePlayer from 'yt-player'
|
||||||
|
import { entry, playing, volume, muted } from '/store.js'
|
||||||
|
|
||||||
|
let element
|
||||||
|
let player
|
||||||
|
|
||||||
|
$: updateEntry($entry)
|
||||||
|
$: updatePlaying($playing)
|
||||||
|
$: updateVolume($volume)
|
||||||
|
$: updateMuted($muted)
|
||||||
|
|
||||||
|
const updateEntry = (entry) => {
|
||||||
|
if (player && entry) player.load(entry.id, get(playing))
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatePlaying = (playing) => {
|
||||||
|
if (player) playing ? player.play() : player.pause()
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateVolume = (volume) => {
|
||||||
|
if (player) player.setVolume(volume)
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateMuted = (muted) => {
|
||||||
|
if (player) muted ? player.mute() : player.unMute()
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
player = new YoutubePlayer(element, {
|
||||||
|
width: 300,
|
||||||
|
height: 300,
|
||||||
|
autoplay: $playing,
|
||||||
|
controls: true, // debug only
|
||||||
|
keyboard: false,
|
||||||
|
fullscreen: false,
|
||||||
|
modestBranding: true,
|
||||||
|
related: false
|
||||||
|
})
|
||||||
|
|
||||||
|
player.on('ended', () => entry.next())
|
||||||
|
player.on('unplayable', () => entry.next())
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
|
@ -5,6 +5,7 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
<title>Eldritch Radio</title>
|
<title>Eldritch Radio</title>
|
||||||
|
<link rel="stylesheet" href="main.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script src="main.js"></script>
|
<script src="main.js"></script>
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
html, body {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import App from './App.svelte'
|
import App from '/components/App.svelte'
|
||||||
|
|
||||||
const app = new App({
|
const app = new App({
|
||||||
target: document.body
|
target: document.body
|
||||||
|
|
64
src/store.js
64
src/store.js
|
@ -1,5 +1,5 @@
|
||||||
import { writable, get } from 'svelte/store'
|
import { writable, get } from 'svelte/store'
|
||||||
import * as util from './util.js'
|
import * as util from '/util.js'
|
||||||
|
|
||||||
export const domain = writable('eldritch.cafe')
|
export const domain = writable('eldritch.cafe')
|
||||||
|
|
||||||
|
@ -11,11 +11,10 @@ export const hashtags = writable([
|
||||||
])
|
])
|
||||||
|
|
||||||
export const playing = writable(true)
|
export const playing = writable(true)
|
||||||
|
export const muted = writable(false)
|
||||||
|
export const volume = writable(100)
|
||||||
|
|
||||||
export const loading = writable(false)
|
export const entries = entriesStore()
|
||||||
|
|
||||||
export const entries = entriesStore(loading)
|
|
||||||
|
|
||||||
export const entry = entryStore(entries)
|
export const entry = entryStore(entries)
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,8 +25,29 @@ function entryStore(entries) {
|
||||||
const store = writable(null)
|
const store = writable(null)
|
||||||
const { set, update, subscribe } = store
|
const { set, update, subscribe } = store
|
||||||
|
|
||||||
const next = async () => {
|
const select = (entry) => {
|
||||||
const entriesList = await get(entries)
|
update(() => entry)
|
||||||
|
|
||||||
|
const entriesList = get(entries)
|
||||||
|
const index = entriesList.indexOf(entry)
|
||||||
|
|
||||||
|
if (index === entriesList.length - 1) {
|
||||||
|
entries.load(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const previous = () => {
|
||||||
|
const entriesList = get(entries)
|
||||||
|
|
||||||
|
update(currentEntry => {
|
||||||
|
const index = entriesList.indexOf(currentEntry)
|
||||||
|
|
||||||
|
return index > 0 ? entriesList[index - 1] : null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const next = () => {
|
||||||
|
const entriesList = get(entries)
|
||||||
|
|
||||||
update(oldEntry => {
|
update(oldEntry => {
|
||||||
if (entriesList.length === 0) {
|
if (entriesList.length === 0) {
|
||||||
|
@ -51,39 +71,16 @@ function entryStore(entries) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return { subscribe, set, next }
|
return { subscribe, set: select, previous, next }
|
||||||
}
|
}
|
||||||
|
|
||||||
async function* loader(loading) {
|
function entriesStore() {
|
||||||
loading.set(true)
|
const entriesSteam = util.statusesToEntries(util.statusesStreaming())
|
||||||
let { statuses, nextLink, previousLink } = await util.fetchTimeline('https://eldritch.cafe/api/v1/timelines/tag/np')
|
|
||||||
loading.set(false)
|
|
||||||
|
|
||||||
yield* util.statusesToEntries(statuses)
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
loading.set(true)
|
|
||||||
const timeline = await util.fetchTimeline(nextLink)
|
|
||||||
loading.set(false)
|
|
||||||
|
|
||||||
nextLink = timeline.nextLink
|
|
||||||
|
|
||||||
yield* util.statusesToEntries(timeline.statuses)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function entriesStore(loading) {
|
|
||||||
const entriesSteam = loader(loading)
|
|
||||||
|
|
||||||
const store = writable([])
|
const store = writable([])
|
||||||
const { update, subscribe } = store
|
const { update, subscribe } = store
|
||||||
|
|
||||||
const load = async (number) => {
|
const load = async (number) => {
|
||||||
if (get(loading)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < number; i++) {
|
for (let i = 0; i < number; i++) {
|
||||||
const iteratorResult = await entriesSteam.next()
|
const iteratorResult = await entriesSteam.next()
|
||||||
|
|
||||||
|
@ -97,4 +94,3 @@ function entriesStore(loading) {
|
||||||
|
|
||||||
return { subscribe, load }
|
return { subscribe, load }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
64
src/util.js
64
src/util.js
|
@ -1,4 +1,45 @@
|
||||||
import getUrls from 'get-urls'
|
import getUrls from 'get-urls'
|
||||||
|
import { pipe, asyncFilter, asyncMap, asyncTap, asyncTake } from 'iter-tools'
|
||||||
|
|
||||||
|
export async function* statusesStreaming() {
|
||||||
|
let { statuses, nextLink, previousLink } = await fetchTimeline('https://eldritch.cafe/api/v1/timelines/tag/np')
|
||||||
|
|
||||||
|
yield* statuses
|
||||||
|
|
||||||
|
while (nextLink) {
|
||||||
|
const a = await fetchTimeline(nextLink)
|
||||||
|
|
||||||
|
nextLink = a.nextLink
|
||||||
|
yield* a.statuses
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const statusesToEntries = pipe(
|
||||||
|
asyncMap(status => ({ status, urls: Array.from(getUrls(status.content)).filter(isSupportedUrl) })),
|
||||||
|
asyncFilter(entry => entry.urls.length > 0),
|
||||||
|
asyncMap(async ({ status, urls }) => {
|
||||||
|
const [url] = urls
|
||||||
|
const id = getYoutubeVideoId(url)
|
||||||
|
|
||||||
|
const tags = intersection(status.tags.map(tag => tag.name), [
|
||||||
|
'np',
|
||||||
|
'nowplaying',
|
||||||
|
'tootradio',
|
||||||
|
'pouetradio'
|
||||||
|
])
|
||||||
|
|
||||||
|
const metadata = await fetchYoutubeMetadata(id)
|
||||||
|
|
||||||
|
return { status, url, id, tags, metadata }
|
||||||
|
}),
|
||||||
|
asyncTake(20)
|
||||||
|
)
|
||||||
|
|
||||||
|
function fetchYoutubeMetadata(id) {
|
||||||
|
return fetch(`https://noembed.com/embed?url=https://www.youtube.com/watch?v=${id}`)
|
||||||
|
.then(response => response.json())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
export function isSupportedUrl(urlAsString) {
|
export function isSupportedUrl(urlAsString) {
|
||||||
const url = new URL(urlAsString)
|
const url = new URL(urlAsString)
|
||||||
|
@ -40,27 +81,4 @@ export function parseLinkHeader(link) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return links
|
return links
|
||||||
}
|
|
||||||
|
|
||||||
export function statusesToEntries(statuses) {
|
|
||||||
const entries = []
|
|
||||||
|
|
||||||
return statuses
|
|
||||||
.map(status => {
|
|
||||||
const [url] = Array.from(getUrls(status.content)).filter(isSupportedUrl)
|
|
||||||
|
|
||||||
return { status, url }
|
|
||||||
})
|
|
||||||
.filter(entry => entry.url != null)
|
|
||||||
.map(({ status, url }) => {
|
|
||||||
const id = getYoutubeVideoId(url)
|
|
||||||
const tags = intersection(status.tags.map(tag => tag.name), [
|
|
||||||
'np',
|
|
||||||
'nowplaying',
|
|
||||||
'tootradio',
|
|
||||||
'pouetradio'
|
|
||||||
])
|
|
||||||
|
|
||||||
return { status, url, id, tags }
|
|
||||||
})
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue