Skip to content

Commit

Permalink
Merge pull request #314 from kagemomiji/issue212-podcast-repository
Browse files Browse the repository at this point in the history
#212 implement podcast repository to replace PodcastDao
  • Loading branch information
kagemomiji authored Nov 8, 2023
2 parents d19991c + 73bf8bc commit 03d4cf1
Show file tree
Hide file tree
Showing 36 changed files with 2,785 additions and 1,969 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import org.airsonic.player.domain.PodcastChannel;
import org.airsonic.player.domain.PodcastEpisode;
import org.airsonic.player.domain.PodcastStatus;
import org.airsonic.player.service.PodcastService;
import org.airsonic.player.service.PodcastManagementService;
import org.airsonic.player.service.PodcastPersistenceService;
import org.airsonic.player.service.podcast.PodcastIndexService;
import org.airsonic.player.service.podcast.PodcastIndexService.PodcastIndexResponse.PodcastIndexResult;
import org.apache.commons.lang.StringUtils;
Expand All @@ -22,45 +23,51 @@
@MessageMapping("/podcasts")
public class PodcastWSController {
@Autowired
PodcastService podcastService;
PodcastPersistenceService podcastPersistenceService;

@Autowired
PodcastManagementService podcastManagementService;

@Autowired
PodcastIndexService podcastIndexService;

@SubscribeMapping("all")
public List<PodcastChannelInfo> getAllPodcastChannels() {
return podcastService.getAllChannels().stream().map(this::wrap).collect(toList());
return podcastPersistenceService.getAllChannels().stream().map(this::wrap).collect(toList());
}

@MessageMapping("channel")
@SendToUser(broadcast = false)
public PodcastChannelInfo getPodcastChannel(Integer channelId) {
return wrap(podcastService.getChannel(channelId));
return wrap(podcastPersistenceService.getChannel(channelId));
}

private PodcastChannelInfo wrap(PodcastChannel channel) {
List<PodcastEpisode> episodes = podcastService.getEpisodes(channel.getId());
List<PodcastEpisode> episodes = podcastPersistenceService.getEpisodes(channel.getId());

return new PodcastChannelInfo(channel, episodes.size(), (int) episodes.stream().filter(e -> e.getStatus() == PodcastStatus.COMPLETED).count());
}

@MessageMapping("create")
public void createChannel(String url) {
podcastService.createChannel(StringUtils.trimToNull(url));
podcastManagementService.createChannel(StringUtils.trimToNull(url));
}

@MessageMapping("delete")
public void deleteChannels(List<Integer> ids) {
ids.forEach(id -> podcastService.deleteChannel(id));
ids.forEach(id -> {
podcastManagementService.deleteChannel(id);
});
}

@MessageMapping("refresh")
public void refreshChannels(List<Integer> ids) {
podcastService.refreshChannelIds(ids, true);
podcastManagementService.refreshChannelIds(ids, true);
}

@SubscribeMapping("episodes/newest")
public List<PodcastEpisode> newestEpisodes() {
return podcastService.getNewestEpisodes(10);
return podcastPersistenceService.getNewestEpisodes(10);
}

@MessageMapping("search")
Expand All @@ -72,12 +79,22 @@ public List<PodcastIndexResult> search(Principal user, String query) throws Exce
public static class PodcastChannelInfo extends PodcastChannel {
private int fileCount;
private int downloadedCount;
private Integer mediaFileId;

public PodcastChannelInfo(PodcastChannel channel, int fileCount, int downloadedCount) {
super(channel.getId(), channel.getUrl(), channel.getTitle(), channel.getDescription(),
channel.getImageUrl(), channel.getStatus(), channel.getErrorMessage(), channel.getMediaFileId());
channel.getImageUrl(), channel.getStatus(), channel.getErrorMessage(), channel.getMediaFile());
this.fileCount = fileCount;
this.downloadedCount = downloadedCount;
this.mediaFileId = channel.getMediaFile() != null ? channel.getMediaFile().getId() : null;
}

public Integer getMediaFileId() {
return mediaFileId;
}

public void setMediaFileId(Integer mediaFileId) {
this.mediaFileId = mediaFileId;
}

public int getFileCount() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,8 @@ public void setDelete(boolean delete) {
this.delete = delete;
}

public PodcastChannelRule toPodcastChannelRule() {
if (id == null || interval == null || episodeRetentionCount == null || episodeDownloadCount == null) {
return null;
}
return new PodcastChannelRule(id, interval, episodeRetentionCount, episodeDownloadCount);
public boolean isValid() {
return id != null && interval != null && episodeRetentionCount != null && episodeDownloadCount != null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,28 @@ public Executor configThreadPool() {
threadPool.initialize();
return threadPool;
}

@Bean(name = "PodcastDownloadThreadPool")
public Executor podcastDownloadThreadPool() {
var threadPool = new ThreadPoolTaskExecutor();
threadPool.setCorePoolSize(2);
threadPool.setMaxPoolSize(3);
threadPool.setQueueCapacity(500);
threadPool.setDaemon(true);
threadPool.setThreadNamePrefix("podcast-download");
threadPool.initialize();
return threadPool;
}

@Bean(name = "PodcastRefreshThreadPool")
public Executor podcastRefreshThreadPool() {
var threadPool = new ThreadPoolTaskExecutor();
threadPool.setCorePoolSize(2);
threadPool.setMaxPoolSize(5);
threadPool.setQueueCapacity(1000);
threadPool.setDaemon(true);
threadPool.setThreadNamePrefix("podcast-refresh");
threadPool.initialize();
return threadPool;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public class CoverArtController {
@Autowired
private PlaylistService playlistService;
@Autowired
private PodcastService podcastService;
private PodcastPersistenceService podcastService;
@Autowired
private ArtistService artistService;
@Autowired
Expand Down Expand Up @@ -202,26 +202,28 @@ private CoverArtRequest createPodcastCoverArtRequest(int id, int offset) {
if (channel == null) {
return null;
}
if (channel.getMediaFileId() == null) {
if (channel.getMediaFile() == null) {
return new PodcastCoverArtRequest(channel);
}
return createMediaFileCoverArtRequest(channel.getMediaFileId(), offset);
return createMediaFileCoverArtRequest(channel.getMediaFile(), offset);
}

private CoverArtRequest createMediaFileCoverArtRequest(int id, int offset) {
MediaFile mediaFile = mediaFileService.getMediaFile(id);
private CoverArtRequest createMediaFileCoverArtRequest(MediaFile mediaFile, int offset) {
if (mediaFile == null) {
return null;
}
if (mediaFile.isVideo()) {
return new VideoCoverArtRequest(mediaFile, offset);
}

var dir = mediaFile.isDirectory() ? mediaFile : mediaFileService.getParentOf(mediaFile);

return new MediaFileCoverArtRequest(dir, mediaFile.isDirectory() ? null : mediaFile.getId());
}

private CoverArtRequest createMediaFileCoverArtRequest(int id, int offset) {
MediaFile mediaFile = mediaFileService.getMediaFile(id);
return createMediaFileCoverArtRequest(mediaFile, offset);
}

private void sendImage(Path file, HttpServletResponse response) throws IOException {
response.setContentType(StringUtil.getMimeType(MoreFiles.getFileExtension(file)));
Files.copy(file, response.getOutputStream());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

package org.airsonic.player.controller;

import org.airsonic.player.service.PodcastService;
import org.airsonic.player.service.PodcastPersistenceService;
import org.airsonic.player.service.SecurityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
Expand All @@ -44,7 +44,7 @@
public class PodcastChannelController {

@Autowired
private PodcastService podcastService;
private PodcastPersistenceService podcastService;
@Autowired
private SecurityService securityService;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@
*/
package org.airsonic.player.controller;

import org.airsonic.player.domain.PodcastEpisode;
import org.airsonic.player.domain.PodcastStatus;
import org.airsonic.player.service.PodcastService;
import org.airsonic.player.service.PodcastManagementService;
import org.airsonic.player.service.PodcastPersistenceService;
import org.airsonic.player.service.podcast.PodcastDownloadClient;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
Expand All @@ -42,7 +45,13 @@
public class PodcastReceiverAdminController {

@Autowired
private PodcastService podcastService;
private PodcastPersistenceService podcastPersistenceService;

@Autowired
private PodcastManagementService podcastManagementService;

@Autowired
private PodcastDownloadClient podcastDownloadClient;

@RequestMapping(method = { RequestMethod.POST, RequestMethod.GET })
protected ModelAndView handleRequestInternal(
Expand All @@ -55,32 +64,33 @@ protected ModelAndView handleRequestInternal(

if (add != null) {
String url = StringUtils.trim(add);
podcastService.createChannel(url);
podcastManagementService.createChannel(url);
return new ModelAndView(new RedirectView("podcastChannels.view"));
}
if (downloadEpisode != null && channelId != null) {
downloadEpisode.parallelStream()
.map(e -> podcastService.getEpisode(e, false))
.map(e -> podcastPersistenceService.getEpisode(e, false))
.filter(episode -> episode != null && episode.getUrl() != null
&& (episode.getStatus() == PodcastStatus.NEW || episode.getStatus() == PodcastStatus.ERROR
|| episode.getStatus() == PodcastStatus.SKIPPED))
.forEach(podcastService::downloadEpisode);
.map(PodcastEpisode::getId)
.forEach(podcastDownloadClient::downloadEpisode);
return new ModelAndView(new RedirectView("podcastChannel.view?id=" + channelId));
}
if (deleteChannel != null && channelId != null) {
podcastService.deleteChannel(channelId);
podcastManagementService.deleteChannel(channelId);
return new ModelAndView(new RedirectView("podcastChannels.view"));
}
if (deleteEpisode != null) {
deleteEpisode.forEach(episodeId -> podcastService.deleteEpisode(episodeId, true));
deleteEpisode.forEach(episodeId -> podcastPersistenceService.deleteEpisode(episodeId, true));
return new ModelAndView(new RedirectView("podcastChannel.view?id=" + channelId));
}
if (refresh != null) {
if (channelId != null) {
podcastService.refreshChannel(channelId, true);
podcastManagementService.refreshChannel(channelId, true);
return new ModelAndView(new RedirectView("podcastChannel.view?id=" + channelId));
} else {
podcastService.refreshAllChannels(true);
podcastManagementService.refreshAllChannels(true);
return new ModelAndView(new RedirectView("podcastChannels.view"));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
import org.airsonic.player.domain.PodcastChannel;
import org.airsonic.player.domain.PodcastChannelRule;
import org.airsonic.player.service.MediaFolderService;
import org.airsonic.player.service.PodcastService;
import org.airsonic.player.service.PodcastManagementService;
import org.airsonic.player.service.PodcastPersistenceService;
import org.airsonic.player.service.SettingsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
Expand Down Expand Up @@ -54,7 +55,11 @@ public class PodcastSettingsController {
@Autowired
private SettingsService settingsService;
@Autowired
private PodcastService podcastService;
private PodcastPersistenceService podcastPersistenceService;

@Autowired
private PodcastManagementService podcastManagementService;

@Autowired
private MediaFolderService mediaFolderService;

Expand All @@ -73,8 +78,8 @@ protected String formBackingObject(Model model) {
.filter(f -> f.getType() == Type.PODCAST)
.collect(toMap(f -> f.getId(), f -> f.getId() + " - " + f.getName())));

List<PodcastChannel> channels = podcastService.getAllChannels();
List<PodcastChannelRule> rules = podcastService.getAllChannelRules();
List<PodcastChannel> channels = podcastPersistenceService.getAllChannels();
List<PodcastChannelRule> rules = podcastPersistenceService.getAllChannelRules();
command.setRules(rules.stream()
.map(cr -> new PodcastRule(
cr,
Expand Down Expand Up @@ -102,20 +107,22 @@ protected String doSubmitAction(@ModelAttribute PodcastSettingsCommand command,
settingsService.setPodcastEpisodeRetentionCount(defaultRule.getEpisodeRetentionCount());
settingsService.setPodcastEpisodeDownloadCount(defaultRule.getEpisodeDownloadCount());
settingsService.save();
podcastService.scheduleDefault();
podcastManagementService.scheduleDefault();

boolean success = mediaFolderService.enablePodcastFolder(command.getFolderId());

command.getRules().stream().filter(r -> !r.getId().equals(-1)).forEach(r -> {
if (r.getDelete()) {
podcastService.deleteChannelRule(r.getId());
podcastManagementService.deleteChannelRule(r.getId());
} else {
podcastService.createOrUpdateChannelRule(r.toPodcastChannelRule());
podcastManagementService.createOrUpdateChannelRuleByCommand(r);
}
});

Optional.ofNullable(command.getNewRule().toPodcastChannelRule())
.ifPresent(podcastService::createOrUpdateChannelRule);


Optional.ofNullable(command.getNewRule())
.ifPresent(podcastManagementService::createOrUpdateChannelRuleByCommand);

redirectAttributes.addFlashAttribute("settings_toast", success);
return "redirect:podcastSettings.view";
Expand Down
Loading

0 comments on commit 03d4cf1

Please sign in to comment.