Passed
Pull Request — master (#992)
by
unknown
02:18
created

RadioApiController::getRadioStreamData()   A

Complexity

Conditions 3
Paths 8

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 9
c 0
b 0
f 0
dl 0
loc 12
rs 9.9666
cc 3
nc 8
nop 1
1
<?php declare(strict_types=1);
2
3
/**
4
 * ownCloud - Music app
5
 *
6
 * This file is licensed under the Affero General Public License version 3 or
7
 * later. See the COPYING file.
8
 *
9
 * @author Pauli Järvinen <[email protected]>
10
 * @copyright Pauli Järvinen 2020, 2021
11
 */
12
13
namespace OCA\Music\Controller;
14
15
use OCP\AppFramework\Controller;
16
use OCP\AppFramework\Http;
17
use OCP\AppFramework\Http\JSONResponse;
18
19
use OCP\Files\Folder;
20
use OCP\IRequest;
21
22
use OCA\Music\AppFramework\BusinessLayer\BusinessLayerException;
23
use OCA\Music\AppFramework\Core\Logger;
24
use OCA\Music\BusinessLayer\RadioStationBusinessLayer;
25
use OCA\Music\Http\ErrorResponse;
26
use OCA\Music\Utility\PlaylistFileService;
27
use OCA\Music\Utility\Util;
28
use OCA\Music\Utility\RadioMetadata;
29
30
class RadioApiController extends Controller {
31
	private $businessLayer;
32
	private $playlistFileService;
33
	private $userId;
34
	private $userFolder;
35
	private $logger;
36
37
	public function __construct(string $appname,
38
								IRequest $request,
39
								RadioStationBusinessLayer $businessLayer,
40
								PlaylistFileService $playlistFileService,
41
								?string $userId,
42
								?Folder $userFolder,
43
								Logger $logger) {
44
		parent::__construct($appname, $request);
45
		$this->businessLayer = $businessLayer;
46
		$this->playlistFileService = $playlistFileService;
47
		$this->userId = $userId ?? ''; // ensure non-null to satisfy Scrutinizer; the null case should happen only when the user has already logged out
48
		$this->userFolder = $userFolder;
49
		$this->logger = $logger;
50
	}
51
52
	/**
53
	 * lists all radio stations
54
	 *
55
	 * @NoAdminRequired
56
	 * @NoCSRFRequired
57
	 */
58
	public function getAll() {
59
		$stations = $this->businessLayer->findAll($this->userId);
60
		return Util::arrayMapMethod($stations, 'toApi');
61
	}
62
63
	/**
64
	 * creates a station
65
	 *
66
	 * @NoAdminRequired
67
	 * @NoCSRFRequired
68
	 */
69
	public function create($name, $streamUrl, $homeUrl) {
70
		if ($streamUrl === null) {
71
			return new ErrorResponse(Http::STATUS_BAD_REQUEST, "Mandatory argument 'streamUrl' not given");
72
		} else {
73
			$station = $this->businessLayer->create($this->userId, $name, $streamUrl, $homeUrl);
74
			return $station->toApi();
75
		}
76
	}
77
78
	/**
79
	 * deletes a station
80
	 *
81
	 * @NoAdminRequired
82
	 * @NoCSRFRequired
83
	 */
84
	public function delete(int $id) {
85
		try {
86
			$this->businessLayer->delete($id, $this->userId);
87
			return [];
88
		} catch (BusinessLayerException $ex) {
89
			return new ErrorResponse(Http::STATUS_NOT_FOUND, $ex->getMessage());
90
		}
91
	}
92
93
	/**
94
	 * get a single radio station
95
	 *
96
	 * @NoAdminRequired
97
	 * @NoCSRFRequired
98
	 */
99
	public function get(int $id) {
100
		try {
101
			$station = $this->businessLayer->find($id, $this->userId);
102
			return $station->toAPI();
103
		} catch (BusinessLayerException $ex) {
104
			return new ErrorResponse(Http::STATUS_NOT_FOUND, $ex->getMessage());
105
		}
106
	}
107
108
	/**
109
	 * update a station
110
	 *
111
	 * @NoAdminRequired
112
	 * @NoCSRFRequired
113
	 */
114
	public function update(int $id, string $name = null, string $streamUrl = null, string $homeUrl = null) {
115
		if ($name === null && $streamUrl === null && $homeUrl === null) {
116
			return new ErrorResponse(Http::STATUS_BAD_REQUEST, "at least one of the args ['name', 'streamUrl', 'homrUrl'] must be given");
117
		}
118
119
		try {
120
			$station = $this->businessLayer->find($id, $this->userId);
121
			if ($name !== null) {
122
				$station->setName($name);
123
			}
124
			if ($streamUrl !== null) {
125
				$station->setStreamUrl($streamUrl);
126
			}
127
			if ($homeUrl !== null) {
128
				$station->setHomeUrl($homeUrl);
129
			}
130
			$this->businessLayer->update($station);
131
132
			return new JSONResponse($station->toApi());
133
		} catch (BusinessLayerException $ex) {
134
			return new ErrorResponse(Http::STATUS_NOT_FOUND, $ex->getMessage());
135
		}
136
	}
137
138
	/**
139
	 * export all radio stations to a file
140
	 *
141
	 * @param string $name target file name without the file extension
142
	 * @param string $path parent folder path
143
	 * @param string $oncollision action to take on file name collision,
144
	 *								supported values:
145
	 *								- 'overwrite' The existing file will be overwritten
146
	 *								- 'keepboth' The new file is named with a suffix to make it unique
147
	 *								- 'abort' (default) The operation will fail
148
	 *
149
	 * @NoAdminRequired
150
	 * @NoCSRFRequired
151
	 */
152
	public function exportAllToFile(string $name, string $path, string $oncollision) {
153
		if ($this->userFolder === null) {
154
			// This shouldn't get actually run. The folder may be null in case the user has already logged out.
155
			// But in that case, the framework should block the execution before it reaches here.
156
			return new ErrorResponse(Http::STATUS_UNAUTHORIZED, 'no valid user folder got');
157
		}
158
		try {
159
			$exportedFilePath = $this->playlistFileService->exportRadioStationsToFile(
160
					$this->userId, $this->userFolder, $path, $name . '.m3u8', $oncollision);
161
			return new JSONResponse(['wrote_to_file' => $exportedFilePath]);
162
		} catch (\OCP\Files\NotFoundException $ex) {
163
			return new ErrorResponse(Http::STATUS_NOT_FOUND, 'folder not found');
164
		} catch (\RuntimeException $ex) {
165
			return new ErrorResponse(Http::STATUS_CONFLICT, $ex->getMessage());
166
		} catch (\OCP\Files\NotPermittedException $ex) {
167
			return new ErrorResponse(Http::STATUS_FORBIDDEN, 'user is not allowed to write to the target file');
168
		}
169
	}
170
171
	/**
172
	 * import radio stations from a file
173
	 * @param string $filePath path of the file to import
174
	 *
175
	 * @NoAdminRequired
176
	 * @NoCSRFRequired
177
	 */
178
	public function importFromFile(string $filePath) {
179
		if ($this->userFolder === null) {
180
			// This shouldn't get actually run. The folder may be null in case the user has already logged out.
181
			// But in that case, the framework should block the execution before it reaches here.
182
			return new ErrorResponse(Http::STATUS_UNAUTHORIZED, 'no valid user folder got');
183
		}
184
		try {
185
			$result = $this->playlistFileService->importRadioStationsFromFile($this->userId, $this->userFolder, $filePath);
186
			$result['stations'] = Util::arrayMapMethod($result['stations'], 'toApi');
187
			return $result;
188
		} catch (\OCP\Files\NotFoundException $ex) {
189
			return new ErrorResponse(Http::STATUS_NOT_FOUND, 'playlist file not found');
190
		} catch (\UnexpectedValueException $ex) {
191
			return new ErrorResponse(Http::STATUS_UNSUPPORTED_MEDIA_TYPE, $ex->getMessage());
192
		}
193
	}
194
195
	/**
196
	 * reset all the radio stations of the user
197
	 *
198
	 * @NoAdminRequired
199
	 * @NoCSRFRequired
200
	 */
201
	public function resetAll() {
202
		$this->businessLayer->deleteAll($this->userId);
203
		return new JSONResponse(['success' => true]);
204
	}
205
206
	/**
207
	* get radio metadata from url
208
	*
209
	* @NoAdminRequired
210
	* @NoCSRFRequired
211
	*/
212
213
	public function getRadioURLData(int $id) {
214
		try {
215
			$response = "";
216
			$station = $this->businessLayer->find($id, $this->userId);
217
			$stapi = $station->toAPI();
218
			if (isset($stapi['stream_url'])) {
219
				$parse_url = parse_url($stapi['stream_url']);
220
				$response = RadioMetadata::fetchUrlData($parse_url['scheme'] . '://' . $parse_url['host'] . ':' . $parse_url['port'] . '/7.html');
221
			}
222
			return new JSONResponse($response);
0 ignored issues
show
Bug introduced by
It seems like $response can also be of type string; however, parameter $data of OCP\AppFramework\Http\JSONResponse::__construct() does only seem to accept array|object, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

222
			return new JSONResponse(/** @scrutinizer ignore-type */ $response);
Loading history...
223
224
		} catch (BusinessLayerException $ex) {
225
			return new ErrorResponse(Http::STATUS_NOT_FOUND, $ex->getMessage());
226
		}
227
	}
228
229
	/**
230
	* get radio metadata from stream
231
	*
232
	* @NoAdminRequired
233
	* @NoCSRFRequired
234
	*/
235
236
	public function getRadioStreamData(int $id) {
237
		try {
238
			$response = "";
239
			$station = $this->businessLayer->find($id, $this->userId);
240
			$stapi = $station->toAPI();
241
			if (isset($stapi['stream_url'])) {
242
				$response = RadioMetadata::fetchStreamData($stapi['stream_url'], 1, 1);
243
			}
244
			return new JSONResponse($response);
0 ignored issues
show
Bug introduced by
$response of type mixed|string is incompatible with the type array|object expected by parameter $data of OCP\AppFramework\Http\JSONResponse::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

244
			return new JSONResponse(/** @scrutinizer ignore-type */ $response);
Loading history...
245
246
		} catch (BusinessLayerException $ex) {
247
			return new ErrorResponse(Http::STATUS_NOT_FOUND, $ex->getMessage());
248
		}
249
	}
250
}
251