Passed
Push — feature/786_podcasts ( 9814c8...5eb2d3 )
by Pauli
02:30
created

PodcastEpisode::extractSuffixFromUrl()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 10
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 9
nc 3
nop 1
dl 0
loc 10
rs 9.9666
c 0
b 0
f 0
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 2021
11
 */
12
13
namespace OCA\Music\Db;
14
15
use \OCP\AppFramework\Db\Entity;
16
use \OCA\Music\Utility\Util;
17
18
/**
19
 * @method string getUserId()
20
 * @method void setUserId(string $userId)
21
 * @method int getChannelId()
22
 * @method void setChannelId(int $id)
23
 * @method string getStreamUrl()
24
 * @method setStreamUrl(string $url)
25
 * @method string getMimetype()
26
 * @method setMimetype(string $mime)
27
 * @method int getSize()
28
 * @method void setSize(int $size)
29
 * @method int getDuration()
30
 * @method void setDuration(int $duration)
31
 * @method string getGuid()
32
 * @method void setGuid(string $guid)
33
 * @method string getGuidHash()
34
 * @method void setGuidHash(string $guidHash)
35
 * @method string getTitle()
36
 * @method void setTitle(string $title)
37
 * @method int getEpisode()
38
 * @method void setEpisode(int $episode)
39
 * @method string getLinkUrl()
40
 * @method void setLinkUrl(string $url)
41
 * @method string getPublished()
42
 * @method void setPublished(string $timestamp)
43
 * @method string getKeywords()
44
 * @method void setKeywords(string $keywords)
45
 * @method string getCopyright()
46
 * @method void setCopyright(string $copyright)
47
 * @method string getAuthor()
48
 * @method void setAuthor(string $author)
49
 * @method string getDescription()
50
 * @method void setDescription(string $description)
51
 * @method string getStarred()
52
 * @method void setStarred(string $timestamp)
53
 * @method string getCreated()
54
 * @method void setCreated(string $timestamp)
55
 * @method string getUpdated()
56
 * @method void setUpdated(string $timestamp)
57
 */
58
class PodcastEpisode extends Entity {
59
	public $userId;
60
	public $channelId;
61
	public $streamUrl;
62
	public $mimetype;
63
	public $size;
64
	public $duration;
65
	public $guid;
66
	public $guidHash;
67
	public $title;
68
	public $episode;
69
	public $linkUrl;
70
	public $published;
71
	public $keywords;
72
	public $copyright;
73
	public $author;
74
	public $description;
75
	public $starred;
76
	public $created;
77
	public $updated;
78
79
	public function __construct() {
80
		$this->addType('channelId', 'int');
81
		$this->addType('size', 'int');
82
		$this->addType('duration', 'int');
83
		$this->addType('episode', 'int');
84
	}
85
86
	public function toApi() : array {
87
		return [
88
			'id' => $this->getId(),
89
			'title' => $this->getTitle(),
90
			'stream_url' => $this->getStreamUrl(),
91
			'mimetype' => $this->getMimetype()
92
		];
93
	}
94
95
	public function toAmpacheApi() : array {
96
		return [
97
			'id' => (string)$this->getId(),
98
			'name' => $this->getTitle(),
99
			'title' => $this->getTitle(),
100
			'description' => $this->getDescription(),
101
			'author' => $this->getAuthor(),
102
			'author_full' => $this->getAuthor(),
103
			'website' => $this->getLinkUrl(),
104
			'pubdate' => $this->getPublished(), // TODO: format?
105
			'state' => 'Completed',
106
			'filelength' => Util::formatTime($this->getDuration()),
107
			'filesize' => Util::formatFileSize($this->getSize(), 2) . 'B',
108
			'mime' => $this->getMimetype(),
109
			'url' => $this->getStreamUrl(),
110
			'flag' => empty($this->getStarred()) ? 0 : 1,
111
		];
112
	}
113
114
	public function toSubsonicApi() : array {
115
		$result = [
116
			'id' => 'podcast_episode-' . $this->getId(),
117
			'streamId' => 'podcast_episode-' . $this->getId(),
118
			'channelId' => 'podcast_channel-' . $this->getChannelId(),
119
			'title' => $this->getTitle(),
120
			'description' => $this->getDescription(),
121
			'publishDate' => Util::formatZuluDateTime($this->getPublished()),
122
			'status' => 'completed',
123
			'parent' => 'podcast_channel-' . $this->getChannelId(),
124
			'isDir' => false,
125
			'year' => $this->getYear(),
126
			'genre' => 'Podcast',
127
			'coverArt' => 'podcast_channel-' . $this->getChannelId(),
128
			'size' => $this->getSize(),
129
			'contentType' => $this->getMimetype(),
130
			'suffix' => $this->getSuffix(),
131
			'duration' => $this->getDuration(),
132
			'bitRate' => empty($this->getBitrate()) ? 0 : (int)\round($this->getBitrate()/1000), // convert bps to kbps
133
		];
134
135
		if (!empty($this->starred)) {
136
			$result['starred'] = Util::formatZuluDateTime($this->starred);
137
		}
138
139
		return $result;
140
	}
141
142
	public function getYear() : ?int {
143
		$matches = null;
144
		if (\is_string($this->published) && \preg_match('/^(\d\d\d\d)-\d\d-\d\d.*/', $this->published, $matches) === 1) {
145
			return (int)$matches[1];
146
		} else {
147
			return null;
148
		}
149
	}
150
151
	/** @return ?int bits per second (bps) */
152
	public function getBitrate() : ?float {
153
		if (empty($this->size) || empty($this->duration)) {
154
			return null;
155
		} else {
156
			return $this->size / $this->duration * 8;
157
		}
158
	}
159
160
	public function getSuffix() : ?string {
161
		return self::mimeToSuffix($this->mimetype) ?? self::extractSuffixFromUrl($this->streamUrl);
162
	}
163
164
	private static function mimeToSuffix(?string $mime) : ?string {
165
		// a relevant subset from https://stackoverflow.com/a/53662733/4348850 wit a few additions
166
		$mime_map = [
167
			'audio/x-acc'					=> 'aac',
168
			'audio/ac3'						=> 'ac3',
169
			'audio/x-aiff'					=> 'aif',
170
			'audio/aiff'					=> 'aif',
171
			'audio/x-au'					=> 'au',
172
			'audio/x-flac'					=> 'flac',
173
			'audio/x-m4a'					=> 'm4a',
174
			'audio/mp4'						=> 'm4a',
175
			'audio/midi'					=> 'mid',
176
			'audio/mpeg'					=> 'mp3',
177
			'audio/mpg'						=> 'mp3',
178
			'audio/mpeg3'					=> 'mp3',
179
			'audio/mp3'						=> 'mp3',
180
			'audio/ogg'						=> 'ogg',
181
			'application/ogg'				=> 'ogg',
182
			'audio/x-realaudio'				=> 'ra',
183
			'audio/x-pn-realaudio'			=> 'ram',
184
			'audio/x-wav'					=> 'wav',
185
			'audio/wave'					=> 'wav',
186
			'audio/wav'						=> 'wav',
187
			'audio/x-ms-wma'				=> 'wma',
188
			'audio/m4b'						=> 'm4b',
189
			'application/vnd.apple.mpegurl'	=> 'm3u',
190
			'audio/mpegurl'					=> 'm3u',
191
		];
192
193
		return $mime_map[$mime] ?? null;
194
	}
195
196
	private static function extractSuffixFromUrl(?string $url) : ?string {
197
		if ($url === null) {
198
			return null;
199
		} else {
200
			$path = \parse_url($url, PHP_URL_PATH);
201
			$ext = \pathinfo($path, PATHINFO_EXTENSION);
202
			if (\is_string($ext) && !empty($ext)) {
203
				return $ext;
204
			} else {
205
				return null;
206
			}
207
		}
208
	}
209
}
210