+* A custom fields API kellhet? Ott be lehet állítani a custom filed-re pl. azt, hogy kötelező e, így amíg nincs értéke
+ addig a videó nem aktív. Ennek használata nélkül is létrehozható video?
+*
* A sunset kezelése is kell, tehát jöhet adat későbbi sunset-el?
* A sunset és sunrise formátuma legyen egyforma (mindegy melyik) minden sorra!
* Mik a kötelező mezők? Most: playlist, sunset, sunrise, title
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
-import org.springframework.context.ApplicationContext;
import org.springframework.core.SpringVersion;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableScheduling
public class VodSyncEntry extends SpringBootServletInitializer {
-
public static void main(String[] args) {
-// AnsiConsole.systemInstall();
-// System.out.println( ansi().eraseScreen());
log.info("Spring version: {}", SpringVersion.getVersion());
- ApplicationContext applicationContext = SpringApplication.run(VodSyncEntry.class, args);
-// AnsiConsole.systemUninstall();
- }
-
- @Override
- protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
- logger.info("Starting configure");
- return builder.sources(VodSyncEntry.class);
+ SpringApplication.run(VodSyncEntry.class, args);
}
}
retrieveMessagesFromServerOnGetMessage: true
username: db2admin
password: password
+ mail:
+ host: mx.in.useribm.hu
+# port: 587
+# spring.mail.username=<login user to smtp server>
+# spring.mail.password=<login password to smtp server>
+# spring.mail.properties.mail.smtp.auth=true
+# spring.mail.properties.mail.smtp.starttls.enable=true
camunda.bpm:
generic-properties.properties:
telemetry-reporter-activate: false
--- /dev/null
+/*
+ * Copyright (c) $today.year-$today.month-24.
+ * By elGekko
+ */
+
+package hu.user.mcvodsync;
+
+import com.brightcove.cms.client.model.Video;
+import hu.user.mcvodsync.db.Asset;
+import hu.user.mcvodsync.service.export.VideoMapper;
+import lombok.extern.log4j.Log4j2;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.Assert.assertEquals;
+
+
+@Log4j2
+@RunWith(SpringRunner.class)
+@ComponentScan("hu.user.lis")
+@SpringBootTest
+@ActiveProfiles("dev")
+public class AssetMapperIT {
+ @Autowired
+ private VideoMapper videoMapper;
+
+ @Test
+ public void mapAssetToVideoTest() {
+ Asset asset = Asset.builder()
+ .progLocalTitle("progLocalTitle")
+ .catalogId("catalogId")
+ .hubInfo("hubInfo")
+ .build();
+ Video video = videoMapper.toVideo(asset);
+
+ assertEquals(asset.getCatalogId(), video.getReferenceId());
+ assertEquals(asset.getProgLocalTitle(), video.getName());
+ assertEquals(asset.getHubInfo(), video.getCustomFields().get(VideoMapper.NOTES));
+ }
+
+ @Test
+ public void mapVideoToAssetTest() {
+ Video video = new Video();
+ video.setReferenceId("setReferenceId");
+ video.setName("name");
+ video.putCustomFieldsItem(VideoMapper.NOTES, "notes");
+ Asset asset = videoMapper.toAsset(video);
+
+ assertEquals(video.getReferenceId(), asset.getCatalogId());
+ assertEquals(video.getName(), asset.getProgLocalTitle());
+ assertEquals(video.getCustomFields().get(VideoMapper.NOTES), asset.getHubInfo());
+ }
+}
import com.brightcove.cms.client.model.CreateVideoRequestBodyFields;
import com.brightcove.cms.client.model.Playlist;
+import com.brightcove.cms.client.model.PlaylistInputFields;
import com.brightcove.cms.client.model.Video;
+import com.google.common.collect.ImmutableMap;
import hu.user.mcvodsync.brightcove.BrightCoveClient;
+import hu.user.mcvodsync.brightcove.PagedSearch;
import lombok.extern.log4j.Log4j2;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.HttpServerErrorException;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import java.util.stream.Collectors;
@Log4j2
@RunWith(SpringRunner.class)
private BrightCoveClient bcClient;
+ private List<String> getVideos() {
+ List<String> ids = new ArrayList<>();
+ PagedSearch<Video> page = PagedSearch.<Video>builder()
+ .query("tags:mc-vod-sync")
+ .sort("reference_id")
+ .build();
+ while (bcClient.getVideosPaged(page)) {
+ List<String> currentIds = page.getData().stream().map(Video::getId).collect(Collectors.toList());
+ ids.addAll(currentIds);
+ }
+ return ids;
+ }
+
@Test
- public void testGetPlayLists() {
+ public void testCreate5PlayLists() {
try {
- List<Playlist> playLists = bcClient.getPlayLists(0, 10);
+ List<String> ids = getVideos();
+
+ for (int i = 1; i < 6; i++) {
+ PlaylistInputFields fields = new PlaylistInputFields();
+ fields.setType(PlaylistInputFields.TypeEnum.EXPLICIT);
+ fields.setName("Playlist 0000" + i);
+ fields.setVideoIds(ids);
+ fields.setDescription("mc-vod-sync");
+ Playlist playList = bcClient.createPlaylist(fields);
+ logPlaylist(playList);
+ }
+
+ } catch (Exception e) {
+ log.error(e);
+ }
+ }
+
+ @Test
+ public void updatePlayLists() {
+ try {
+
+ PagedSearch<Playlist> page = PagedSearch.<Playlist>builder()
+ .query("description:mc-vod-sync")
+ .sort("name")
+ .build();
+ bcClient.getPlaylistsPaged(page);
+ Playlist playlist = page.getData().get(0);
+ playlist.setVideoIds(getVideos());
+
+// List<String> videoIds = playlist.getVideoIds();
+// assertNotNull(videoIds);
+// String id1 = videoIds.get(0);
+// String id2 = videoIds.get(videoIds.size() - 1);
+// videoIds.set(0, id2);
+// videoIds.set(videoIds.size() - 1, id1);
- playLists.forEach(playList -> {
- log.info(playList.getName());
- });
+
+ Playlist playList = bcClient.updatePlaylist(playlist);
+ logPlaylist(playList);
} catch (Exception e) {
log.error(e);
}
@Test
- public void testGetVideos() {
+ public void testGetPlayLists() {
try {
- List<Video> videos = bcClient.getVideos(0, 10);
+ PagedSearch<Playlist> page = PagedSearch.<Playlist>builder()
+ .query("description:mc-vod-sync")
+ .sort("name")
+ .build();
+ while (bcClient.getPlaylistsPaged(page)) {
+ page.getData().forEach(this::logPlaylist);
+ }
- videos.forEach(video -> {
- log.info("{} ref: {} {} {}", video.getId(), video.getReferenceId(), video.getName(), video.getState());
- });
+ } catch (Exception e) {
+ log.error(e);
+ }
+ }
+ @Test
+ public void testGetVideos() {
+ try {
+ PagedSearch<Video> page = PagedSearch.<Video>builder()
+ .query("tags:mc-vod-sync")
+ .sort("reference_id")
+ .build();
+ while (bcClient.getVideosPaged(page)) {
+ page.getData().forEach(this::logVideo);
+ }
} catch (Exception e) {
log.error(e);
}
}
+
@Test
public void testGetVideoById() {
try {
Video video = bcClient.getVideoById("6328122715112");
- log.info("{} {} {}", video.getId(), video.getReferenceId(), video.getName());
+ logVideo(video);
} catch (Exception e) {
log.error(e);
}
public void testGetVideosById() {
try {
List<Video> videos = bcClient.getVideosById("6328122715112,6339727091112");
- videos.forEach(video -> {
- log.info("{} {} {}", video.getId(), video.getReferenceId(), video.getName());
- });
+ videos.forEach(this::logVideo);
} catch (Exception e) {
log.error(e);
}
try {
CreateVideoRequestBodyFields fields = new CreateVideoRequestBodyFields();
fields.setName("TEST video 00001");
- fields.setReferenceId("MCVODSYNC00001");
+ fields.setReferenceId("MCVODSYNC10001");
fields.setState(CreateVideoRequestBodyFields.StateEnum.INACTIVE);
fields.setEconomics(CreateVideoRequestBodyFields.EconomicsEnum.FREE);
+ fields.setTags(Collections.singletonList("mc-vod-sync"));
+ fields.setCustomFields(ImmutableMap.of("Notes", "notes"));
Video video = bcClient.createVideo(fields);
- log.info("{} {} {}", video.getId(), video.getReferenceId(), video.getName());
+ logVideo(video);
+
+
+ log.info("Search result");
+ List<Video> videos = bcClient.getVideos(0, 10, "tags:mc-vod-sync");
+ videos.forEach(this::logVideo);
+
+
+ } catch (Exception e) {
+ log.error(e);
+ }
+ }
+
+ @Test
+ public void testCreate13Videos() {
+ try {
+
+ int i = 13;
+ while (i > 0) {
+ CreateVideoRequestBodyFields fields = new CreateVideoRequestBodyFields();
+ fields.setName("TEST video 0000" + i);
+ fields.setReferenceId("MCVODSYNC0000" + i);
+ fields.setState(CreateVideoRequestBodyFields.StateEnum.INACTIVE);
+ fields.setEconomics(CreateVideoRequestBodyFields.EconomicsEnum.FREE);
+ fields.setTags(Collections.singletonList("mc-vod-sync"));
+ Video video = bcClient.createVideo(fields);
+ logVideo(video);
+ i--;
+ }
} catch (Exception e) {
log.error(e);
}
@Test
public void testGetVideoByRefId() {
try {
- Video video = bcClient.getVideoById("ref:MCVODSYNC00001");
- log.info("{} {} {}", video.getId(), video.getReferenceId(), video.getName());
+ Video video = bcClient.getVideoByReferenceId("MCVODSYNC00001_");
+ logVideo(video);
+
+ } catch (HttpClientErrorException e) {
+ log.warn(e);
+ } catch (HttpServerErrorException e) {
+ log.error("Server error", e);
+ } catch (Exception e) {
+ log.error(e);
+ }
+ }
+
+
+ @Test
+ public void deleteVideos() {
+ try {
+ List<Video> videos = bcClient.getVideos(0, 10, "tags:mc-vod-sync");
+ videos.forEach(video -> {
+ bcClient.deleteVideo(video.getId());
+ });
+
} catch (Exception e) {
log.error(e);
}
@Test
public void testDeleteVideo() {
try {
- bcClient.deleteVideo("ref:MCVODSYNC00001");
+// bcClient.deleteVideo("ref:MCVODSYNC00001");
+ bcClient.deleteVideo("6340725850112,6340726442112,6340725849112,6340727220112");
} catch (Exception e) {
log.error(e);
}
}
+ private void logVideo(Video video) {
+ log.info("{} ref: {} {} {} {} {}", video.getId(), video.getReferenceId(), video.getName(), video.getState(), video.getTags(), video.getCustomFields());
+ }
+
+ private void logPlaylist(Playlist playlist) {
+ log.info("{} {} {} {}\r\n{}", playlist.getId(), playlist.getName(), playlist.getType(), playlist.getDescription(), playlist.getVideoIds());
+ }
}
--- /dev/null
+/*
+ * Copyright (c) $today.year-$today.month-24.
+ * By elGekko
+ */
+
+package hu.user.mcvodsync;
+
+import hu.user.mcvodsync.service.mail.EmailSendService;
+import org.junit.jupiter.api.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@ActiveProfiles("dev")
+@TestPropertySource("classpath:application-dev.yaml")
+public class EmailSendServiceTest {
+
+ @Autowired
+ EmailSendService emailSendService;
+
+
+ @Test
+ public void sendEmail() {
+ emailSendService.sendSimpleMessage();
+ }
+
+}
package hu.user.mcvodsync;
+import hu.user.mcvodsync.db.AssetSync;
+import hu.user.mcvodsync.db.SyncType;
import hu.user.mcvodsync.db.repository.AssetRepository;
import hu.user.mcvodsync.db.repository.AssetSyncRepository;
import hu.user.mcvodsync.service.xls.AssetImportService;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.ActiveProfiles;
-import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import java.sql.Date;
+import java.time.Instant;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
import java.util.List;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.*;
@Log4j2
@ComponentScan("hu.user.lis")
@SpringBootTest
@ActiveProfiles("dev")
-//@Profile("dev")
-@TestPropertySource("classpath:application-dev.yaml")
-//@AutoConfigureMockMvc
public class RepositoryIT {
@Autowired
private AssetRepository assetRepository;
}
+ @Test
+ public void queryForExport() {
+ List<AssetSync> assetSyncs = new ArrayList<>();
+
+ for (int i = 0; i < 3; i++) {
+ assetSyncs.add(AssetSync.builder()
+ .syncType(SyncType.INSERT)
+ .catalogId("XXX" + i)
+ .build());
+ assetSyncs.add(AssetSync.builder()
+ .syncType(SyncType.UPDATE)
+ .catalogId("YYY" + i)
+ .build());
+ assetSyncs.add(AssetSync.builder()
+ .syncType(SyncType.DELETE)
+ .catalogId("ZZZ" + i)
+ .build());
+ }
+ assetSyncRepository.saveAllAndFlush(assetSyncs);
+
+ while (true) {
+ List<AssetSync> result = assetSyncRepository.findFirst100ByExportedSuccessIsNullOrderByCreated();
+ if (result.isEmpty()) {
+ break;
+ }
+ result.forEach(this::processAssetSync);
+ }
+
+ List<AssetSync> result = assetSyncRepository.findFirst100ByExportedSuccessIsNullOrderByCreated();
+ assertTrue(result.isEmpty());
+ assetSyncRepository.deleteAllInBatch();
+ }
+
+ private void processAssetSync(AssetSync assetSync) {
+ assetSync.setExportedSuccess(java.util.Date.from(Instant.now()));
+ assetSyncRepository.saveAndFlush(assetSync);
+ log.info("Processed {}", assetSync);
+ }
+
}
+++ /dev/null
-/*
- * Copyright (c) $today.year-$today.month-24.
- * By elGekko
- */
-
-package hu.user.mcvodsync;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.context.SpringBootTest;
-
-
-@SpringBootTest
-public class VodSyncEntryTest {
-
-
- @Test
- public void contextLoads() {
-
- }
-
-}
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
-import org.junit.jupiter.api.Order;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@ActiveProfiles("dev")
@TestPropertySource("classpath:application-dev.yaml")
public class VodXlsProcessorIT {
+
@Autowired
private VodXlsProcessor vodXlsProcessor;
}
@Test
- @Order(5)
public void changePlaylistAddAssetTest() {
log.info("changePlaylistAddAssetTest");
// "src/test/resources/testdata-playlist-add-asset.xlsx"
}
@Test
- @Order(6)
public void changePlaylistRemoveAssetTest() {
log.info("changePlaylistRemoveAssetTest");
// "src/test/resources/testdata-playlist-remove-asset.xlsx"
assertEquals(expectedAllCount, playlistSyncRepository.count());
}
+
}
<artifactId>org.apache.oltu.oauth2.client</artifactId>
<version>0.31</version>
</dependency>
+ <!-- <dependency>-->
+ <!-- <groupId>org.apache.httpcomponents</groupId>-->
+ <!-- <artifactId>httpcore</artifactId>-->
+ <!-- <version>4.4.16</version>-->
+ <!-- </dependency>-->
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.14</version>
+ </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
package hu.user.mcvodsync.brightcove;
+import com.brightcove.cms.client.ApiClient;
import com.brightcove.cms.client.api.PlaylistsApi;
import com.brightcove.cms.client.api.VideosApi;
-import com.brightcove.cms.client.model.CreateVideoRequestBodyFields;
-import com.brightcove.cms.client.model.Playlist;
-import com.brightcove.cms.client.model.Video;
+import com.brightcove.cms.client.model.*;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.oltu.oauth2.client.OAuthClient;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
@Log4j2
@Service
public class BrightCoveClient {
private String authToken;
public static final String BEARER = "Bearer ";
+ private final ApiClient apiClient = new ExtendedApiClient();
private final PlaylistsApi playListApi = new PlaylistsApi();
-
private final VideosApi videosApi = new VideosApi();
@Autowired
private ApiProperties apiProperties;
+ public BrightCoveClient() {
+ playListApi.setApiClient(apiClient);
+ videosApi.setApiClient(apiClient);
+ }
+
public String createToken() {
String token = null;
try {
return authToken;
}
- public List<Playlist> getPlayLists(int offset, int limit) throws RestClientException {
+ public Playlist updatePlaylist(Playlist playlist) {
+ PlaylistInputFields fields = new PlaylistInputFields();
+ fields.setVideoIds(playlist.getVideoIds());
+ fields.setDescription(playlist.getDescription());
+ fields.setType(PlaylistInputFields.TypeEnum.EXPLICIT);
+ fields.setName(playlist.getName());
+ return playListApi.updatePlaylist(apiProperties.getAccountId(), playlist.getId(), MediaType.APPLICATION_JSON_VALUE, getToken(), fields);
+ }
+
+ public Playlist createPlaylist(PlaylistInputFields fields) {
+ return playListApi.createPlaylist(apiProperties.getAccountId(), MediaType.APPLICATION_JSON_VALUE, getToken(), fields);
+ }
+
+ public List<Playlist> getPlaylists(int offset, int limit) throws RestClientException {
String q = null;
String sort = null;
return playListApi.getPlaylists(apiProperties.getAccountId(), MediaType.APPLICATION_JSON_VALUE, getToken(), limit, offset, q, sort);
}
- public List<Video> getVideos(int offset, int limit) throws RestClientException {
+ public int getPlaylistCount(String query) {
+ int result = 0;
+ PlaylistCount playlistCount = playListApi.getPlaylistCount(apiProperties.getAccountId(), MediaType.APPLICATION_JSON_VALUE, getToken(), query);
+ if (Objects.nonNull(playlistCount) && Objects.nonNull(playlistCount.getCount())) {
+ result = playlistCount.getCount();
+ }
+ return result;
+ }
+
+ public boolean getPlaylistsPaged(PagedSearch<Playlist> page) throws RestClientException {
+ if (page.getCount() == 0) {
+ int count = getPlaylistCount(page.getQuery());
+ page.setCount(count);
+ if (count > 0) {
+ page.setPages((int) Math.ceil((float) count / page.getLimit()));
+ } else {
+ return false;
+ }
+ }
+ page.setPage(page.getPage() + 1);
+ if (page.getPage() > page.getPages()) {
+ return false;
+ }
+ List<Playlist> playlists = playListApi.getPlaylists(apiProperties.getAccountId(), MediaType.APPLICATION_JSON_VALUE,
+ getToken(), page.getLimit(), (page.getPage() - 1) * page.getLimit(), page.getQuery(), page.getSort());
+ if (playlists.isEmpty()) {
+ return false;
+ }
+ page.setData(playlists);
+ return true;
+ }
+
+ public int getVideosCount(String query) {
+ int result = 0;
+ VideoCount videoCount = videosApi.getVideoCount(apiProperties.getAccountId(), MediaType.APPLICATION_JSON_VALUE, getToken(), query);
+ if (Objects.nonNull(videoCount) && Objects.nonNull(videoCount.getCount())) {
+ result = videoCount.getCount();
+ }
+ return result;
+ }
+
+
+ public List<Video> getVideos(int offset, int limit, String query) throws RestClientException {
String sort = null;
- String query = null;
return videosApi.getVideos(apiProperties.getAccountId(), MediaType.APPLICATION_JSON_VALUE,
getToken(), limit, offset, sort, query);
}
+
+ public boolean getVideosPaged(PagedSearch<Video> page) throws RestClientException {
+ if (page.getCount() == 0) {
+ int count = getVideosCount(page.getQuery());
+ page.setCount(count);
+ if (count > 0) {
+ page.setPages((int) Math.ceil((float) count / page.getLimit()));
+ } else {
+ return false;
+ }
+ }
+ page.setPage(page.getPage() + 1);
+ if (page.getPage() > page.getPages()) {
+ return false;
+ }
+ List<Video> videos = videosApi.getVideos(apiProperties.getAccountId(), MediaType.APPLICATION_JSON_VALUE,
+ getToken(), page.getLimit(), (page.getPage() - 1) * page.getLimit(), page.getSort(), page.getQuery());
+ if (videos.isEmpty()) {
+ return false;
+ }
+ page.setData(videos);
+ return true;
+ }
+
+
+ public Video getVideoByReferenceId(String referenceId) throws RestClientException {
+ return videosApi.getVideoByIdOrReferenceId(apiProperties.getAccountId(), "/ref:" + referenceId, MediaType.APPLICATION_JSON_VALUE,
+ getToken(), true);
+ }
+
public Video getVideoById(String id) throws RestClientException {
return videosApi.getVideoByIdOrReferenceId(apiProperties.getAccountId(), "/" + id, MediaType.APPLICATION_JSON_VALUE,
getToken(), true);
return videosApi.createVideo(apiProperties.getAccountId(), MediaType.APPLICATION_JSON_VALUE, getToken(), fields);
}
+ public Video createVideo(Video video) {
+ CreateVideoRequestBodyFields fields = new CreateVideoRequestBodyFields();
+ fields.setName(video.getName());
+ fields.setReferenceId(video.getReferenceId());
+ fields.setCustomFields(video.getCustomFields());
+ fields.setTags(video.getTags());
+ return createVideo(fields);
+ }
+
+ public Video updateVideo(String videoId, Video video) {
+ return videosApi.updateVideo(apiProperties.getAccountId(), videoId, MediaType.APPLICATION_JSON_VALUE, getToken(), video);
+ }
+
public void deleteVideo(String id) {
videosApi.deleteVideo(apiProperties.getAccountId(), "/" + id, MediaType.APPLICATION_JSON_VALUE, getToken());
}
+ //generated VideosApi returns Video entity not a List
private ResponseEntity<List<Video>> getVideoByIdOrReferenceIdWithHttpInfo(String accountId, String videoIds, String contentType, String authorization, Boolean includeVariants) throws RestClientException {
Object postBody = null;
--- /dev/null
+package hu.user.mcvodsync.brightcove;
+
+import com.brightcove.cms.client.ApiClient;
+import com.brightcove.cms.client.CustomInstantDeserializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule;
+import org.apache.http.client.HttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.openapitools.jackson.nullable.JsonNullableModule;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;
+import org.springframework.web.client.RestTemplate;
+import org.threeten.bp.Instant;
+import org.threeten.bp.OffsetDateTime;
+import org.threeten.bp.ZonedDateTime;
+
+public class ExtendedApiClient extends ApiClient {
+ @Override
+ protected RestTemplate buildRestTemplate() {
+ RestTemplateBuilder builder = new RestTemplateBuilder();
+// RestTemplate restTemplate = builder.errorHandler(new RestTemplateResponseErrorHandler()).build();
+ RestTemplate restTemplate = builder.build();
+ for (HttpMessageConverter<?> converter : restTemplate.getMessageConverters()) {
+ if (converter instanceof AbstractJackson2HttpMessageConverter) {
+ ObjectMapper mapper = ((AbstractJackson2HttpMessageConverter) converter).getObjectMapper();
+ ThreeTenModule module = new ThreeTenModule();
+ module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT);
+ module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME);
+ module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME);
+ mapper.registerModule(module);
+ mapper.registerModule(new JsonNullableModule());
+ }
+ }
+
+ HttpClient httpClient = HttpClientBuilder.create().build();
+ HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
+ restTemplate.setRequestFactory(requestFactory);
+// // This allows us to read the response more than once - Necessary for debugging.
+// restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(restTemplate.getRequestFactory()));
+ return restTemplate;
+ }
+
+
+}
--- /dev/null
+package hu.user.mcvodsync.brightcove;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Getter
+@Setter
+@Builder
+public class PagedSearch<T> {
+ private static final int DEFAULT_LIMIT = 10;
+
+ private int count;
+
+ private int pages;
+
+ private int page;
+
+ @Builder.Default
+ private int limit = DEFAULT_LIMIT;
+
+ private String query;
+
+ private String sort;
+
+
+ private List<T> data;
+}
--- /dev/null
+package hu.user.mcvodsync.brightcove;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.ResourceAccessException;
+import org.springframework.web.client.ResponseErrorHandler;
+
+import java.io.IOException;
+
+import static org.springframework.http.HttpStatus.Series.CLIENT_ERROR;
+import static org.springframework.http.HttpStatus.Series.SERVER_ERROR;
+
+@Component
+public class RestTemplateResponseErrorHandler implements ResponseErrorHandler {
+
+ @Override
+ public boolean hasError(ClientHttpResponse httpResponse)
+ throws IOException {
+
+ return (
+ httpResponse.getStatusCode().series() == CLIENT_ERROR
+ || httpResponse.getStatusCode().series() == SERVER_ERROR);
+ }
+
+ @Override
+ public void handleError(ClientHttpResponse httpResponse) throws IOException {
+
+ if (httpResponse.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR) {
+ // handle SERVER_ERROR
+ } else if (httpResponse.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR) {
+ // handle CLIENT_ERROR
+ if (httpResponse.getStatusCode() == HttpStatus.NOT_FOUND) {
+ throw new ResourceAccessException(httpResponse.getStatusText());
+ }
+ }
+ }
+}
\ No newline at end of file
account_name: BC - Samples
approved: true
- account_id: '301925175'
- account_name: BC Home Page Player
+ account_name: BC Home PagedSearch Player
approved: true
properties:
account_id:
CREATE TABLE asset (
catalog_id VARCHAR(20) NOT NULL,
+ reference_id VARCHAR(20),
season_id BIGINT NOT NULL,
series_id BIGINT NOT NULL,
sunset DATE NOT NULL,
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
- <version>2.7.13</version>
+ <!-- <version>2.7.13</version>-->
</dependency>
<dependency>
<groupId>com.ibm.db2</groupId>
private Long seasonId;
+ private String referenceId;
+
private Long seriesId;
@Column(nullable = false)
package hu.user.mcvodsync.db;
import lombok.*;
+import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import java.io.Serializable;
private String catalogId;
- @Column(nullable = false)
+ @CreationTimestamp
+ @Column(updatable = false)
private Date created;
@Enumerated(EnumType.STRING)
package hu.user.mcvodsync.db;
import lombok.*;
+import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import java.io.Serializable;
private String playlist;
- @Column(nullable = false)
+ @CreationTimestamp
+ @Column(updatable = false)
private Date created;
@Enumerated(EnumType.STRING)
package hu.user.mcvodsync.db;
public enum SyncType {
- INSERT, UPDATE, DELETE, ERROR
+ INSERT, UPDATE, DELETE
}
import hu.user.mcvodsync.db.AssetSync;
import hu.user.mcvodsync.db.SyncType;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
+import java.util.List;
+
public interface AssetSyncRepository extends JpaRepository<AssetSync, String> {
long countBySyncType(SyncType syncType);
+ Page<AssetSync> findAllByExportedSuccessIsNullOrderByCreated(Pageable page);
+
+ List<AssetSync> findFirst100ByExportedSuccessIsNullOrderByCreated();
+
}
<artifactId>spring-context</artifactId>
<version>5.3.24</version>
</dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-mail</artifactId>
+ </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>1.4.0</version>
<scope>compile</scope>
</dependency>
+ <dependency>
+ <groupId>hu.user</groupId>
+ <artifactId>mc-vod-sync-brightcove</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
</project>
--- /dev/null
+package hu.user.mcvodsync.service;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Getter
+@Setter
+@Component
+@ConfigurationProperties(prefix = "mc-vod-sync.service")
+public class ServiceProperties {
+
+ private boolean targetVideoInsertEnabled;
+
+ private boolean targetPlaylistInsertEnabled;
+}
--- /dev/null
+package hu.user.mcvodsync.service.export;
+
+
+import com.brightcove.cms.client.model.Video;
+import hu.user.mcvodsync.brightcove.BrightCoveClient;
+import hu.user.mcvodsync.db.Asset;
+import hu.user.mcvodsync.db.AssetSync;
+import hu.user.mcvodsync.db.SyncType;
+import hu.user.mcvodsync.db.repository.AssetRepository;
+import hu.user.mcvodsync.db.repository.AssetSyncRepository;
+import hu.user.mcvodsync.db.repository.PlaylistSyncRepository;
+import hu.user.mcvodsync.service.ServiceProperties;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.persistence.EntityNotFoundException;
+import java.time.Instant;
+import java.util.Date;
+import java.util.List;
+
+@Log4j2
+@Service
+public class AssetExportService {
+ @Autowired
+ private BrightCoveClient bcClient;
+
+ @Autowired
+ private AssetRepository assetRepository;
+
+ @Autowired
+ private AssetSyncRepository assetSyncRepository;
+
+ @Autowired
+ private PlaylistSyncRepository playlistSyncRepository;
+
+ @Autowired
+ private VideoMapper videoMapper;
+
+ @Autowired
+ private ServiceProperties serviceProperties;
+
+ public void export() {
+ while (true) {
+ List<AssetSync> result = assetSyncRepository.findFirst100ByExportedSuccessIsNullOrderByCreated();
+ if (result.isEmpty()) {
+ break;
+ }
+
+ if (serviceProperties.isTargetVideoInsertEnabled()) {
+ result.forEach(this::processAssetSync);
+ } else {
+ result.forEach(this::processAssetSyncWithoutInsert);
+ }
+ }
+
+ }
+
+ @Transactional
+ public void processAssetSyncWithoutInsert(AssetSync assetSync) {
+ try {
+ if (SyncType.DELETE.equals(assetSync.getSyncType())) {
+ //delete not necessary, remove only from all playlists
+ assetSync.setExportedSuccess(Date.from(Instant.now()));
+ } else {
+ Asset asset = assetRepository.findById(assetSync.getCatalogId()).orElseThrow(EntityNotFoundException::new);
+
+ Video video = bcClient.getVideoByReferenceId(asset.getCatalogId());
+
+ Video assetVideo = videoMapper.toVideo(asset);
+ if (SyncType.INSERT.equals(assetSync.getSyncType())) {
+ Video createdVideo = bcClient.createVideo(assetVideo);
+ asset.setReferenceId(createdVideo.getId());
+ assetRepository.save(asset);
+ }
+ if (SyncType.UPDATE.equals(assetSync.getSyncType())) {
+ if (StringUtils.isBlank(asset.getReferenceId())) {
+ throw new IllegalArgumentException("Can not update Video when Asset entity reference ID is empty");
+ }
+ bcClient.updateVideo(asset.getReferenceId(), assetVideo);
+ }
+ assetSync.setExportedSuccess(Date.from(Instant.now()));
+ }
+ } catch (Exception e) {
+ log.error(e);
+ assetSync.setExportedError(Date.from(Instant.now()));
+ } finally {
+ assetSyncRepository.save(assetSync);
+ }
+ }
+
+ @Transactional
+ public void processAssetSync(AssetSync assetSync) {
+ try {
+ if (SyncType.DELETE.equals(assetSync.getSyncType())) {
+ //delete not necessary, remove only from all playlists
+ assetSync.setExportedSuccess(Date.from(Instant.now()));
+ } else {
+ Asset asset = assetRepository.findById(assetSync.getCatalogId()).orElseThrow(EntityNotFoundException::new);
+ Video assetVideo = videoMapper.toVideo(asset);
+ if (SyncType.INSERT.equals(assetSync.getSyncType())) {
+ Video createdVideo = bcClient.createVideo(assetVideo);
+ asset.setReferenceId(createdVideo.getId());
+ assetRepository.save(asset);
+ }
+ if (SyncType.UPDATE.equals(assetSync.getSyncType())) {
+ if (StringUtils.isBlank(asset.getReferenceId())) {
+ throw new IllegalArgumentException("Can not update Video when Asset entity reference ID is empty");
+ }
+ bcClient.updateVideo(asset.getReferenceId(), assetVideo);
+ }
+ assetSync.setExportedSuccess(Date.from(Instant.now()));
+ }
+ } catch (Exception e) {
+ log.error(e);
+ assetSync.setExportedError(Date.from(Instant.now()));
+ } finally {
+ assetSyncRepository.save(assetSync);
+ }
+ }
+
+}
--- /dev/null
+package hu.user.mcvodsync.service.export;
+
+import org.mapstruct.Named;
+
+@Named("CustomPropertiesTranslator")
+public class CustomPropertiesTranslator {
+
+
+}
--- /dev/null
+package hu.user.mcvodsync.service.export;
+
+import com.brightcove.cms.client.model.Video;
+import hu.user.mcvodsync.db.Asset;
+import org.mapstruct.Mapper;
+import org.mapstruct.ReportingPolicy;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+
+@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)
+public interface VideoMapper {
+
+ String NOTES = "Notes";
+ String SHOW = "Show";
+ String SEASON = "Season";
+ String EPISODE = "Episode";
+ String RATING_TV = "Rating TV";
+ String PRODUCTION_YEAR = "Production Year";
+
+ default Video toVideo(Asset asset) {
+ Video result = new Video();
+ result.setReferenceId(asset.getCatalogId());
+ result.setName(asset.getProgLocalTitle());
+ result.putCustomFieldsItem(NOTES, asset.getHubInfo());
+ result.putCustomFieldsItem(SHOW, asset.getSeasonLocalTitle());
+ if (Objects.nonNull(asset.getSeasonNr())) {
+ result.putCustomFieldsItem(SEASON, asset.getSeasonNr().toString());
+ }
+ if (Objects.nonNull(asset.getEpisodeNr())) {
+ result.putCustomFieldsItem(EPISODE, asset.getEpisodeNr().toString());
+ }
+ result.putCustomFieldsItem(RATING_TV, asset.getAgeRating());
+ if (Objects.nonNull(asset.getProductionYear())) {
+ result.putCustomFieldsItem(PRODUCTION_YEAR, asset.getProductionYear().toString());
+ }
+ return result;
+ }
+
+ default Asset toAsset(Video video) {
+ Asset result = Asset.builder()
+ .referenceId(video.getId())
+ .catalogId(video.getReferenceId())
+ .progLocalTitle(video.getName())
+ .build();
+ Optional<Map<String, String>> opCustomFields = Optional.ofNullable(video.getCustomFields());
+ opCustomFields.flatMap(fields -> Optional.ofNullable(fields.get(NOTES))).ifPresent(result::setHubInfo);
+ opCustomFields.flatMap(fields -> Optional.ofNullable(fields.get(SHOW))).ifPresent(result::setSeasonLocalTitle);
+ opCustomFields.flatMap(fields -> Optional.ofNullable(fields.get(SEASON))).ifPresent(val -> result.setSeasonNr(Integer.parseInt(val)));
+ opCustomFields.flatMap(fields -> Optional.ofNullable(fields.get(EPISODE))).ifPresent(val -> result.setEpisodeNr(Integer.parseInt(val)));
+ opCustomFields.flatMap(fields -> Optional.ofNullable(fields.get(RATING_TV))).ifPresent(result::setAgeRating);
+ opCustomFields.flatMap(fields -> Optional.ofNullable(fields.get(PRODUCTION_YEAR))).ifPresent(val -> result.setProductionYear(Integer.parseInt(val)));
+ return result;
+ }
+
+}
private Map<String, List<String>> currentPlaylists;
- private ImportSummary summary;
+ private hu.user.mcvodsync.service.xls.ImportSummary summary;
- public void prepare(ImportSummary summary) {
+ public void prepare(hu.user.mcvodsync.service.xls.ImportSummary summary) {
this.summary = summary;
currentPlaylists = getPlayLists();
}
Optional<Asset> optionalEntity = assetRepository.findById(asset.getCatalogId());
AssetSync assetSync = AssetSync.builder()
- .created(Date.from(Instant.now()))
.catalogId(asset.getCatalogId())
.build();
List<AssetSync> syncs = ids.stream().map(id -> AssetSync.builder()
.catalogId(id)
.syncType(SyncType.DELETE)
- .created(Date.from(Instant.now()))
.build()).collect(Collectors.toList());
assetSyncRepository.saveAll(syncs);
assetRepository.deleteExpired(java.sql.Date.valueOf(currentDate));
--- /dev/null
+package hu.user.mcvodsync.service.mail;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mail.SimpleMailMessage;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.stereotype.Service;
+
+@Service
+public class EmailSendService {
+ // https://www.baeldung.com/spring-email
+ @Autowired
+ private JavaMailSender emailSender;
+
+ public void sendSimpleMessage() {
+ SimpleMailMessage message = new SimpleMailMessage();
+ message.setFrom("noreply@useribm.hu");
+ message.setTo("vasary@elgekko.net");
+ message.setSubject("Teszt");
+ message.setText("Teszt1");
+ emailSender.send(message);
+ }
+}
+
</dependency>
</annotationProcessorPaths>
<compilerArgs>
- <compilerArg>
+ <arg>
-Amapstruct.defaultComponentModel=spring
- </compilerArg>
+ </arg>
</compilerArgs>
</configuration>
</plugin>