diff --git a/pom.xml b/pom.xml index e7f17aa..96671ba 100644 --- a/pom.xml +++ b/pom.xml @@ -1,79 +1,86 @@ - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.5.0 - - - com.backend.extractor.kodik.service - anyame-backend - 0.0.1-SNAPSHOT - anyame-backend - Kodik video URL extractor for anyame - - - - - - - - - - - - - - - 21 + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.5.0 + + + com.backend.extractor.kodik.service + anyame-backend + 0.0.1-SNAPSHOT + anyame-backend + Kodik video URL extractor for anyame + + + + + + + + + + + + + + + 21 - 3.0.0 - 1.20.1 - 4.0.0 - - - - org.springframework.boot - spring-boot-starter-web - + 3.0.0 + 1.20.1 + 4.0.0 + 2.8.9 + + + + org.springframework.boot + spring-boot-starter-web + - - com.squareup.retrofit2 - retrofit - ${retrofit.version} - - - com.squareup.retrofit2 - converter-jackson - ${retrofit.version} - - - org.jsoup - jsoup - ${jsoup.version} - - - me.paulschwarz - spring-dotenv - ${spring-dotenv.version} - + + com.squareup.retrofit2 + retrofit + ${retrofit.version} + + + com.squareup.retrofit2 + converter-jackson + ${retrofit.version} + + + org.jsoup + jsoup + ${jsoup.version} + + + me.paulschwarz + spring-dotenv + ${spring-dotenv.version} + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + ${springdoc-openapi-starter.version} + - - org.springframework.boot - spring-boot-starter-test - test - - + + org.springframework.boot + spring-boot-starter-test + test + + - - - - org.springframework.boot - spring-boot-maven-plugin - - - + + + + org.springframework.boot + spring-boot-maven-plugin + + + diff --git a/src/main/java/com/backend/extractor/kodik/service/anyame_backend/AnyameBackendApplication.java b/src/main/java/com/backend/extractor/kodik/service/anyame_backend/AnyameBackendApplication.java index a6a2cdc..c70130b 100644 --- a/src/main/java/com/backend/extractor/kodik/service/anyame_backend/AnyameBackendApplication.java +++ b/src/main/java/com/backend/extractor/kodik/service/anyame_backend/AnyameBackendApplication.java @@ -2,12 +2,26 @@ package com.backend.extractor.kodik.service.anyame_backend; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @SpringBootApplication public class AnyameBackendApplication { - public static void main(String[] args) { - SpringApplication.run(AnyameBackendApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(AnyameBackendApplication.class, args); + } + + // TODO: Research if this is good approach or not? + @Bean + public WebMvcConfigurer corsConfigurer() { + return new WebMvcConfigurer() { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**").allowedOrigins("http://localhost:3000"); + } + }; + } } diff --git a/src/main/java/com/backend/extractor/kodik/service/anyame_backend/controller/ExtractController.java b/src/main/java/com/backend/extractor/kodik/service/anyame_backend/controller/ExtractController.java index bb48195..4492e5f 100644 --- a/src/main/java/com/backend/extractor/kodik/service/anyame_backend/controller/ExtractController.java +++ b/src/main/java/com/backend/extractor/kodik/service/anyame_backend/controller/ExtractController.java @@ -4,74 +4,40 @@ import java.io.IOException; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.server.ResponseStatusException; -import com.backend.extractor.kodik.service.anyame_backend.api.KodikPlayerAPI; -import com.backend.extractor.kodik.service.anyame_backend.api.model.KodikPlayerResponse; import com.backend.extractor.kodik.service.anyame_backend.api.model.KodikVideoLinks; -import com.backend.extractor.kodik.service.anyame_backend.component.KodikAPITokenProvider; +import com.backend.extractor.kodik.service.anyame_backend.dto.KodikTranslationDTO; import com.backend.extractor.kodik.service.anyame_backend.exception.KodikAPINotFoundException; import com.backend.extractor.kodik.service.anyame_backend.exception.KodikDecryptionException; import com.backend.extractor.kodik.service.anyame_backend.exception.KodikExtractionException; import com.backend.extractor.kodik.service.anyame_backend.exception.KodikPlayerNotFoundException; import com.backend.extractor.kodik.service.anyame_backend.service.KodikExtractService; import com.backend.extractor.kodik.service.anyame_backend.service.KodikURLDecoderService; -import com.backend.extractor.kodik.service.anyame_backend.service.model.KodikMetadata; - -import retrofit2.Response; /** * ExtractController */ @RestController +@RequestMapping("/extract") public class ExtractController { - private final KodikPlayerAPI kodikPlayerAPI; - private final KodikAPITokenProvider tokenProvider; private final KodikExtractService extractService; private final KodikURLDecoderService decoderService; public ExtractController( - KodikPlayerAPI kodikPlayerAPI, - KodikAPITokenProvider tokenProvider, KodikExtractService extractService, + KodikExtractService extractService, KodikURLDecoderService decoderService) { - this.kodikPlayerAPI = kodikPlayerAPI; - this.tokenProvider = tokenProvider; this.extractService = extractService; this.decoderService = decoderService; } - @GetMapping("/shikimori") - public KodikMetadata shikimori(@RequestParam("id") String shikimoriId) { + @GetMapping("/video") + public KodikVideoLinks video(KodikTranslationDTO translationDTO, String quality, int episode) { try { - Response response = kodikPlayerAPI - .getShikimoriPlayer(shikimoriId, tokenProvider.getKodikToken()).execute(); - if (!response.isSuccessful()) { - throw new ResponseStatusException(HttpStatus.NOT_FOUND, "cannot find player, check id validity"); - } - KodikPlayerResponse responseResult = response.body(); - String url = responseResult.getLink(); - return extractService.getMetadata(url); - } catch (KodikExtractionException e) { - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "cannot retrieve metadat", e); - } catch (IOException e) { - throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "i/o error"); - } - } - - @GetMapping("/shikimori/video") - public KodikVideoLinks shikimoriVideo(@RequestParam("id") String shikimoriId) { - try { - Response response = kodikPlayerAPI - .getShikimoriPlayer(shikimoriId, tokenProvider.getKodikToken()).execute(); - if (!response.isSuccessful()) { - throw new ResponseStatusException(HttpStatus.NOT_FOUND, "cannot find player, check id validity"); - } - KodikPlayerResponse responseResult = response.body(); - String url = responseResult.getLink(); - KodikVideoLinks links = extractService.retrieveVideoLinks(url); + KodikVideoLinks links = extractService.retrieveVideoLinks(translationDTO.buildUrl(quality, episode)); links.decodeLinks(decoderService); return links; } catch (KodikExtractionException e) { diff --git a/src/main/java/com/backend/extractor/kodik/service/anyame_backend/controller/MetadataController.java b/src/main/java/com/backend/extractor/kodik/service/anyame_backend/controller/MetadataController.java new file mode 100644 index 0000000..8359b0a --- /dev/null +++ b/src/main/java/com/backend/extractor/kodik/service/anyame_backend/controller/MetadataController.java @@ -0,0 +1,71 @@ +package com.backend.extractor.kodik.service.anyame_backend.controller; + +import java.io.IOException; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; + +import com.backend.extractor.kodik.service.anyame_backend.api.KodikPlayerAPI; +import com.backend.extractor.kodik.service.anyame_backend.api.model.KodikPlayerResponse; +import com.backend.extractor.kodik.service.anyame_backend.component.KodikAPITokenProvider; +import com.backend.extractor.kodik.service.anyame_backend.exception.KodikExtractionException; +import com.backend.extractor.kodik.service.anyame_backend.service.KodikExtractService; +import com.backend.extractor.kodik.service.anyame_backend.service.model.KodikMetadata; + +import retrofit2.Response; + +@RestController +@RequestMapping("/metadata") +public class MetadataController { + private final KodikPlayerAPI kodikPlayerAPI; + private final KodikAPITokenProvider tokenProvider; + private final KodikExtractService extractService; + + public MetadataController( + KodikPlayerAPI kodikPlayerAPI, + KodikAPITokenProvider tokenProvider, KodikExtractService extractService) { + this.kodikPlayerAPI = kodikPlayerAPI; + this.tokenProvider = tokenProvider; + this.extractService = extractService; + } + + @GetMapping("/shikimori") + public KodikMetadata shikimori(@RequestParam("id") String shikimoriId) { + try { + Response response = kodikPlayerAPI + .getShikimoriPlayer(shikimoriId, tokenProvider.getKodikToken()).execute(); + if (!response.isSuccessful()) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "cannot find player, check id validity"); + } + KodikPlayerResponse responseResult = response.body(); + String url = responseResult.getLink(); + return extractService.getMetadata(url); + } catch (KodikExtractionException e) { + throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "cannot retrieve metadat", e); + } catch (IOException e) { + throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "i/o error"); + } + } + + @GetMapping("/kodik") + public KodikMetadata kodik(@RequestParam("id") String kodikId) { + try { + Response response = kodikPlayerAPI + .getKodikIDPlayer(kodikId, tokenProvider.getKodikToken()).execute(); + if (!response.isSuccessful()) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "cannot find player, check id validity"); + } + KodikPlayerResponse responseResult = response.body(); + String url = responseResult.getLink(); + return extractService.getMetadata(url); + } catch (KodikExtractionException e) { + throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "cannot retrieve metadat", e); + } catch (IOException e) { + throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "i/o error"); + } + } +} diff --git a/src/main/java/com/backend/extractor/kodik/service/anyame_backend/dto/KodikTranslationDTO.java b/src/main/java/com/backend/extractor/kodik/service/anyame_backend/dto/KodikTranslationDTO.java new file mode 100644 index 0000000..92ed1c6 --- /dev/null +++ b/src/main/java/com/backend/extractor/kodik/service/anyame_backend/dto/KodikTranslationDTO.java @@ -0,0 +1,45 @@ +package com.backend.extractor.kodik.service.anyame_backend.dto; + +public class KodikTranslationDTO { + + // TODO: NotBlank and other validation annotations can be added as needed + private String mediaType; + private String mediaId; + private String mediaHash; + + public KodikTranslationDTO(String mediaType, String mediaId, String mediaHash) { + this.mediaType = mediaType; + this.mediaId = mediaId; + this.mediaHash = mediaHash; + } + + public String getMediaType() { + return mediaType; + } + + public void setMediaType(String mediaType) { + this.mediaType = mediaType; + } + + public String getMediaId() { + return mediaId; + } + + public void setMediaId(String mediaId) { + this.mediaId = mediaId; + } + + public String getMediaHash() { + return mediaHash; + } + + public void setMediaHash(String mediaHash) { + this.mediaHash = mediaHash; + } + + public String buildUrl(String quality, int episodeNumber) { + return String.format("https://kodik.info/%s/%s/%s/720p?min_age=16&first_url=false&season=1&episode=%d", + mediaType, mediaId, mediaHash, episodeNumber); + } + +} diff --git a/src/main/java/com/backend/extractor/kodik/service/anyame_backend/service/KodikExtractService.java b/src/main/java/com/backend/extractor/kodik/service/anyame_backend/service/KodikExtractService.java index 7f835d4..c4cd9ce 100644 --- a/src/main/java/com/backend/extractor/kodik/service/anyame_backend/service/KodikExtractService.java +++ b/src/main/java/com/backend/extractor/kodik/service/anyame_backend/service/KodikExtractService.java @@ -38,12 +38,6 @@ public class KodikExtractService { } } - public KodikVideoLinks retrieveVideoLinks(KodikTranslation translation, int episode) - throws KodikExtractionException, IOException, KodikPlayerNotFoundException, KodikAPINotFoundException { - String episodeUrl = translation.buildUrl(episode); - return retrieveVideoLinks(episodeUrl); - } - public KodikVideoLinks retrieveVideoLinks(String episodeUrl) throws KodikExtractionException, IOException, KodikPlayerNotFoundException, KodikAPINotFoundException { KodikMetadata metadata = getMetadata(episodeUrl); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 7b3fc30..faed815 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,2 +1,3 @@ spring.application.name=anyame-backend server.error.include-message=always +server.port=8081