diff --git a/pom.xml b/pom.xml index 4ecb845..9fa7cea 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 1.5.1.RELEASE + 2.1.9.RELEASE @@ -39,6 +39,39 @@ spring-boot-configuration-processor true + + junit + junit + test + + + org.springframework + spring-test + 5.1.5.RELEASE + test + + + org.springframework.boot + spring-boot + 2.1.9.RELEASE + + + org.springframework.boot + spring-boot-autoconfigure + 2.1.9.RELEASE + + + org.springframework.boot + spring-boot-test + 2.1.3.RELEASE + test + + + org.mockito + mockito-core + 2.23.4 + test + @@ -51,5 +84,6 @@ + ${project.basedir}/src/test diff --git a/src/main/java/org/nuvola/tvshowtime/ApplicationLauncher.java b/src/main/java/org/nuvola/tvshowtime/ApplicationLauncher.java index fbded82..aa94a82 100644 --- a/src/main/java/org/nuvola/tvshowtime/ApplicationLauncher.java +++ b/src/main/java/org/nuvola/tvshowtime/ApplicationLauncher.java @@ -18,268 +18,27 @@ package org.nuvola.tvshowtime; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; -import java.util.stream.Collectors; - -import org.nuvola.tvshowtime.business.plex.MediaContainer; -import org.nuvola.tvshowtime.business.plex.User; -import org.nuvola.tvshowtime.business.plex.Video; -import org.nuvola.tvshowtime.business.tvshowtime.AccessToken; -import org.nuvola.tvshowtime.business.tvshowtime.AuthorizationCode; -import org.nuvola.tvshowtime.business.tvshowtime.Message; -import org.nuvola.tvshowtime.config.PMSConfig; -import org.nuvola.tvshowtime.config.TVShowTimeConfig; -import org.nuvola.tvshowtime.util.DateUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.web.client.RestTemplate; - -import static org.nuvola.tvshowtime.util.Constants.MINUTE_IN_MILIS; -import static org.nuvola.tvshowtime.util.Constants.PMS_WATCH_HISTORY; -import static org.nuvola.tvshowtime.util.Constants.TVST_ACCESS_TOKEN_URI; -import static org.nuvola.tvshowtime.util.Constants.TVST_AUTHORIZE_URI; -import static org.nuvola.tvshowtime.util.Constants.TVST_CHECKIN_URI; -import static org.nuvola.tvshowtime.util.Constants.TVST_CLIENT_ID; -import static org.nuvola.tvshowtime.util.Constants.TVST_CLIENT_SECRET; -import static org.nuvola.tvshowtime.util.Constants.TVST_RATE_REMAINING_HEADER; -import static org.nuvola.tvshowtime.util.Constants.TVST_USER_AGENT; -import static org.springframework.http.HttpMethod.POST; @SpringBootApplication @EnableScheduling public class ApplicationLauncher { - private static final Logger LOG = LoggerFactory.getLogger(ApplicationLauncher.class); @Autowired - private TVShowTimeConfig tvShowTimeConfig; - @Autowired - private PMSConfig pmsConfig; - - private RestTemplate tvShowTimeTemplate; - private RestTemplate pmsTemplate; - private AccessToken accessToken; - private Timer tokenTimer; - - public static void main(String[] args) { - SpringApplication.run(ApplicationLauncher.class, args); - } - - @Scheduled(fixedDelay = Long.MAX_VALUE) - public void init() { - tvShowTimeTemplate = new RestTemplate(); + private TvTimeService m_tvTimeService; - File storeToken = new File(tvShowTimeConfig.getTokenFile()); - if (storeToken.exists()) { - try { - FileInputStream fileInputStream = new FileInputStream(storeToken); - ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); - accessToken = (AccessToken) objectInputStream.readObject(); - objectInputStream.close(); - fileInputStream.close(); - - LOG.info("AccessToken loaded from file with success : " + accessToken); - } catch (Exception e) { - LOG.error("Error parsing the AccessToken stored in 'session_token'."); - LOG.error("Please remove the 'session_token' file, and try again."); - LOG.error(e.getMessage()); - - System.exit(1); - } - - try { - processWatchedEpisodes(); - } catch (Exception e) { - LOG.error("Error during marking episodes as watched."); - LOG.error(e.getMessage()); - - System.exit(1); - } - } else { - requestAccessToken(); - } + public static void main(String[] args) { + SpringApplication.run(ApplicationLauncher.class, args); } - private void requestAccessToken() { - try { - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - HttpEntity entity = new HttpEntity<>("client_id=" + TVST_CLIENT_ID, headers); - - ResponseEntity content = tvShowTimeTemplate.exchange(TVST_AUTHORIZE_URI, POST, entity, - AuthorizationCode.class); - AuthorizationCode authorizationCode = content.getBody(); - - if (authorizationCode.getResult().equals("OK")) { - LOG.info("Linking with your TVShowTime account using the code " + authorizationCode.getDevice_code()); - LOG.info("Please open the URL " + authorizationCode.getVerification_url() + " in your browser"); - LOG.info("Connect with your TVShowTime account and type in the following code : "); - LOG.info(authorizationCode.getUser_code()); - LOG.info("Waiting for you to type in the code in TVShowTime :-D ..."); - - tokenTimer = new Timer(); - tokenTimer.scheduleAtFixedRate(new TimerTask() { - @Override - public void run() { - loadAccessToken(authorizationCode.getDevice_code()); - } - }, 1000 * authorizationCode.getInterval(), 1000 * authorizationCode.getInterval()); - } else { - LOG.error("OAuth authentication TVShowTime failed."); - - System.exit(1); - } - } catch (Exception e) { - LOG.error("OAuth authentication TVShowTime failed."); - LOG.error(e.getMessage()); - - System.exit(1); - } + @EventListener(ApplicationReadyEvent.class) + public void init() throws Exception { + m_tvTimeService.init(); } - private void loadAccessToken(String deviceCode) { - String query = new StringBuilder("client_id=") - .append(TVST_CLIENT_ID) - .append("&client_secret=") - .append(TVST_CLIENT_SECRET) - .append("&code=") - .append(deviceCode) - .toString(); - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - HttpEntity entity = new HttpEntity<>(query, headers); - - ResponseEntity content = tvShowTimeTemplate.exchange(TVST_ACCESS_TOKEN_URI, POST, entity, - AccessToken.class); - accessToken = content.getBody(); - - if (accessToken.getResult().equals("OK")) { - LOG.info("AccessToken from TVShowTime with success : " + accessToken); - tokenTimer.cancel(); - - storeAccessToken(); - processWatchedEpisodes(); - } else { - if (!accessToken.getMessage().equals("Authorization pending") - && !accessToken.getMessage().equals("Slow down")) { - LOG.error("Unexpected error did arrive, please reload the service :-("); - tokenTimer.cancel(); - - System.exit(1); - } - } - } - - private void storeAccessToken() { - try { - File storeToken = new File(tvShowTimeConfig.getTokenFile()); - FileOutputStream fileOutputStream = new FileOutputStream(storeToken); - ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); - objectOutputStream.writeObject(accessToken); - objectOutputStream.close(); - fileOutputStream.close(); - - LOG.info("AccessToken store successfully inside a file..."); - } catch (Exception e) { - LOG.error("Unexpected error did arrive when trying to store the AccessToken in a file "); - LOG.error(e.getMessage()); - - System.exit(1); - } - } - - private void processWatchedEpisodes() { - pmsTemplate = new RestTemplate(); - String watchHistoryUrl = pmsConfig.getPath() + PMS_WATCH_HISTORY; - - if (pmsConfig.getToken() != null && !pmsConfig.getToken().isEmpty()) { - watchHistoryUrl += "?X-Plex-Token=" + pmsConfig.getToken(); - LOG.info("Calling Plex with a X-Plex-Token..."); - } - - ResponseEntity response = pmsTemplate.getForEntity(watchHistoryUrl, MediaContainer.class); - MediaContainer mediaContainer = response.getBody(); - - for (Video video : mediaContainer.getVideo()) { - LocalDateTime date = DateUtils.getDateTimeFromTimestamp(video.getViewedAt()); - - // Mark as watched only episodes for configured user - if (pmsConfig.getUsername() != null && video.getUser() != null) { - List users = video.getUser().stream().filter(user -> user.getName().equals(pmsConfig.getUsername())).collect(Collectors.toList()); - - if (users.stream().count() == 0) { - continue; - } - } - - // Mark as watched only today and yesterday episodes - if (DateUtils.isTodayOrYesterday(date) || pmsConfig.getMarkall() == true) { - if (video.getType().equals("episode")) { - String episode = new StringBuilder(video.getGrandparentTitle()) - .append(" - S") - .append(video.getParentIndex()) - .append("E").append(video.getIndex()) - .toString(); - - markEpisodeAsWatched(episode); - } else { - continue; - } - } else { - LOG.info("All episodes are processed successfully ..."); - System.exit(0); - } - } - } - - private void markEpisodeAsWatched(String episode) { - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.add("User-Agent", TVST_USER_AGENT); - HttpEntity entity = new HttpEntity<>("filename=" + episode, headers); - - String checkinUrl = new StringBuilder(TVST_CHECKIN_URI) - .append("?access_token=") - .append(accessToken.getAccess_token()) - .toString(); - - ResponseEntity content = tvShowTimeTemplate.exchange(checkinUrl, POST, entity, Message.class); - Message message = content.getBody(); - - if (message.getResult().equals("OK")) { - LOG.info("Mark " + episode + " as watched in TVShowTime"); - } else { - LOG.error("Error while marking [" + episode + "] as watched in TVShowTime "); - } - - // Check if we are below the Rate-Limit of the API - int remainingApiCalls = Integer.parseInt(content.getHeaders().get(TVST_RATE_REMAINING_HEADER).get(0)); - if (remainingApiCalls == 0) { - try { - LOG.info("Consumed all available TVShowTime API calls slots, waiting for new slots ..."); - Thread.sleep(MINUTE_IN_MILIS); - } catch (Exception e) { - LOG.error(e.getMessage()); - - System.exit(1); - } - } - } } diff --git a/src/main/java/org/nuvola/tvshowtime/PlexService.java b/src/main/java/org/nuvola/tvshowtime/PlexService.java new file mode 100644 index 0000000..f6ba0e4 --- /dev/null +++ b/src/main/java/org/nuvola/tvshowtime/PlexService.java @@ -0,0 +1,102 @@ +package org.nuvola.tvshowtime; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.nuvola.tvshowtime.business.plex.MetaData; +import org.nuvola.tvshowtime.business.plex.PlexResponse; +import org.nuvola.tvshowtime.config.PMSConfig; +import org.nuvola.tvshowtime.util.DateUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.*; + +import static org.nuvola.tvshowtime.util.Constants.PMS_GET_ACCOUNTS; +import static org.nuvola.tvshowtime.util.Constants.PMS_WATCH_HISTORY; + +@Service +class PlexService { + + private static final Logger LOG = LoggerFactory.getLogger(PlexService.class); + + @Autowired + private PMSConfig pmsConfig; + @Autowired + private RestTemplate pmsTemplate; + private Map m_users = new HashMap<>(); + private String m_url; + private final static ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + void getUsersInPlex() throws IOException { + m_url = pmsConfig.getPath() + PMS_GET_ACCOUNTS; + appendPlexToken(); + LOG.debug("Get users from plex with url: " + m_url); + String response = pmsTemplate.getForObject(m_url, String.class); + PlexResponse plexResponse = OBJECT_MAPPER.readValue(response, PlexResponse.class); + plexResponse.getMediaContainer().getAccount().stream().filter(user -> !user.getName().equals("")).forEach(user -> m_users.put(user.getName(), user.getId())); + } + + Map getUsers() { + return m_users; + } + + Set getWatchedOnPlex() throws IOException { + //refresh m_users + getUsersInPlex(); + + Set watched = new HashSet<>(); + m_url = pmsConfig.getPath() + PMS_WATCH_HISTORY; + + appendPlexToken(); + String response = pmsTemplate.getForObject(m_url, String.class); + + PlexResponse plexResponse = OBJECT_MAPPER.readValue(response, PlexResponse.class); + LOG.debug(plexResponse.getMediaContainer().toString()); + + for (MetaData metaData : plexResponse.getMediaContainer().getMetaData()) { + LocalDateTime date = DateUtils.getDateTimeFromTimestamp(metaData.getViewedAt()); + + LOG.debug(metaData.toString()); + + // If present, mark as watched only episodes for configured user + if (pmsConfig.getUsername() != null) { + if (!metaData.getAccountID().equals(m_users.get(pmsConfig.getUsername()))) { + continue; + } + } + + // Mark as watched only today and yesterday episodes + if (DateUtils.isTodayOrYesterday(date) || pmsConfig.getMarkall()) { + if (metaData.getType().equals("episode")) { + String episode = new StringBuilder(metaData.getGrandparentTitle()) + .append(" - S") + .append(metaData.getParentIndex()) + .append("E").append(metaData.getIndex()) + .toString(); + + watched.add(episode); + } + /* + * Enable when TvTime should accept movie + + else if (metaData.getType().equals("movie")) { + watched.add(metaData.getTitle()); + } + */ + } + } + return watched; + } + + private void appendPlexToken() { + if (pmsConfig.getToken() != null && !pmsConfig.getToken().isEmpty()) { + m_url += "?X-Plex-Token=" + pmsConfig.getToken(); + LOG.debug("Calling Plex with a X-Plex-Token = " + pmsConfig.getToken()); + } + } + +} diff --git a/src/main/java/org/nuvola/tvshowtime/TvTimeService.java b/src/main/java/org/nuvola/tvshowtime/TvTimeService.java new file mode 100644 index 0000000..fec70c0 --- /dev/null +++ b/src/main/java/org/nuvola/tvshowtime/TvTimeService.java @@ -0,0 +1,203 @@ +package org.nuvola.tvshowtime; + +import org.nuvola.tvshowtime.business.tvshowtime.*; +import org.nuvola.tvshowtime.config.TVShowTimeConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.*; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.io.*; +import java.util.*; + +import static org.nuvola.tvshowtime.util.Constants.*; +import static org.springframework.http.HttpMethod.POST; + +@Service +class TvTimeService { + + private static final Logger LOG = LoggerFactory.getLogger(TvTimeService.class); + + @Autowired + private TVShowTimeConfig tvShowTimeConfig; + + @Autowired + private PlexService m_plexService; + + @Autowired + private RestTemplate tvShowTimeTemplate; + private AccessToken accessToken; + private Timer tokenTimer; + + void init() throws Exception { + File storeToken = new File(tvShowTimeConfig.getTokenFile()); + if (storeToken.exists()) { + try { + FileInputStream fileInputStream = new FileInputStream(storeToken); + ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); + accessToken = (AccessToken) objectInputStream.readObject(); + objectInputStream.close(); + fileInputStream.close(); + LOG.info("AccessToken loaded from file with success : " + accessToken); + } + catch (Exception e) { + LOG.error("Error parsing the AccessToken stored in 'session_token'."); + LOG.error("Please remove the 'session_token' file, and try again."); + LOG.error(e.getMessage()); + throw e; + } + + try { + m_plexService.getUsersInPlex(); + markEpisodesAsWatched(m_plexService.getWatchedOnPlex()); + LOG.info("All episodes are processed successfully ..."); + } + catch (Exception e) { + LOG.error("Error during marking episodes as watched."); + LOG.error("Error: ", e); + throw e; + } + } + else { + requestAccessToken(); + LOG.info("Re-run the app to load info to TvTime ;-)"); + } + } + + void requestAccessToken() throws Exception { + LOG.info("RequestAccessToken...."); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + HttpEntity entity = new HttpEntity<>("client_id=" + TVST_CLIENT_ID, headers); + + ResponseEntity content = tvShowTimeTemplate.exchange(TVST_AUTHORIZE_URI, POST, entity, + AuthorizationCode.class); + AuthorizationCode authorizationCode = content.getBody(); + + if (authorizationCode != null && authorizationCode.getResult().equals("OK")) { + LOG.info("Linking with your TVShowTime account using the code " + authorizationCode.getDevice_code()); + LOG.info("Please open the URL " + authorizationCode.getVerification_url() + " in your browser"); + LOG.info("Connect with your TVShowTime account and type in the following code : "); + LOG.info(">>> INSERT THE FOLLOWING CODE: " + authorizationCode.getUser_code() + " <<<"); + LOG.info("Waiting for you to type in the code in TVShowTime :-D ..."); + + tokenTimer = new Timer(); + tokenTimer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + try { + loadAccessToken(authorizationCode.getDevice_code()); + } + catch (Exception e) { + e.printStackTrace(); + } + } + }, 1000 * authorizationCode.getInterval(), 1000 * authorizationCode.getInterval()); + } + else { + throw new Exception("OAuth authentication TVShowTime failed."); + } + } + + void loadAccessToken(String deviceCode) throws Exception { + String query = new StringBuilder("client_id=") + .append(TVST_CLIENT_ID) + .append("&client_secret=") + .append(TVST_CLIENT_SECRET) + .append("&code=") + .append(deviceCode) + .toString(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + HttpEntity entity = new HttpEntity<>(query, headers); + + ResponseEntity content = tvShowTimeTemplate.exchange(TVST_ACCESS_TOKEN_URI, POST, entity, + AccessToken.class); + accessToken = content.getBody(); + + if (accessToken == null) { + throw new Exception("Access token is null"); + } + + if (accessToken.getResult().equals("OK")) { + LOG.info("AccessToken from TVShowTime with success : " + accessToken); + tokenTimer.cancel(); + storeAccessToken(); + markEpisodesAsWatched(m_plexService.getWatchedOnPlex()); + } + else { + if (!accessToken.getMessage().equals("Authorization pending") + && !accessToken.getMessage().equals("Slow down")) { + LOG.error("Unexpected error did arrive, please reload the service :-("); + tokenTimer.cancel(); + throw new Exception("Unexpected error did arrive, please reload the service :-("); + } + } + } + + private void storeAccessToken() throws IOException { + try { + File storeToken = new File(tvShowTimeConfig.getTokenFile()); + FileOutputStream fileOutputStream = new FileOutputStream(storeToken); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); + objectOutputStream.writeObject(accessToken); + objectOutputStream.close(); + fileOutputStream.close(); + LOG.info("AccessToken store successfully inside a file..."); + } + catch (Exception e) { + LOG.error("Unexpected error did arrive when trying to store the AccessToken in a file "); + LOG.error(e.getMessage()); + throw e; + } + } + + void markEpisodesAsWatched(Set episodes) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + headers.add("User-Agent", TVST_USER_AGENT); + + String checkInUrl = new StringBuilder(TVST_CHECKIN_URI) + .append("?access_token=") + .append(accessToken.getAccess_token()) + .toString(); + + for (String episode : episodes) { + HttpEntity entity = new HttpEntity<>("filename=" + episode, headers); + + ResponseEntity content = tvShowTimeTemplate.exchange(checkInUrl, POST, entity, Message.class); + Message message = content.getBody(); + + if (message != null && message.getResult().equals("OK")) { + LOG.info("Marked " + episode + " as watched in TVShowTime"); + } + else { + LOG.error("Error while marking [" + episode + "] as watched in TVShowTime "); + } + + // Check if we are below the Rate-Limit of the API + if (content.getHeaders().get(TVST_RATE_REMAINING_HEADER) != null + && !content.getHeaders().get(TVST_RATE_REMAINING_HEADER).isEmpty()) { + + int remainingApiCalls = Integer.parseInt(content.getHeaders().get(TVST_RATE_REMAINING_HEADER).get(0)); + long epocNewRateLimit = (Long.valueOf(content.getHeaders().get(TVST_RATE_RESET_HEADER).get(0)) * 1000); + if (remainingApiCalls == 0) { + try { + LOG.info("Consumed all available TVShowTime API calls slots, waiting for new slots at " + epocNewRateLimit); + epocNewRateLimit = epocNewRateLimit - System.currentTimeMillis(); + if (epocNewRateLimit > 0) { + Thread.sleep(epocNewRateLimit); + } + } + catch (Exception e) { + LOG.error(e.getMessage()); + } + } + + } + } + } +} diff --git a/src/main/java/org/nuvola/tvshowtime/business/plex/Account.java b/src/main/java/org/nuvola/tvshowtime/business/plex/Account.java new file mode 100644 index 0000000..7df2cfa --- /dev/null +++ b/src/main/java/org/nuvola/tvshowtime/business/plex/Account.java @@ -0,0 +1,108 @@ +/* + * tvshowtimeplex + * Copyright (C) 2017 Appulize - Maciej Swic + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.nuvola.tvshowtime.business.plex; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "Account") +public class Account { + private Long id; + private String key; + private String name; + private String defaultAudioLanguage; + private Boolean autoSelectAudio; + private String defaultSubtitleLanguage; + private Integer subtitleMode; + private String thumb; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getDefaultAudioLanguage() { + return defaultAudioLanguage; + } + + public void setDefaultAudioLanguage(String defaultAudioLanguage) { + this.defaultAudioLanguage = defaultAudioLanguage; + } + + public Boolean getAutoSelectAudio() { + return autoSelectAudio; + } + + public void setAutoSelectAudio(Boolean autoSelectAudio) { + this.autoSelectAudio = autoSelectAudio; + } + + public String getDefaultSubtitleLanguage() { + return defaultSubtitleLanguage; + } + + public void setDefaultSubtitleLanguage(String defaultSubtitleLanguage) { + this.defaultSubtitleLanguage = defaultSubtitleLanguage; + } + + public Integer getSubtitleMode() { + return subtitleMode; + } + + public void setSubtitleMode(Integer subtitleMode) { + this.subtitleMode = subtitleMode; + } + + public String getThumb() { + return thumb; + } + + public void setThumb(String thumb) { + this.thumb = thumb; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @JsonProperty("title") + public String getTitle() { + return name; + } + + public void setTitle(String title) { + this.name = title; + } +} diff --git a/src/main/java/org/nuvola/tvshowtime/business/plex/MediaContainer.java b/src/main/java/org/nuvola/tvshowtime/business/plex/MediaContainer.java index 50ad752..1d2ede5 100644 --- a/src/main/java/org/nuvola/tvshowtime/business/plex/MediaContainer.java +++ b/src/main/java/org/nuvola/tvshowtime/business/plex/MediaContainer.java @@ -18,17 +18,22 @@ package org.nuvola.tvshowtime.business.plex; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; +import com.fasterxml.jackson.annotation.JsonProperty; + import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; import java.util.List; @XmlRootElement(name = "MediaContainer") public class MediaContainer { + @JsonProperty("size") private Integer size; - private List