Incorporate new NowPlaying library
- Move much of AzuraCast's merging and client integration into the library itself - The library now uses typed properties on a return object for much more reliable hinting - Update both this library and SupervisorPHP to use PSR-17 and PSR-18 standardized factories
This commit is contained in:
parent
90e12fec62
commit
0adda37403
|
@ -43,7 +43,7 @@
|
|||
"league/flysystem-aws-s3-v3": "^1.0",
|
||||
"league/flysystem-cached-adapter": "^1.0",
|
||||
"league/plates": "^3.1",
|
||||
"lstrojny/fxmlrpc": "^0.15",
|
||||
"lstrojny/fxmlrpc": "dev-master",
|
||||
"malkusch/lock": "^2.1",
|
||||
"maxmind-db/reader": "~1.0",
|
||||
"mezzio/mezzio-session": "^1.3",
|
||||
|
|
|
@ -4,20 +4,20 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "7b700975885f74d5c8b0a1f83fd7247f",
|
||||
"content-hash": "925aceab5c1165782215531ba732c16f",
|
||||
"packages": [
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.143.2",
|
||||
"version": "3.145.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "d44eac162f8ed1869d20c076adca9869c70a8ad9"
|
||||
"reference": "df5406b49f4f5774045e51e8fecc75717c4d6454"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/d44eac162f8ed1869d20c076adca9869c70a8ad9",
|
||||
"reference": "d44eac162f8ed1869d20c076adca9869c70a8ad9",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/df5406b49f4f5774045e51e8fecc75717c4d6454",
|
||||
"reference": "df5406b49f4f5774045e51e8fecc75717c4d6454",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -89,7 +89,7 @@
|
|||
"s3",
|
||||
"sdk"
|
||||
],
|
||||
"time": "2020-06-26T18:21:03+00:00"
|
||||
"time": "2020-07-02T18:12:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "azuracast/azuraforms",
|
||||
|
@ -148,23 +148,26 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/AzuraCast/nowplaying.git",
|
||||
"reference": "3b6cb5848482341dc2614e4e49d84db35d4c5078"
|
||||
"reference": "645880eecde55ccd3feefdf0bad6b52d41b83d70"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/AzuraCast/nowplaying/zipball/3b6cb5848482341dc2614e4e49d84db35d4c5078",
|
||||
"reference": "3b6cb5848482341dc2614e4e49d84db35d4c5078",
|
||||
"url": "https://api.github.com/repos/AzuraCast/nowplaying/zipball/645880eecde55ccd3feefdf0bad6b52d41b83d70",
|
||||
"reference": "645880eecde55ccd3feefdf0bad6b52d41b83d70",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-simplexml": "*",
|
||||
"ext-xml": "*",
|
||||
"guzzlehttp/guzzle": ">6.0",
|
||||
"php": ">=7.2"
|
||||
"php": ">=7.4",
|
||||
"psr/http-client": "*",
|
||||
"psr/http-factory": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"overtrue/phplint": "^1.1",
|
||||
"php-http/discovery": "^1.9",
|
||||
"phpstan/phpstan": "^0.11.1",
|
||||
"phpstan/phpstan-strict-rules": "^0.11.0",
|
||||
"roave/security-advisories": "dev-master"
|
||||
|
@ -186,7 +189,7 @@
|
|||
}
|
||||
],
|
||||
"description": "A lightweight PHP adapter for viewing the current now playing data in Icecast and SHOUTcast 1/2. A part of the AzuraCast software suite.",
|
||||
"time": "2020-05-05T04:11:51+00:00"
|
||||
"time": "2020-07-03T20:07:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
|
@ -2750,12 +2753,12 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/JamesHeinrich/getID3.git",
|
||||
"reference": "cde8ac014c7d8fce9af004974eff400a9ee348a6"
|
||||
"reference": "03ce1bc314aa17e0a8943127c3868bb151181a22"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/cde8ac014c7d8fce9af004974eff400a9ee348a6",
|
||||
"reference": "cde8ac014c7d8fce9af004974eff400a9ee348a6",
|
||||
"url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/03ce1bc314aa17e0a8943127c3868bb151181a22",
|
||||
"reference": "03ce1bc314aa17e0a8943127c3868bb151181a22",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2805,7 +2808,7 @@
|
|||
"php",
|
||||
"tags"
|
||||
],
|
||||
"time": "2020-06-06T20:57:42+00:00"
|
||||
"time": "2020-07-01T01:52:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "jean85/pretty-package-versions",
|
||||
|
@ -3432,31 +3435,32 @@
|
|||
},
|
||||
{
|
||||
"name": "lstrojny/fxmlrpc",
|
||||
"version": "0.15.0",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/lstrojny/fxmlrpc.git",
|
||||
"reference": "d0336746bef99d5d9cb39ae826975d3a1462b23e"
|
||||
"reference": "f21eb6edbf44d9fa79e7ff583b136bdb156ee3d7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/lstrojny/fxmlrpc/zipball/d0336746bef99d5d9cb39ae826975d3a1462b23e",
|
||||
"reference": "d0336746bef99d5d9cb39ae826975d3a1462b23e",
|
||||
"url": "https://api.github.com/repos/lstrojny/fxmlrpc/zipball/f21eb6edbf44d9fa79e7ff583b136bdb156ee3d7",
|
||||
"reference": "f21eb6edbf44d9fa79e7ff583b136bdb156ee3d7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "~7.1",
|
||||
"php-http/discovery": "^1.0",
|
||||
"php-http/httplug": "^1.0 || ^2.0",
|
||||
"php-http/message-factory": "^1.0"
|
||||
"php-http/discovery": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"internations/kodierungsregelwerksammlung": "dev-master",
|
||||
"lstrojny/hmmmath": "dev-master",
|
||||
"monolog/monolog": "~1",
|
||||
"php-http/guzzle6-adapter": "^1.0 || ^2.0",
|
||||
"php-http/httplug": "^1.0 || ^2.0",
|
||||
"php-http/message": "^1.2",
|
||||
"php-http/message-factory": "^1.0",
|
||||
"phpunit/phpunit": "~6",
|
||||
"psr/http-factory": "*",
|
||||
"psr/log": "*",
|
||||
"symfony/process": "~2.1",
|
||||
"zendframework/zend-diactoros": "^1.3",
|
||||
|
@ -3502,7 +3506,7 @@
|
|||
"xml",
|
||||
"xmlrpc"
|
||||
],
|
||||
"time": "2019-02-07T14:10:11+00:00"
|
||||
"time": "2020-07-02T22:06:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "malkusch/lock",
|
||||
|
@ -4061,16 +4065,16 @@
|
|||
},
|
||||
{
|
||||
"name": "myclabs/deep-copy",
|
||||
"version": "1.10.0",
|
||||
"version": "1.10.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/myclabs/DeepCopy.git",
|
||||
"reference": "5796d127b0c4ff505b77455148ea9d5269d99758"
|
||||
"reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/5796d127b0c4ff505b77455148ea9d5269d99758",
|
||||
"reference": "5796d127b0c4ff505b77455148ea9d5269d99758",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/969b211f9a51aa1f6c01d1d2aef56d3bd91598e5",
|
||||
"reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -4111,7 +4115,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-06-28T07:02:41+00:00"
|
||||
"time": "2020-06-29T13:22:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "n98/junit-xml",
|
||||
|
@ -4894,16 +4898,16 @@
|
|||
},
|
||||
{
|
||||
"name": "php-http/client-common",
|
||||
"version": "2.1.0",
|
||||
"version": "2.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-http/client-common.git",
|
||||
"reference": "a8b29678d61556f45d6236b1667db16d998ceec5"
|
||||
"reference": "f3985360f3d054292605e9ec7c4bc24ebcf249bb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-http/client-common/zipball/a8b29678d61556f45d6236b1667db16d998ceec5",
|
||||
"reference": "a8b29678d61556f45d6236b1667db16d998ceec5",
|
||||
"url": "https://api.github.com/repos/php-http/client-common/zipball/f3985360f3d054292605e9ec7c4bc24ebcf249bb",
|
||||
"reference": "f3985360f3d054292605e9ec7c4bc24ebcf249bb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -4911,13 +4915,19 @@
|
|||
"php-http/httplug": "^2.0",
|
||||
"php-http/message": "^1.6",
|
||||
"php-http/message-factory": "^1.0",
|
||||
"symfony/options-resolver": " ^3.4.20 || ~4.0.15 || ~4.1.9 || ^4.2.1 || ^5.0"
|
||||
"psr/http-client": "^1.0",
|
||||
"psr/http-factory": "^1.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"symfony/options-resolver": "^2.6 || ^3.4.20 || ~4.0.15 || ~4.1.9 || ^4.2.1 || ^5.0",
|
||||
"symfony/polyfill-php80": "^1.17"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/instantiator": "^1.1",
|
||||
"guzzlehttp/psr7": "^1.4",
|
||||
"phpspec/phpspec": "^5.1",
|
||||
"nyholm/psr7": "^1.2",
|
||||
"phpspec/phpspec": "^5.1 || ^6.0",
|
||||
"phpspec/prophecy": "^1.8",
|
||||
"phpunit/phpunit": "^7.5",
|
||||
"sebastian/comparator": "^3.0"
|
||||
},
|
||||
"suggest": {
|
||||
|
@ -4930,7 +4940,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0.x-dev"
|
||||
"dev-master": "2.2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -4956,20 +4966,20 @@
|
|||
"http",
|
||||
"httplug"
|
||||
],
|
||||
"time": "2019-11-18T08:58:18+00:00"
|
||||
"time": "2020-07-02T06:51:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-http/discovery",
|
||||
"version": "1.8.0",
|
||||
"version": "1.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-http/discovery.git",
|
||||
"reference": "10d9019f393773345aedc0dc79e7fd678da874ee"
|
||||
"reference": "9ab7668fee74a5ad61996095e50917bd50ee8bfe"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-http/discovery/zipball/10d9019f393773345aedc0dc79e7fd678da874ee",
|
||||
"reference": "10d9019f393773345aedc0dc79e7fd678da874ee",
|
||||
"url": "https://api.github.com/repos/php-http/discovery/zipball/9ab7668fee74a5ad61996095e50917bd50ee8bfe",
|
||||
"reference": "9ab7668fee74a5ad61996095e50917bd50ee8bfe",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -4992,7 +5002,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.7-dev"
|
||||
"dev-master": "1.9-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -5021,7 +5031,7 @@
|
|||
"message",
|
||||
"psr7"
|
||||
],
|
||||
"time": "2020-06-14T10:44:12+00:00"
|
||||
"time": "2020-07-02T11:43:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-http/guzzle6-adapter",
|
||||
|
@ -5513,20 +5523,20 @@
|
|||
},
|
||||
{
|
||||
"name": "psr/http-client",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-client.git",
|
||||
"reference": "496a823ef742b632934724bf769560c2a5c7c44e"
|
||||
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-client/zipball/496a823ef742b632934724bf769560c2a5c7c44e",
|
||||
"reference": "496a823ef742b632934724bf769560c2a5c7c44e",
|
||||
"url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
|
||||
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.0",
|
||||
"php": "^7.0 || ^8.0",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"type": "library",
|
||||
|
@ -5558,7 +5568,7 @@
|
|||
"psr",
|
||||
"psr-18"
|
||||
],
|
||||
"time": "2018-10-30T23:29:13+00:00"
|
||||
"time": "2020-06-29T06:28:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-factory",
|
||||
|
@ -6093,16 +6103,16 @@
|
|||
},
|
||||
{
|
||||
"name": "sentry/sentry",
|
||||
"version": "2.4.0",
|
||||
"version": "2.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/getsentry/sentry-php.git",
|
||||
"reference": "e44561875e0d724bac3d9cdb705bf58847acd425"
|
||||
"reference": "407573e22e6cc46b72cff07c117eeb16bf3a17de"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/e44561875e0d724bac3d9cdb705bf58847acd425",
|
||||
"reference": "e44561875e0d724bac3d9cdb705bf58847acd425",
|
||||
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/407573e22e6cc46b72cff07c117eeb16bf3a17de",
|
||||
"reference": "407573e22e6cc46b72cff07c117eeb16bf3a17de",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -6186,7 +6196,7 @@
|
|||
"type": "custom"
|
||||
}
|
||||
],
|
||||
"time": "2020-05-20T20:49:38+00:00"
|
||||
"time": "2020-07-03T09:58:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "slim/http",
|
||||
|
@ -6491,12 +6501,12 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/supervisorphp/supervisor.git",
|
||||
"reference": "b7bd433a385edd38d2df77b0dfe52dc488608edc"
|
||||
"reference": "3deb0b1e0a79ac155172074f727a47b9ee68940b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/supervisorphp/supervisor/zipball/b7bd433a385edd38d2df77b0dfe52dc488608edc",
|
||||
"reference": "b7bd433a385edd38d2df77b0dfe52dc488608edc",
|
||||
"url": "https://api.github.com/repos/supervisorphp/supervisor/zipball/3deb0b1e0a79ac155172074f727a47b9ee68940b",
|
||||
"reference": "3deb0b1e0a79ac155172074f727a47b9ee68940b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -6545,7 +6555,7 @@
|
|||
"process manager",
|
||||
"supervisor"
|
||||
],
|
||||
"time": "2020-07-02T00:55:37+00:00"
|
||||
"time": "2020-07-02T01:08:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/amqp-messenger",
|
||||
|
@ -9579,16 +9589,16 @@
|
|||
},
|
||||
{
|
||||
"name": "codeception/stub",
|
||||
"version": "3.6.1",
|
||||
"version": "3.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Codeception/Stub.git",
|
||||
"reference": "a3ba01414cbee76a1bced9f9b6b169cc8d203880"
|
||||
"reference": "468dd5fe659f131fc997f5196aad87512f9b1304"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Codeception/Stub/zipball/a3ba01414cbee76a1bced9f9b6b169cc8d203880",
|
||||
"reference": "a3ba01414cbee76a1bced9f9b6b169cc8d203880",
|
||||
"url": "https://api.github.com/repos/Codeception/Stub/zipball/468dd5fe659f131fc997f5196aad87512f9b1304",
|
||||
"reference": "468dd5fe659f131fc997f5196aad87512f9b1304",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -9605,7 +9615,7 @@
|
|||
"MIT"
|
||||
],
|
||||
"description": "Flexible Stub wrapper for PHPUnit's Mock Builder",
|
||||
"time": "2020-02-07T18:42:28+00:00"
|
||||
"time": "2020-07-03T15:54:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "filp/whoops",
|
||||
|
@ -10205,16 +10215,16 @@
|
|||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "0.12.31",
|
||||
"version": "0.12.32",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "776c8056b401e1b67f277b9e9fb334d1a274671d"
|
||||
"reference": "d03863f504c8432b3de4d1881f73f6acb8c0e67c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/776c8056b401e1b67f277b9e9fb334d1a274671d",
|
||||
"reference": "776c8056b401e1b67f277b9e9fb334d1a274671d",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/d03863f504c8432b3de4d1881f73f6acb8c0e67c",
|
||||
"reference": "d03863f504c8432b3de4d1881f73f6acb8c0e67c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -10257,7 +10267,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-06-24T20:55:29+00:00"
|
||||
"time": "2020-07-01T11:57:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-doctrine",
|
||||
|
@ -10830,12 +10840,12 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Roave/SecurityAdvisories.git",
|
||||
"reference": "6d2e5ab854782830911ddd33b7d4649b9f18c10f"
|
||||
"reference": "57353ec1a34527a2dbbd3c0fb9418ffc008c6f60"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/6d2e5ab854782830911ddd33b7d4649b9f18c10f",
|
||||
"reference": "6d2e5ab854782830911ddd33b7d4649b9f18c10f",
|
||||
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/57353ec1a34527a2dbbd3c0fb9418ffc008c6f60",
|
||||
"reference": "57353ec1a34527a2dbbd3c0fb9418ffc008c6f60",
|
||||
"shasum": ""
|
||||
},
|
||||
"conflict": {
|
||||
|
@ -10929,8 +10939,9 @@
|
|||
"magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2",
|
||||
"monolog/monolog": ">=1.8,<1.12",
|
||||
"namshi/jose": "<2.2",
|
||||
"nystudio107/craft-seomatic": "<3.3",
|
||||
"nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1",
|
||||
"october/october": ">=1.0.319,<1.0.466",
|
||||
"october/october": ">=1.0.319,<1.0.467",
|
||||
"onelogin/php-saml": "<2.10.4",
|
||||
"oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5",
|
||||
"openid/php-openid": "<2.3",
|
||||
|
@ -11107,7 +11118,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-06-19T13:23:43+00:00"
|
||||
"time": "2020-07-03T16:50:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/code-unit",
|
||||
|
@ -11284,20 +11295,20 @@
|
|||
},
|
||||
{
|
||||
"name": "sebastian/diff",
|
||||
"version": "4.0.1",
|
||||
"version": "4.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/diff.git",
|
||||
"reference": "3e523c576f29dacecff309f35e4cc5a5c168e78a"
|
||||
"reference": "1e90b4cf905a7d06c420b1d2e9d11a4dc8a13113"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3e523c576f29dacecff309f35e4cc5a5c168e78a",
|
||||
"reference": "3e523c576f29dacecff309f35e4cc5a5c168e78a",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/1e90b4cf905a7d06c420b1d2e9d11a4dc8a13113",
|
||||
"reference": "1e90b4cf905a7d06c420b1d2e9d11a4dc8a13113",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.3"
|
||||
"php": "^7.3 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.0",
|
||||
|
@ -11342,7 +11353,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-05-08T05:01:12+00:00"
|
||||
"time": "2020-06-30T04:46:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/environment",
|
||||
|
@ -12208,6 +12219,7 @@
|
|||
"azuracast/azuraforms": 20,
|
||||
"azuracast/nowplaying": 20,
|
||||
"james-heinrich/getid3": 20,
|
||||
"lstrojny/fxmlrpc": 20,
|
||||
"supervisorphp/supervisor": 20,
|
||||
"zircote/swagger-php": 20,
|
||||
"roave/security-advisories": 20
|
||||
|
|
|
@ -385,15 +385,14 @@ return [
|
|||
|
||||
// Supervisor manager
|
||||
Supervisor\Supervisor::class => function (Settings $settings) {
|
||||
$guzzle_client = new GuzzleHttp\Client();
|
||||
$client = new fXmlRpc\Client(
|
||||
'http://' . ($settings->isDocker() ? 'stations' : '127.0.0.1') . ':9001/RPC2',
|
||||
new fXmlRpc\Transport\HttpAdapterTransport(
|
||||
new Http\Message\MessageFactory\GuzzleMessageFactory(),
|
||||
new Http\Adapter\Guzzle6\Client($guzzle_client)
|
||||
new fXmlRpc\Transport\PsrTransport(
|
||||
new Http\Factory\Guzzle\RequestFactory,
|
||||
new Http\Adapter\Guzzle6\Client
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
$supervisor = new Supervisor\Supervisor($client);
|
||||
|
||||
if (!$supervisor->isConnected()) {
|
||||
|
@ -403,6 +402,15 @@ return [
|
|||
return $supervisor;
|
||||
},
|
||||
|
||||
// NowPlaying Adapter factory
|
||||
NowPlaying\Adapter\AdapterFactory::class => function (GuzzleHttp\Client $httpClient) {
|
||||
return new NowPlaying\Adapter\AdapterFactory(
|
||||
new Http\Factory\Guzzle\UriFactory,
|
||||
new Http\Factory\Guzzle\RequestFactory,
|
||||
new Http\Adapter\Guzzle6\Client($httpClient)
|
||||
);
|
||||
},
|
||||
|
||||
// Asset Management
|
||||
App\Assets::class => function (App\Config $config, Settings $settings) {
|
||||
$libraries = $config->get('assets');
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use NowPlaying\Result\Client;
|
||||
|
||||
/**
|
||||
* @ORM\Table(name="listener", indexes={
|
||||
|
@ -72,16 +73,16 @@ class Listener
|
|||
*/
|
||||
protected $timestamp_end;
|
||||
|
||||
public function __construct(Station $station, array $client)
|
||||
public function __construct(Station $station, Client $client)
|
||||
{
|
||||
$this->station = $station;
|
||||
|
||||
$this->timestamp_start = time();
|
||||
$this->timestamp_end = 0;
|
||||
|
||||
$this->listener_uid = $client['uid'];
|
||||
$this->listener_user_agent = $this->truncateString($client['user_agent']) ?? '';
|
||||
$this->listener_ip = $client['ip'];
|
||||
$this->listener_uid = $client->uid;
|
||||
$this->listener_user_agent = $this->truncateString($client->userAgent) ?? '';
|
||||
$this->listener_ip = $client->ip;
|
||||
$this->listener_hash = self::calculateListenerHash($client);
|
||||
}
|
||||
|
||||
|
@ -189,8 +190,17 @@ class Listener
|
|||
return $seconds;
|
||||
}
|
||||
|
||||
public static function calculateListenerHash(array $client): string
|
||||
/**
|
||||
* @param array|Client $client
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function calculateListenerHash($client): string
|
||||
{
|
||||
if ($client instanceof Client) {
|
||||
return md5($client->ip . $client->userAgent);
|
||||
}
|
||||
|
||||
return md5($client['ip'] . $client['user_agent']);
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ namespace App\Entity\Repository;
|
|||
|
||||
use App\Doctrine\Repository;
|
||||
use App\Entity;
|
||||
use NowPlaying\Result\Client;
|
||||
|
||||
class ListenerRepository extends Repository
|
||||
{
|
||||
|
@ -33,7 +34,7 @@ class ListenerRepository extends Repository
|
|||
* Update listener data for a station.
|
||||
*
|
||||
* @param Entity\Station $station
|
||||
* @param array $clients
|
||||
* @param Client[] $clients
|
||||
*/
|
||||
public function update(Entity\Station $station, $clients): void
|
||||
{
|
||||
|
@ -51,9 +52,9 @@ class ListenerRepository extends Repository
|
|||
$existingClients[$identifier] = $client['id'];
|
||||
}
|
||||
|
||||
foreach ((array)$clients as $client) {
|
||||
foreach ($clients as $client) {
|
||||
$listenerHash = Entity\Listener::calculateListenerHash($client);
|
||||
$identifier = $client['uid'] . '_' . $listenerHash;
|
||||
$identifier = $client->uid . '_' . $listenerHash;
|
||||
|
||||
// Check for an existing record for this client.
|
||||
if (isset($existingClients[$identifier])) {
|
||||
|
|
|
@ -3,20 +3,27 @@ namespace App\Entity\Repository;
|
|||
|
||||
use App\Doctrine\Repository;
|
||||
use App\Entity;
|
||||
use NowPlaying\Result\CurrentSong;
|
||||
|
||||
class SongRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* Retrieve an existing Song entity or create a new one.
|
||||
*
|
||||
* @param array|string $song_info
|
||||
* @param CurrentSong|array|string $song_info
|
||||
* @param bool $is_radio_play
|
||||
*
|
||||
* @return Entity\Song
|
||||
*/
|
||||
public function getOrCreate($song_info, $is_radio_play = false): Entity\Song
|
||||
{
|
||||
if (!is_array($song_info)) {
|
||||
if ($song_info instanceof CurrentSong) {
|
||||
$song_info = [
|
||||
'text' => $song_info->text,
|
||||
'artist' => $song_info->artist,
|
||||
'title' => $song_info->title,
|
||||
];
|
||||
} elseif (!is_array($song_info)) {
|
||||
$song_info = ['text' => $song_info];
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ use App\Exception;
|
|||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use NowPlaying\Result\CurrentSong;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
/**
|
||||
|
@ -120,6 +121,12 @@ class Song
|
|||
'artist' => $song_info->getArtist(),
|
||||
'title' => $song_info->getTitle(),
|
||||
];
|
||||
} elseif ($song_info instanceof CurrentSong) {
|
||||
$song_info = [
|
||||
'text' => $song_info->text,
|
||||
'artist' => $song_info->artist,
|
||||
'title' => $song_info->title,
|
||||
];
|
||||
} elseif (!is_array($song_info)) {
|
||||
$song_info = [
|
||||
'text' => $song_info,
|
||||
|
|
|
@ -3,6 +3,7 @@ namespace App\Event\Radio;
|
|||
|
||||
use App\Entity\Station;
|
||||
use App\Radio;
|
||||
use NowPlaying\Result\Result;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
class GenerateRawNowPlaying extends Event
|
||||
|
@ -16,23 +17,17 @@ class GenerateRawNowPlaying extends Event
|
|||
|
||||
protected bool $include_clients = false;
|
||||
|
||||
/** @var string|null The preloaded "payload" to supply to the nowplaying adapters, if one is available. */
|
||||
protected ?string $payload;
|
||||
|
||||
/** @var array The composed "raw" NowPlaying data. */
|
||||
protected array $np_raw = [];
|
||||
protected ?Result $result = null;
|
||||
|
||||
public function __construct(
|
||||
Station $station,
|
||||
Radio\Frontend\AbstractFrontend $frontend,
|
||||
array $remotes,
|
||||
$payload = null,
|
||||
$include_clients = false
|
||||
) {
|
||||
$this->station = $station;
|
||||
$this->frontend = $frontend;
|
||||
$this->remotes = $remotes;
|
||||
$this->payload = $payload;
|
||||
$this->include_clients = $include_clients;
|
||||
}
|
||||
|
||||
|
@ -59,18 +54,13 @@ class GenerateRawNowPlaying extends Event
|
|||
return $this->include_clients;
|
||||
}
|
||||
|
||||
public function getPayload(): ?string
|
||||
public function getResult(): Result
|
||||
{
|
||||
return $this->payload;
|
||||
return $this->result ?? Result::blank();
|
||||
}
|
||||
|
||||
public function getRawResponse(): array
|
||||
public function setResult(Result $result): void
|
||||
{
|
||||
return $this->np_raw;
|
||||
}
|
||||
|
||||
public function setRawResponse(array $np): void
|
||||
{
|
||||
$this->np_raw = $np;
|
||||
$this->result = $result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ abstract class AbstractAdapter
|
|||
Logger::getInstance()->info('Adapter "' . static::class . '" stopped.',
|
||||
['station_id' => $station->getId(), 'station_name' => $station->getName()]);
|
||||
} catch (SupervisorLibException $e) {
|
||||
$this->_handleSupervisorException($e, $program_name, $station);
|
||||
$this->handleSupervisorException($e, $program_name, $station);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ abstract class AbstractAdapter
|
|||
Logger::getInstance()->info('Adapter "' . static::class . '" started.',
|
||||
['station_id' => $station->getId(), 'station_name' => $station->getName()]);
|
||||
} catch (SupervisorLibException $e) {
|
||||
$this->_handleSupervisorException($e, $program_name, $station);
|
||||
$this->handleSupervisorException($e, $program_name, $station);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ abstract class AbstractAdapter
|
|||
* @throws NotRunningException
|
||||
* @throws SupervisorException
|
||||
*/
|
||||
protected function _handleSupervisorException(
|
||||
protected function handleSupervisorException(
|
||||
SupervisorLibException $e,
|
||||
$program_name,
|
||||
Entity\Station $station
|
||||
|
|
|
@ -4,14 +4,14 @@ namespace App\Radio\Frontend;
|
|||
use App\Entity;
|
||||
use App\EventDispatcher;
|
||||
use App\Http\Router;
|
||||
use App\Logger;
|
||||
use App\Radio\AbstractAdapter;
|
||||
use App\Settings;
|
||||
use App\Xml\Reader;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
use NowPlaying\Adapter\AdapterAbstract;
|
||||
use NowPlaying\Adapter\AdapterFactory;
|
||||
use NowPlaying\Result\Result;
|
||||
use PhpIP\IP;
|
||||
use PhpIP\IPBlock;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
@ -19,6 +19,8 @@ use Supervisor\Supervisor;
|
|||
|
||||
abstract class AbstractFrontend extends AbstractAdapter
|
||||
{
|
||||
protected AdapterFactory $adapterFactory;
|
||||
|
||||
protected Client $http_client;
|
||||
|
||||
protected Router $router;
|
||||
|
@ -29,20 +31,22 @@ abstract class AbstractFrontend extends AbstractAdapter
|
|||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
Entity\Repository\SettingsRepository $settingsRepo,
|
||||
Entity\Repository\StationMountRepository $stationMountRepo,
|
||||
Supervisor $supervisor,
|
||||
EventDispatcher $dispatcher,
|
||||
AdapterFactory $adapterFactory,
|
||||
Client $client,
|
||||
Router $router
|
||||
Router $router,
|
||||
Entity\Repository\SettingsRepository $settingsRepo,
|
||||
Entity\Repository\StationMountRepository $stationMountRepo
|
||||
) {
|
||||
parent::__construct($em, $supervisor, $dispatcher);
|
||||
|
||||
$this->settingsRepo = $settingsRepo;
|
||||
$this->stationMountRepo = $stationMountRepo;
|
||||
|
||||
$this->adapterFactory = $adapterFactory;
|
||||
$this->http_client = $client;
|
||||
$this->router = $router;
|
||||
|
||||
$this->settingsRepo = $settingsRepo;
|
||||
$this->stationMountRepo = $stationMountRepo;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -183,74 +187,9 @@ abstract class AbstractFrontend extends AbstractAdapter
|
|||
|
||||
abstract public function getAdminUrl(Entity\Station $station, UriInterface $base_url = null): UriInterface;
|
||||
|
||||
/**
|
||||
* @param Entity\Station $station
|
||||
* @param string|null $payload A prepopulated payload (to avoid duplicate web requests)
|
||||
* @param bool $include_clients Whether to try to retrieve detailed listener client info
|
||||
*
|
||||
* @return array Whether the NP update succeeded
|
||||
*/
|
||||
public function getNowPlaying(Entity\Station $station, $payload = null, $include_clients = true): array
|
||||
public function getNowPlaying(Entity\Station $station, bool $includeClients = true): Result
|
||||
{
|
||||
return AdapterAbstract::NOWPLAYING_EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entity\StationMount $mount
|
||||
* @param array $np_aggregate The aggregated nowplaying data for all mounts.
|
||||
* @param array $np The nowplaying data for this specific mount.
|
||||
* @param array|null $clients
|
||||
*
|
||||
* @return array The processed aggregate nowplaying data for all mounts.
|
||||
*/
|
||||
protected function _processNowPlayingForMount(
|
||||
Entity\StationMount $mount,
|
||||
array $np_aggregate,
|
||||
array $np,
|
||||
?array $clients
|
||||
): array {
|
||||
if (null !== $clients) {
|
||||
$original_num_clients = count($clients);
|
||||
|
||||
$np['listeners']['clients'] = Entity\Listener::filterClients($clients);
|
||||
|
||||
$num_clients = count($np['listeners']['clients']);
|
||||
|
||||
// If clients were filtered out, remove them from the listener count as well.
|
||||
if ($num_clients < $original_num_clients) {
|
||||
$client_diff = $original_num_clients - $num_clients;
|
||||
$np['listeners']['total'] -= $client_diff;
|
||||
}
|
||||
|
||||
$np['listeners']['unique'] = $num_clients;
|
||||
$np['listeners']['current'] = $num_clients;
|
||||
|
||||
if ($np['listeners']['unique'] > $np['listeners']['total']) {
|
||||
$np['listeners']['total'] = $np['listeners']['unique'];
|
||||
}
|
||||
} else {
|
||||
$np['listeners']['clients'] = [];
|
||||
}
|
||||
|
||||
Logger::getInstance()->debug('Response for mount point', ['mount' => $mount->getName(), 'response' => $np]);
|
||||
|
||||
$mount->setListenersTotal($np['listeners']['total']);
|
||||
$mount->setListenersUnique($np['listeners']['unique']);
|
||||
$this->em->persist($mount);
|
||||
$this->em->flush();
|
||||
|
||||
if ($mount->getIsDefault()) {
|
||||
$np_aggregate['current_song'] = $np['current_song'];
|
||||
$np_aggregate['meta'] = $np['meta'];
|
||||
}
|
||||
|
||||
$np_aggregate['listeners']['clients'] = array_merge((array)$np_aggregate['listeners']['clients'],
|
||||
(array)$np['listeners']['clients']);
|
||||
$np_aggregate['listeners']['current'] += $np['listeners']['current'];
|
||||
$np_aggregate['listeners']['unique'] += $np['listeners']['unique'];
|
||||
$np_aggregate['listeners']['total'] += $np['listeners']['total'];
|
||||
|
||||
return $np_aggregate;
|
||||
return Result::blank();
|
||||
}
|
||||
|
||||
protected function _processCustomConfig($custom_config_raw)
|
||||
|
|
|
@ -9,7 +9,8 @@ use App\Utilities;
|
|||
use App\Xml\Reader;
|
||||
use App\Xml\Writer;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
use NowPlaying\Adapter\AdapterAbstract;
|
||||
use NowPlaying\Adapter\AdapterFactory;
|
||||
use NowPlaying\Result\Result;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
class Icecast extends AbstractFrontend
|
||||
|
@ -19,34 +20,48 @@ class Icecast extends AbstractFrontend
|
|||
public const LOGLEVEL_WARN = 2;
|
||||
public const LOGLEVEL_ERROR = 1;
|
||||
|
||||
public function getNowPlaying(Entity\Station $station, $payload = null, $include_clients = true): array
|
||||
public function getNowPlaying(Entity\Station $station, bool $includeClients = true): Result
|
||||
{
|
||||
$fe_config = $station->getFrontendConfig();
|
||||
$radio_port = $fe_config->getPort();
|
||||
$feConfig = $station->getFrontendConfig();
|
||||
$radioPort = $feConfig->getPort();
|
||||
|
||||
$base_url = 'http://' . (Settings::getInstance()->isDocker() ? 'stations' : 'localhost') . ':' . $radio_port;
|
||||
$baseUrl = 'http://' . (Settings::getInstance()->isDocker() ? 'stations' : 'localhost') . ':' . $radioPort;
|
||||
|
||||
$np_adapter = new \NowPlaying\Adapter\Icecast($base_url, $this->http_client);
|
||||
$np_adapter->setAdminPassword($fe_config->getAdminPassword());
|
||||
$npAdapter = $this->adapterFactory->getAdapter(
|
||||
AdapterFactory::ADAPTER_ICECAST,
|
||||
$baseUrl,
|
||||
$feConfig->getAdminPassword()
|
||||
);
|
||||
|
||||
$np_final = AdapterAbstract::NOWPLAYING_EMPTY;
|
||||
$np_final['listeners']['clients'] = [];
|
||||
$defaultResult = Result::blank();
|
||||
$otherResults = [];
|
||||
|
||||
try {
|
||||
foreach ($station->getMounts() as $mount) {
|
||||
/** @var Entity\StationMount $mount */
|
||||
$np_final = $this->_processNowPlayingForMount(
|
||||
$mount,
|
||||
$np_final,
|
||||
$np_adapter->getNowPlaying($mount->getName()),
|
||||
$include_clients ? $np_adapter->getClients($mount->getName(), true) : null
|
||||
);
|
||||
$result = $npAdapter->getNowPlaying($mount->getName(), $includeClients);
|
||||
|
||||
$mount->setListenersTotal($result->listeners->total);
|
||||
$mount->setListenersUnique($result->listeners->unique);
|
||||
$this->em->persist($mount);
|
||||
|
||||
if ($mount->getIsDefault()) {
|
||||
$defaultResult = $result;
|
||||
} else {
|
||||
$otherResults[] = $result;
|
||||
}
|
||||
}
|
||||
|
||||
$this->em->flush();
|
||||
|
||||
foreach ($otherResults as $otherResult) {
|
||||
$defaultResult = $defaultResult->merge($otherResult);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Logger::getInstance()->error(sprintf('NowPlaying adapter error: %s', $e->getMessage()));
|
||||
}
|
||||
|
||||
return $np_final;
|
||||
return $defaultResult;
|
||||
}
|
||||
|
||||
public function read(Entity\Station $station): bool
|
||||
|
|
|
@ -5,8 +5,8 @@ use App\Entity;
|
|||
use App\Logger;
|
||||
use App\Settings;
|
||||
use App\Utilities;
|
||||
use NowPlaying\Adapter\AdapterAbstract;
|
||||
use NowPlaying\Adapter\SHOUTcast2;
|
||||
use NowPlaying\Adapter\AdapterFactory;
|
||||
use NowPlaying\Result\Result;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
|
@ -48,37 +48,50 @@ class SHOUTcast extends AbstractFrontend
|
|||
: false;
|
||||
}
|
||||
|
||||
public function getNowPlaying(Entity\Station $station, $payload = null, $include_clients = true): array
|
||||
public function getNowPlaying(Entity\Station $station, bool $includeClients = true): Result
|
||||
{
|
||||
$fe_config = $station->getFrontendConfig();
|
||||
$radio_port = $fe_config->getPort();
|
||||
$feConfig = $station->getFrontendConfig();
|
||||
$radioPort = $feConfig->getPort();
|
||||
$baseUrl = 'http://' . (Settings::getInstance()->isDocker() ? 'stations' : 'localhost') . ':' . $radioPort;
|
||||
|
||||
$base_url = 'http://' . (Settings::getInstance()->isDocker() ? 'stations' : 'localhost') . ':' . $radio_port;
|
||||
$npAdapter = $this->adapterFactory->getAdapter(
|
||||
AdapterFactory::ADAPTER_SHOUTCAST2,
|
||||
$baseUrl,
|
||||
$feConfig->getAdminPassword()
|
||||
);
|
||||
|
||||
$np_adapter = new SHOUTcast2($base_url, $this->http_client);
|
||||
$np_adapter->setAdminPassword($fe_config->getAdminPassword());
|
||||
|
||||
$np_final = AdapterAbstract::NOWPLAYING_EMPTY;
|
||||
$np_final['listeners']['clients'] = [];
|
||||
$defaultResult = Result::blank();
|
||||
$otherResults = [];
|
||||
|
||||
try {
|
||||
$sid = 0;
|
||||
|
||||
foreach ($station->getMounts() as $mount) {
|
||||
/** @var Entity\StationMount $mount */
|
||||
$sid++;
|
||||
$np_final = $this->_processNowPlayingForMount(
|
||||
$mount,
|
||||
$np_final,
|
||||
$np_adapter->getNowPlaying($sid),
|
||||
$include_clients ? $np_adapter->getClients($sid, true) : null
|
||||
);
|
||||
|
||||
$result = $npAdapter->getNowPlaying($sid, $includeClients);
|
||||
|
||||
$mount->setListenersTotal($result->listeners->total);
|
||||
$mount->setListenersUnique($result->listeners->unique);
|
||||
$this->em->persist($mount);
|
||||
|
||||
if ($mount->getIsDefault()) {
|
||||
$defaultResult = $result;
|
||||
} else {
|
||||
$otherResults[] = $result;
|
||||
}
|
||||
}
|
||||
|
||||
$this->em->flush();
|
||||
|
||||
foreach ($otherResults as $otherResult) {
|
||||
$defaultResult = $defaultResult->merge($otherResult);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Logger::getInstance()->error(sprintf('NowPlaying adapter error: %s', $e->getMessage()));
|
||||
}
|
||||
|
||||
return $np_final;
|
||||
return $defaultResult;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -6,7 +6,8 @@ use Doctrine\ORM\EntityManagerInterface;
|
|||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
use Monolog\Logger;
|
||||
use NowPlaying\Adapter\AdapterAbstract;
|
||||
use NowPlaying\Adapter\AdapterFactory;
|
||||
use NowPlaying\Result\Result;
|
||||
|
||||
abstract class AbstractRemote
|
||||
{
|
||||
|
@ -18,33 +19,62 @@ abstract class AbstractRemote
|
|||
|
||||
protected Logger $logger;
|
||||
|
||||
protected AdapterFactory $adapterFactory;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
Entity\Repository\SettingsRepository $settingsRepo,
|
||||
Client $http_client,
|
||||
Logger $logger
|
||||
Logger $logger,
|
||||
AdapterFactory $adapterFactory
|
||||
) {
|
||||
$this->em = $em;
|
||||
$this->settingsRepo = $settingsRepo;
|
||||
$this->http_client = $http_client;
|
||||
$this->logger = $logger;
|
||||
$this->adapterFactory = $adapterFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Result $np
|
||||
* @param Entity\StationRemote $remote
|
||||
* @param array $np_aggregate
|
||||
* @param bool $include_clients
|
||||
* @param bool $includeClients
|
||||
*
|
||||
* @return array The aggregated now-playing result.
|
||||
* @return Result The aggregated now-playing result.
|
||||
*/
|
||||
public function updateNowPlaying(
|
||||
Result $np,
|
||||
Entity\StationRemote $remote,
|
||||
$np_aggregate,
|
||||
bool $include_clients = false
|
||||
): array {
|
||||
return $np_aggregate;
|
||||
bool $includeClients = false
|
||||
): Result {
|
||||
$adapterType = $this->getAdapterType();
|
||||
|
||||
$npAdapter = $this->adapterFactory->getAdapter(
|
||||
$adapterType,
|
||||
$remote->getUrl(),
|
||||
$remote->getAdminPassword()
|
||||
);
|
||||
|
||||
try {
|
||||
$npRemote = $npAdapter->getNowPlaying($remote->getMount(), $includeClients);
|
||||
|
||||
$this->logger->debug('NowPlaying adapter response', ['response' => $npRemote]);
|
||||
|
||||
$remote->setListenersTotal($npRemote->listeners->total);
|
||||
$remote->setListenersUnique($npRemote->listeners->unique);
|
||||
$this->em->persist($remote);
|
||||
$this->em->flush();
|
||||
|
||||
return $np->merge($npRemote);
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error(sprintf('NowPlaying adapter error: %s', $e->getMessage()));
|
||||
}
|
||||
|
||||
return $np;
|
||||
}
|
||||
|
||||
abstract protected function getAdapterType(): string;
|
||||
|
||||
/**
|
||||
* Return the likely "public" listen URL for the remote.
|
||||
*
|
||||
|
@ -58,7 +88,7 @@ abstract class AbstractRemote
|
|||
|
||||
return (!empty($custom_listen_url))
|
||||
? $custom_listen_url
|
||||
: $this->_getRemoteUrl($remote, $remote->getMount());
|
||||
: $this->getRemoteUrl($remote, $remote->getMount());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,7 +99,7 @@ abstract class AbstractRemote
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _getRemoteUrl(Entity\StationRemote $remote, $custom_path = null): string
|
||||
protected function getRemoteUrl(Entity\StationRemote $remote, $custom_path = null): string
|
||||
{
|
||||
$uri = new Uri($remote->getUrl());
|
||||
|
||||
|
@ -77,111 +107,4 @@ abstract class AbstractRemote
|
|||
? (string)$uri->withPath($custom_path)
|
||||
: (string)$uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entity\StationRemote $remote
|
||||
* @param array $np_aggregate
|
||||
* @param string $adapter_class
|
||||
* @param bool $include_clients
|
||||
*
|
||||
* @return array The resulting aggregated now-playing response.
|
||||
*/
|
||||
protected function _updateNowPlayingFromAdapter(
|
||||
Entity\StationRemote $remote,
|
||||
$np_aggregate,
|
||||
$adapter_class,
|
||||
bool $include_clients = false
|
||||
): array {
|
||||
/** @var AdapterAbstract $np_adapter */
|
||||
$np_adapter = new $adapter_class($remote->getUrl(), $this->http_client);
|
||||
|
||||
try {
|
||||
$adminPassword = $remote->getAdminPassword();
|
||||
if (!empty($adminPassword)) {
|
||||
$np_adapter->setAdminPassword($adminPassword);
|
||||
}
|
||||
|
||||
$np = $np_adapter->getNowPlaying($remote->getMount());
|
||||
if (empty($np)) {
|
||||
return $np_aggregate;
|
||||
}
|
||||
|
||||
$clients = ($include_clients && !empty($adminPassword))
|
||||
? $np_adapter->getClients($remote->getMount(), true)
|
||||
: null;
|
||||
|
||||
$this->logger->debug('NowPlaying adapter response', ['response' => $np, 'clients' => $clients]);
|
||||
|
||||
return $this->_mergeNowPlaying(
|
||||
$remote,
|
||||
$np_aggregate,
|
||||
$np,
|
||||
$clients
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error(sprintf('NowPlaying adapter error: %s', $e->getMessage()));
|
||||
}
|
||||
|
||||
return $np_aggregate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entity\StationRemote $remote
|
||||
* @param array $np_aggregate
|
||||
* @param array $np
|
||||
* @param array|null $clients
|
||||
*
|
||||
* @return array The composed aggregate now-playing response.
|
||||
*/
|
||||
protected function _mergeNowPlaying(
|
||||
Entity\StationRemote $remote,
|
||||
array $np_aggregate,
|
||||
array $np,
|
||||
?array $clients
|
||||
): array {
|
||||
if (null !== $clients) {
|
||||
$original_num_clients = count($clients);
|
||||
|
||||
$np['listeners']['clients'] = Entity\Listener::filterClients($clients);
|
||||
|
||||
$num_clients = count($np['listeners']['clients']);
|
||||
|
||||
// If clients were filtered out, remove them from the listener count as well.
|
||||
if ($num_clients < $original_num_clients) {
|
||||
$client_diff = $original_num_clients - $num_clients;
|
||||
$np['listeners']['total'] -= $client_diff;
|
||||
}
|
||||
|
||||
$np['listeners']['unique'] = $num_clients;
|
||||
$np['listeners']['current'] = $num_clients;
|
||||
|
||||
if ($np['listeners']['unique'] > $np['listeners']['total']) {
|
||||
$np['listeners']['total'] = $np['listeners']['unique'];
|
||||
}
|
||||
} else {
|
||||
$np['listeners']['clients'] = [];
|
||||
}
|
||||
|
||||
$this->logger->debug('Response for remote relay', ['remote' => $remote->getDisplayName(), 'response' => $np]);
|
||||
|
||||
$remote->setListenersTotal($np['listeners']['total']);
|
||||
$remote->setListenersUnique($np['listeners']['unique']);
|
||||
$this->em->persist($remote);
|
||||
$this->em->flush();
|
||||
|
||||
if ($np_aggregate['meta']['status'] === 'offline' && $np['meta']['status'] === 'online') {
|
||||
$np_aggregate['current_song'] = $np['current_song'];
|
||||
$np_aggregate['meta'] = $np['meta'];
|
||||
}
|
||||
|
||||
$np_aggregate['listeners']['clients'] = array_merge(
|
||||
(array)$np_aggregate['listeners']['clients'],
|
||||
(array)$np['listeners']['clients']
|
||||
);
|
||||
$np_aggregate['listeners']['current'] += $np['listeners']['current'];
|
||||
$np_aggregate['listeners']['unique'] += $np['listeners']['unique'];
|
||||
$np_aggregate['listeners']['total'] += $np['listeners']['total'];
|
||||
|
||||
return $np_aggregate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,11 +5,15 @@ use App\Entity;
|
|||
use App\Settings;
|
||||
use GuzzleHttp\Psr7\Uri;
|
||||
use InvalidArgumentException;
|
||||
use NowPlaying\Result\Result;
|
||||
|
||||
class AzuraRelay extends AbstractRemote
|
||||
{
|
||||
public function updateNowPlaying(Entity\StationRemote $remote, $np_aggregate, bool $include_clients = false): array
|
||||
{
|
||||
public function updateNowPlaying(
|
||||
Result $np,
|
||||
Entity\StationRemote $remote,
|
||||
bool $includeClients = false
|
||||
): Result {
|
||||
$station = $remote->getStation();
|
||||
$relay = $remote->getRelay();
|
||||
|
||||
|
@ -17,24 +21,30 @@ class AzuraRelay extends AbstractRemote
|
|||
throw new InvalidArgumentException('AzuraRelay remote must have a corresponding relay.');
|
||||
}
|
||||
|
||||
$relay_np = $relay->getNowplaying();
|
||||
$npRawRelay = $relay->getNowplaying();
|
||||
|
||||
if (isset($relay_np[$station->getId()][$remote->getMount()])) {
|
||||
$np_new = $relay_np[$station->getId()][$remote->getMount()];
|
||||
if (isset($npRawRelay[$station->getId()][$remote->getMount()])) {
|
||||
$npRaw = $npRawRelay[$station->getId()][$remote->getMount()];
|
||||
|
||||
$clients = ($include_clients)
|
||||
? $np_new['listeners']['clients']
|
||||
: null;
|
||||
$npNew = Result::fromArray($npRaw);
|
||||
|
||||
$np_aggregate = $this->_mergeNowPlaying(
|
||||
$remote,
|
||||
$np_aggregate,
|
||||
$np_new,
|
||||
$clients
|
||||
);
|
||||
$this->logger->debug('Response for remote relay',
|
||||
['remote' => $remote->getDisplayName(), 'response' => $npNew]);
|
||||
|
||||
$remote->setListenersTotal($np['listeners']['total']);
|
||||
$remote->setListenersUnique($np['listeners']['unique']);
|
||||
$this->em->persist($remote);
|
||||
$this->em->flush();
|
||||
|
||||
return $np->merge($npNew);
|
||||
}
|
||||
|
||||
return $np_aggregate;
|
||||
return $np;
|
||||
}
|
||||
|
||||
protected function getAdapterType(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,20 +1,12 @@
|
|||
<?php
|
||||
namespace App\Radio\Remote;
|
||||
|
||||
use App\Entity;
|
||||
use NowPlaying\Adapter\AdapterFactory;
|
||||
|
||||
class Icecast extends AbstractRemote
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function updateNowPlaying(Entity\StationRemote $remote, $np_aggregate, bool $include_clients = false): array
|
||||
protected function getAdapterType(): string
|
||||
{
|
||||
return $this->_updateNowPlayingFromAdapter(
|
||||
$remote,
|
||||
$np_aggregate,
|
||||
\NowPlaying\Adapter\Icecast::class,
|
||||
$include_clients
|
||||
);
|
||||
return AdapterFactory::ADAPTER_ICECAST;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,25 +2,18 @@
|
|||
namespace App\Radio\Remote;
|
||||
|
||||
use App\Entity;
|
||||
use NowPlaying\Adapter\AdapterFactory;
|
||||
|
||||
class SHOUTcast1 extends AbstractRemote
|
||||
{
|
||||
protected function getAdapterType(): string
|
||||
{
|
||||
return AdapterFactory::ADAPTER_SHOUTCAST1;
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
public function getPublicUrl(Entity\StationRemote $remote): string
|
||||
{
|
||||
return $this->_getRemoteUrl($remote, '/;stream.nsv');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function updateNowPlaying(Entity\StationRemote $remote, $np_aggregate, bool $include_clients = false): array
|
||||
{
|
||||
return $this->_updateNowPlayingFromAdapter(
|
||||
$remote,
|
||||
$np_aggregate,
|
||||
\NowPlaying\Adapter\SHOUTcast1::class,
|
||||
$include_clients
|
||||
);
|
||||
return $this->getRemoteUrl($remote, '/;stream.nsv');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,12 @@
|
|||
<?php
|
||||
namespace App\Radio\Remote;
|
||||
|
||||
use App\Entity;
|
||||
use NowPlaying\Adapter\AdapterFactory;
|
||||
|
||||
class SHOUTcast2 extends AbstractRemote
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function updateNowPlaying(Entity\StationRemote $remote, $np_aggregate, bool $include_clients = false): array
|
||||
protected function getAdapterType(): string
|
||||
{
|
||||
return $this->_updateNowPlayingFromAdapter(
|
||||
$remote,
|
||||
$np_aggregate,
|
||||
\NowPlaying\Adapter\SHOUTcast2::class,
|
||||
$include_clients
|
||||
);
|
||||
return AdapterFactory::ADAPTER_SHOUTCAST2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ use GuzzleHttp\Psr7\Uri;
|
|||
use InfluxDB\Database;
|
||||
use InfluxDB\Point;
|
||||
use Monolog\Logger;
|
||||
use NowPlaying\Adapter\AdapterAbstract;
|
||||
use NowPlaying\Result\Result;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
@ -96,7 +96,6 @@ class NowPlaying extends AbstractTask implements EventSubscriberInterface
|
|||
GenerateRawNowPlaying::class => [
|
||||
['loadRawFromFrontend', 10],
|
||||
['addToRawFromRemotes', 0],
|
||||
['cleanUpRawOutput', -10],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
@ -199,10 +198,10 @@ class NowPlaying extends AbstractTask implements EventSubscriberInterface
|
|||
$station,
|
||||
$frontend_adapter,
|
||||
$remote_adapters,
|
||||
null,
|
||||
$include_clients);
|
||||
$this->event_dispatcher->dispatch($event);
|
||||
$np_raw = $event->getRawResponse();
|
||||
|
||||
$npResult = $event->getResult();
|
||||
} catch (Exception $e) {
|
||||
$this->logger->log(Logger::ERROR, $e->getMessage(), [
|
||||
'file' => $e->getFile(),
|
||||
|
@ -210,22 +209,27 @@ class NowPlaying extends AbstractTask implements EventSubscriberInterface
|
|||
'code' => $e->getCode(),
|
||||
]);
|
||||
|
||||
$np_raw = AdapterAbstract::NOWPLAYING_EMPTY;
|
||||
$npResult = Result::blank();
|
||||
}
|
||||
|
||||
$this->logger->debug('Final NowPlaying Response for Station', [
|
||||
'id' => $station->getId(),
|
||||
'name' => $station->getName(),
|
||||
'np' => $np_raw,
|
||||
'np' => $npResult,
|
||||
]);
|
||||
|
||||
$np = new Entity\Api\NowPlaying;
|
||||
$uri_empty = new Uri('');
|
||||
|
||||
$np->station = $station->api($frontend_adapter, $remote_adapters, $uri_empty);
|
||||
$np->listeners = new Entity\Api\NowPlayingListeners($np_raw['listeners']);
|
||||
$np->listeners = new Entity\Api\NowPlayingListeners([
|
||||
'current' => $npResult->listeners->current,
|
||||
'unique' => $npResult->listeners->unique,
|
||||
'total' => $npResult->listeners->total,
|
||||
]
|
||||
);
|
||||
|
||||
if (empty($np_raw['current_song']['text'])) {
|
||||
if (empty($npResult->currentSong->text)) {
|
||||
$song_obj = $this->song_repo->getOrCreate(['text' => 'Stream Offline'], true);
|
||||
|
||||
$offline_sh = new Entity\Api\NowPlayingCurrentSong;
|
||||
|
@ -252,7 +256,7 @@ class NowPlaying extends AbstractTask implements EventSubscriberInterface
|
|||
$np->live = new Entity\Api\NowPlayingLive(false);
|
||||
} else {
|
||||
// Pull from current NP data if song details haven't changed .
|
||||
$current_song_hash = Entity\Song::getSongHash($np_raw['current_song']);
|
||||
$current_song_hash = Entity\Song::getSongHash($npResult->currentSong);
|
||||
|
||||
if ($np_old instanceof Entity\Api\NowPlaying &&
|
||||
0 === strcmp($current_song_hash, $np_old->now_playing->song->id)) {
|
||||
|
@ -266,7 +270,7 @@ class NowPlaying extends AbstractTask implements EventSubscriberInterface
|
|||
} else {
|
||||
// SongHistory registration must ALWAYS come before the history/nextsong calls
|
||||
// otherwise they will not have up-to-date database info!
|
||||
$song_obj = $this->song_repo->getOrCreate($np_raw['current_song'], true);
|
||||
$song_obj = $this->song_repo->getOrCreate($npResult->currentSong, true);
|
||||
$sh_obj = $this->history_repo->register($song_obj, $station, $np);
|
||||
|
||||
$np->song_history = $this->history_repo->getHistoryApi(
|
||||
|
@ -283,8 +287,8 @@ class NowPlaying extends AbstractTask implements EventSubscriberInterface
|
|||
}
|
||||
|
||||
// Update detailed listener statistics, if they exist for the station
|
||||
if ($include_clients && isset($np_raw['listeners']['clients'])) {
|
||||
$this->listener_repo->update($station, $np_raw['listeners']['clients']);
|
||||
if ($include_clients && null !== $npResult->clients) {
|
||||
$this->listener_repo->update($station, $npResult->clients);
|
||||
}
|
||||
|
||||
// Detect and report live DJ status
|
||||
|
@ -403,39 +407,27 @@ class NowPlaying extends AbstractTask implements EventSubscriberInterface
|
|||
|
||||
public function loadRawFromFrontend(GenerateRawNowPlaying $event): void
|
||||
{
|
||||
$np_raw = $event
|
||||
$result = $event
|
||||
->getFrontend()
|
||||
->getNowPlaying($event->getStation(), $event->getPayload(), $event->includeClients());
|
||||
->getNowPlaying($event->getStation(), $event->includeClients());
|
||||
|
||||
$event->setRawResponse($np_raw);
|
||||
$event->setResult($result);
|
||||
}
|
||||
|
||||
public function addToRawFromRemotes(GenerateRawNowPlaying $event): void
|
||||
{
|
||||
$np_raw = $event->getRawResponse();
|
||||
$result = $event->getResult();
|
||||
|
||||
// Loop through all remotes and update NP data accordingly.
|
||||
foreach ($event->getRemotes() as $ra_proxy) {
|
||||
$np_raw = $ra_proxy->getAdapter()->updateNowPlaying(
|
||||
$result = $ra_proxy->getAdapter()->updateNowPlaying(
|
||||
$result,
|
||||
$ra_proxy->getRemote(),
|
||||
$np_raw,
|
||||
$event->includeClients()
|
||||
);
|
||||
}
|
||||
|
||||
$event->setRawResponse($np_raw);
|
||||
}
|
||||
|
||||
public function cleanUpRawOutput(GenerateRawNowPlaying $event): void
|
||||
{
|
||||
$np_raw = $event->getRawResponse();
|
||||
|
||||
array_walk($np_raw['current_song'], function (&$value) {
|
||||
$value = htmlspecialchars_decode($value);
|
||||
$value = trim($value);
|
||||
});
|
||||
|
||||
$event->setRawResponse($np_raw);
|
||||
$event->setResult($result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue