connect api
All checks were successful
repod / nextcloud (push) Successful in 1m10s
repod / nodejs (push) Successful in 1m28s

This commit is contained in:
Michel Roux 2023-08-28 17:44:17 +02:00
parent b7c4fb2f61
commit d14ee8aee8
7 changed files with 116 additions and 39 deletions

View File

@ -19,6 +19,7 @@ use OCA\GPodderSync\Core\EpisodeAction\EpisodeAction;
* episodeImage: ?string, * episodeImage: ?string,
* episodeDescription: ?string, * episodeDescription: ?string,
* fetchedAtUnix: int, * fetchedAtUnix: int,
* episodeGuid: string,
* episodePubDate: ?\DateTime, * episodePubDate: ?\DateTime,
* episodeFilesize: ?int, * episodeFilesize: ?int,
* episodeDuration: ?int, * episodeDuration: ?int,
@ -35,6 +36,7 @@ class EpisodeActionExtraData implements \JsonSerializable
private ?string $episodeImage, private ?string $episodeImage,
private ?string $episodeDescription, private ?string $episodeDescription,
private int $fetchedAtUnix, private int $fetchedAtUnix,
private string $episodeGuid,
private ?\DateTime $episodePubDate, private ?\DateTime $episodePubDate,
private ?int $episodeFilesize, private ?int $episodeFilesize,
private ?int $episodeDuration, private ?int $episodeDuration,
@ -47,6 +49,7 @@ class EpisodeActionExtraData implements \JsonSerializable
$this->episodeImage = $episodeImage; $this->episodeImage = $episodeImage;
$this->episodeDescription = $episodeDescription; $this->episodeDescription = $episodeDescription;
$this->fetchedAtUnix = $fetchedAtUnix; $this->fetchedAtUnix = $fetchedAtUnix;
$this->episodeGuid = $episodeGuid;
$this->episodePubDate = $episodePubDate; $this->episodePubDate = $episodePubDate;
$this->episodeFilesize = $episodeFilesize; $this->episodeFilesize = $episodeFilesize;
$this->episodeDuration = $episodeDuration; $this->episodeDuration = $episodeDuration;
@ -58,6 +61,11 @@ class EpisodeActionExtraData implements \JsonSerializable
return $this->episodeUrl ?? '/no episodeUrl/'; return $this->episodeUrl ?? '/no episodeUrl/';
} }
public function getEpisodeGuid(): string
{
return $this->episodeGuid;
}
public function getEpisodePubDate(): ?\DateTime public function getEpisodePubDate(): ?\DateTime
{ {
return $this->episodePubDate; return $this->episodePubDate;
@ -97,6 +105,7 @@ class EpisodeActionExtraData implements \JsonSerializable
'episodeImage' => $this->episodeImage, 'episodeImage' => $this->episodeImage,
'episodeDescription' => $this->episodeDescription, 'episodeDescription' => $this->episodeDescription,
'fetchedAtUnix' => $this->fetchedAtUnix, 'fetchedAtUnix' => $this->fetchedAtUnix,
'episodeGuid' => $this->episodeGuid,
'episodePubDate' => $this->episodePubDate, 'episodePubDate' => $this->episodePubDate,
'episodeFilesize' => $this->episodeFilesize, 'episodeFilesize' => $this->episodeFilesize,
'episodeDuration' => $this->episodeDuration, 'episodeDuration' => $this->episodeDuration,

View File

@ -30,6 +30,7 @@ class EpisodeActionReader extends GPodderSyncEpisodeActionReader
$episodeLink = null; $episodeLink = null;
$episodeImage = null; $episodeImage = null;
$episodeDescription = null; $episodeDescription = null;
$episodeGuid = null;
$episodeFilesize = null; $episodeFilesize = null;
$episodeDuration = null; $episodeDuration = null;
$episodePubDate = null; $episodePubDate = null;
@ -39,6 +40,9 @@ class EpisodeActionReader extends GPodderSyncEpisodeActionReader
foreach ($channel->item as $item) { foreach ($channel->item as $item) {
$episodeUrl = (string) $item->enclosure['url']; $episodeUrl = (string) $item->enclosure['url'];
// Get episode guid
$episodeGuid = (string) $item->guid;
// Get episode filesize // Get episode filesize
$episodeFilesize = (int) $item->enclosure['length']; $episodeFilesize = (int) $item->enclosure['length'];
@ -119,6 +123,7 @@ class EpisodeActionReader extends GPodderSyncEpisodeActionReader
$episodeImage, $episodeImage,
$episodeDescription, $episodeDescription,
$fetchedAtUnix ?? (new \DateTime())->getTimestamp(), $fetchedAtUnix ?? (new \DateTime())->getTimestamp(),
$episodeGuid,
$episodePubDate, $episodePubDate,
$episodeFilesize, $episodeFilesize,
$episodeDuration, $episodeDuration,

85
package-lock.json generated
View File

@ -3548,9 +3548,9 @@
"integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA=="
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "20.5.6", "version": "20.5.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.6.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.7.tgz",
"integrity": "sha512-Gi5wRGPbbyOTX+4Y2iULQ27oUPrefaB0PxGQJnfyWN3kvEDGM3mIB5M/gQLmitZf7A9FmLeaqxD3L1CXpm3VKQ==" "integrity": "sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA=="
}, },
"node_modules/@types/normalize-package-data": { "node_modules/@types/normalize-package-data": {
"version": "2.4.1", "version": "2.4.1",
@ -3604,9 +3604,9 @@
"peer": true "peer": true
}, },
"node_modules/@types/semver": { "node_modules/@types/semver": {
"version": "7.5.0", "version": "7.5.1",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.1.tgz",
"integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", "integrity": "sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==",
"dev": true, "dev": true,
"peer": true "peer": true
}, },
@ -4117,19 +4117,19 @@
} }
}, },
"node_modules/@vueuse/components": { "node_modules/@vueuse/components": {
"version": "10.4.0", "version": "10.4.1",
"resolved": "https://registry.npmjs.org/@vueuse/components/-/components-10.4.0.tgz", "resolved": "https://registry.npmjs.org/@vueuse/components/-/components-10.4.1.tgz",
"integrity": "sha512-+ECAD4NcY6Rf/lLSQEyZapbjX9SE/QeEwINMVStvbMXusqPOB9Wpz9tv8i0QDtUKaFxdJ92X9uns4i6PqrtlRw==", "integrity": "sha512-hEWeumCfH394fkEYc/hng6T5VcjVkdqx7b75Sd6z4Uw3anjeo93Zp9qqtzFOv5bAmHls3Zy04Kowo1glrxDFRQ==",
"dependencies": { "dependencies": {
"@vueuse/core": "10.4.0", "@vueuse/core": "10.4.1",
"@vueuse/shared": "10.4.0", "@vueuse/shared": "10.4.1",
"vue-demi": ">=0.14.5" "vue-demi": ">=0.14.5"
} }
}, },
"node_modules/@vueuse/components/node_modules/vue-demi": { "node_modules/@vueuse/components/node_modules/vue-demi": {
"version": "0.14.5", "version": "0.14.6",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz", "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
"integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
"hasInstallScript": true, "hasInstallScript": true,
"bin": { "bin": {
"vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-fix": "bin/vue-demi-fix.js",
@ -4152,13 +4152,13 @@
} }
}, },
"node_modules/@vueuse/core": { "node_modules/@vueuse/core": {
"version": "10.4.0", "version": "10.4.1",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.4.0.tgz", "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.4.1.tgz",
"integrity": "sha512-8JnnTwiuzUqfiYIW8H4FKG/g5ZMKSE+9auoFUwUAkzhqUjy24VbMkNlDBWetQCimiptx7RAO6u1IS55H6+p1Tg==", "integrity": "sha512-DkHIfMIoSIBjMgRRvdIvxsyboRZQmImofLyOHADqiVbQVilP8VVHDhBX2ZqoItOgu7dWa8oXiNnScOdPLhdEXg==",
"dependencies": { "dependencies": {
"@types/web-bluetooth": "^0.0.17", "@types/web-bluetooth": "^0.0.17",
"@vueuse/metadata": "10.4.0", "@vueuse/metadata": "10.4.1",
"@vueuse/shared": "10.4.0", "@vueuse/shared": "10.4.1",
"vue-demi": ">=0.14.5" "vue-demi": ">=0.14.5"
}, },
"funding": { "funding": {
@ -4166,9 +4166,9 @@
} }
}, },
"node_modules/@vueuse/core/node_modules/vue-demi": { "node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.14.5", "version": "0.14.6",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz", "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
"integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
"hasInstallScript": true, "hasInstallScript": true,
"bin": { "bin": {
"vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-fix": "bin/vue-demi-fix.js",
@ -4191,17 +4191,17 @@
} }
}, },
"node_modules/@vueuse/metadata": { "node_modules/@vueuse/metadata": {
"version": "10.4.0", "version": "10.4.1",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.4.0.tgz", "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.4.1.tgz",
"integrity": "sha512-JNf9IR7ZBTDxWPfQlHhqBOv1VLO6ReTZi9HGY7RABjYHVpaEpjlHU7HpZDVOJGDa0gKITAbA2zMkNSBjKMcdaw==", "integrity": "sha512-2Sc8X+iVzeuMGHr6O2j4gv/zxvQGGOYETYXEc41h0iZXIRnRbJZGmY/QP8dvzqUelf8vg0p/yEA5VpCEu+WpZg==",
"funding": { "funding": {
"url": "https://github.com/sponsors/antfu" "url": "https://github.com/sponsors/antfu"
} }
}, },
"node_modules/@vueuse/shared": { "node_modules/@vueuse/shared": {
"version": "10.4.0", "version": "10.4.1",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.4.0.tgz", "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.4.1.tgz",
"integrity": "sha512-52asvLf5cbAS/h6xWjqoY4MgjxmFjnVNf/nA8BP7RbeIrIGcf+BZbeOcVo+92byqArXEJiBxptXpufQvbwJL/w==", "integrity": "sha512-vz5hbAM4qA0lDKmcr2y3pPdU+2EVw/yzfRsBdu+6+USGa4PxqSQRYIUC9/NcT06y+ZgaTsyURw2I9qOFaaXHAg==",
"dependencies": { "dependencies": {
"vue-demi": ">=0.14.5" "vue-demi": ">=0.14.5"
}, },
@ -4210,9 +4210,9 @@
} }
}, },
"node_modules/@vueuse/shared/node_modules/vue-demi": { "node_modules/@vueuse/shared/node_modules/vue-demi": {
"version": "0.14.5", "version": "0.14.6",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz", "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
"integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
"hasInstallScript": true, "hasInstallScript": true,
"bin": { "bin": {
"vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-fix": "bin/vue-demi-fix.js",
@ -8357,6 +8357,19 @@
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
}, },
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": { "node_modules/function-bind": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@ -12825,15 +12838,15 @@
} }
}, },
"node_modules/object.values": { "node_modules/object.values": {
"version": "1.1.6", "version": "1.1.7",
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz",
"integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"define-properties": "^1.1.4", "define-properties": "^1.2.0",
"es-abstract": "^1.20.4" "es-abstract": "^1.22.1"
}, },
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"

