Separate metadata and extraction to controllers

This commit is contained in:
2025-06-23 00:54:06 +05:00
parent 891b441550
commit 01ae2e3b1d
7 changed files with 220 additions and 122 deletions

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@ -32,6 +33,7 @@
<retrofit.version>3.0.0</retrofit.version>
<jsoup.version>1.20.1</jsoup.version>
<spring-dotenv.version>4.0.0</spring-dotenv.version>
<springdoc-openapi-starter.version>2.8.9</springdoc-openapi-starter.version>
</properties>
<dependencies>
<dependency>
@ -59,6 +61,11 @@
<artifactId>spring-dotenv</artifactId>
<version>${spring-dotenv.version}</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>${springdoc-openapi-starter.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@ -2,6 +2,9 @@ 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 {
@ -10,4 +13,15 @@ public class AnyameBackendApplication {
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");
}
};
}
}

View File

@ -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<KodikPlayerResponse> 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<KodikPlayerResponse> 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) {

View File

@ -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<KodikPlayerResponse> 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<KodikPlayerResponse> 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");
}
}
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -1,2 +1,3 @@
spring.application.name=anyame-backend
server.error.include-message=always
server.port=8081