View File

@ -3,7 +3,7 @@
<NcLoadingIcon v-if="loading" /> <NcLoadingIcon v-if="loading" />
<ul v-if="!loading" :style="{marginBottom: currentEpisode ? '6rem' : 'auto'}"> <ul v-if="!loading" :style="{marginBottom: currentEpisode ? '6rem' : 'auto'}">
<NcListItem v-for="episode in episodes" <NcListItem v-for="episode in episodes"
:key="episode.episodeUrl" :key="episode.episodeGuid"
:details="formatTimeAgo(new Date(episode.episodePubDate.date))" :details="formatTimeAgo(new Date(episode.episodePubDate.date))"
:force-display-actions="true" :force-display-actions="true"
:name="episode.episodeName" :name="episode.episodeName"

View File

@ -6,7 +6,7 @@
:src="episode.episodeUrl" :src="episode.episodeUrl"
@durationchange="duration = audio.duration" @durationchange="duration = audio.duration"
@loadeddata="loading = false" @loadeddata="loading = false"
@pause="paused = true" @pause="pause"
@play="paused = false" @play="paused = false"
@seeked="currentTime = audio.currentTime" @seeked="currentTime = audio.currentTime"
@timeupdate="currentTime = audio.currentTime" @timeupdate="currentTime = audio.currentTime"
@ -34,6 +34,10 @@ import { NcLoadingIcon } from '@nextcloud/vue'
import ProgressBar from './ProgressBar.vue' import ProgressBar from './ProgressBar.vue'
import Timer from './Timer.vue' import Timer from './Timer.vue'
import Volume from './Volume.vue' import Volume from './Volume.vue'
import axios from '@nextcloud/axios'
import { formatEpisodeTimestamp } from '../../utils/time.js'
import { generateUrl } from '@nextcloud/router'
import { showError } from '@nextcloud/dialogs'
export default { export default {
name: 'Bar', name: 'Bar',
@ -45,6 +49,12 @@ export default {
Timer, Timer,
Volume, Volume,
}, },
props: {
podcastUrl: {
type: String,
required: true,
},
},
data() { data() {
return { return {
currentTime: 0, currentTime: 0,
@ -62,6 +72,29 @@ export default {
return this.$store.state.player.episode return this.$store.state.player.episode
}, },
}, },
methods: {
pause() {
this.paused = true
this.track()
},
async track() {
try {
await axios.post(generateUrl('/apps/gpoddersync/episode_action/create'), [{
podcast: this.podcastUrl,
episode: this.episode.episodeUrl,
guid: this.episode.episodeGuid,
action: 'play',
timestamp: formatEpisodeTimestamp(new Date()),
started: this.episode.episodeAction ? this.episode.episodeAction.started : 0,
position: this.currentTime,
total: this.duration,
}])
} catch (e) {
console.error(e)
showError(t('Error while saving position on API'))
}
},
},
} }
</script> </script>

View File

@ -10,7 +10,7 @@
@click="() => audio.play()" /> @click="() => audio.play()" />
<StopButton class="pointer" <StopButton class="pointer"
:size="30" :size="30"
@click="$store.commit('player/play', null)" /> @click="stop" />
</fragment> </fragment>
</template> </template>
@ -37,6 +37,12 @@ export default {
return document.getElementById('audio-player') return document.getElementById('audio-player')
}, },
}, },
methods: {
stop() {
this.audio.pause()
this.$store.commit('player/play', null)
},
},
} }
</script> </script>

View File

@ -37,3 +37,14 @@ export const formatTimer = (date) => {
return timer return timer
} }
export const formatEpisodeTimestamp = (date) => {
const year = date.getFullYear()
const month = date.getMonth().padStart(2, '0')
const day = date.getDate().padStart(2, '0')
const hours = date.getHours().padStart(2, '0')
const mins = date.getMinutes().padStart(2, '0')
const secs = date.getSeconds().padStart(2, '0')
return `${year}-${month}-${day}T${hours}:${mins}:${secs}`
}