Initial codebase commit

This commit is contained in:
2025-05-29 01:06:19 +05:00
parent 34a9087c55
commit 5acae4abe4
15 changed files with 813 additions and 0 deletions

View File

@ -0,0 +1,13 @@
package com.backend.search.service.anyame_backend;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AnyameBackendApplication {
public static void main(String[] args) {
SpringApplication.run(AnyameBackendApplication.class, args);
}
}

View File

@ -0,0 +1,20 @@
package com.backend.search.service.anyame_backend.api;
import com.backend.search.service.anyame_backend.api.model.KodikResponse;
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
public interface KodikAPIService {
@FormUrlEncoded
@POST("search")
Call<KodikResponse> search(
@Field("token") String token,
@Field("title") String title,
@Field("limit") int limit,
@Field("with_material_data") int withMaterialData
);
}

View File

@ -0,0 +1,60 @@
package com.backend.search.service.anyame_backend.api.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
@JsonIgnoreProperties(ignoreUnknown = true)
public class KodikResponse {
public int total;
public List<Result> results;
@JsonIgnoreProperties(ignoreUnknown = true)
public static class Result {
public String id;
public String type;
public String link;
public String title;
@JsonProperty("title_orig")
public String titleOrig;
@JsonProperty("other_title")
public String otherTitle;
public Translation translation;
public int year;
@JsonProperty("last_season")
public int lastSeason;
@JsonProperty("last_episode")
public int lastEpisode;
@JsonProperty("episodes_count")
public int episodesCount;
@JsonProperty("kinopoisk_id")
public String kinopoiskId;
@JsonProperty("imdb_id")
public String imdbId;
@JsonProperty("worldart_link")
public String worldartLink;
@JsonProperty("shikimori_id")
public String shikimoriId;
public String quality;
public boolean camrip;
public boolean lgbt;
@JsonProperty("blocked_countries")
public List<String> blockedCountries;
@JsonProperty("created_at")
public String createdAt;
@JsonProperty("updated_at")
public String updatedAt;
@JsonProperty("material_data")
public MaterialData materialData;
public List<String> screenshots;
}
@JsonIgnoreProperties(ignoreUnknown = true)
public static class Translation {
public int id;
public String title;
public String type;
}
}

View File

@ -0,0 +1,83 @@
package com.backend.search.service.anyame_backend.api.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
public class MaterialData {
public String title;
@JsonProperty("anime_title")
public String animeTitle;
@JsonProperty("title_en")
public String titleEn;
@JsonProperty("other_titles")
public List<String> otherTitles;
@JsonProperty("other_titles_en")
public List<String> otherTitlesEn;
@JsonProperty("other_titles_jp")
public List<String> otherTitlesJp;
@JsonProperty("anime_license_name")
public String animeLicenseName;
@JsonProperty("anime_licensed_by")
public List<String> animeLicensedBy;
@JsonProperty("anime_kind")
public String animeKind;
@JsonProperty("all_status")
public String allStatus;
@JsonProperty("anime_status")
public String animeStatus;
public int year;
public String description;
@JsonProperty("anime_description")
public String animeDescription;
@JsonProperty("poster_url")
public String posterUrl;
@JsonProperty("anime_poster_url")
public String animePosterUrl;
public List<String> screenshots;
public int duration;
public List<String> countries;
@JsonProperty("all_genres")
public List<String> allGenres;
public List<String> genres;
@JsonProperty("anime_genres")
public List<String> animeGenres;
@JsonProperty("anime_studios")
public List<String> animeStudios;
@JsonProperty("kinopoisk_rating")
public double kinopoiskRating;
@JsonProperty("kinopoisk_votes")
public int kinopoiskVotes;
@JsonProperty("imdb_rating")
public double imdbRating;
@JsonProperty("imdb_votes")
public int imdbVotes;
@JsonProperty("shikimori_rating")
public double shikimoriRating;
@JsonProperty("shikimori_votes")
public int shikimoriVotes;
@JsonProperty("premiere_world")
public String premiereWorld;
@JsonProperty("aired_at")
public String airedAt;
@JsonProperty("released_at")
public String releasedAt;
@JsonProperty("rating_mpaa")
public String ratingMpaa;
@JsonProperty("minimal_age")
public int minimalAge;
@JsonProperty("episodes_total")
public int episodesTotal;
@JsonProperty("episodes_aired")
public int episodesAired;
public List<String> actors;
public List<String> directors;
public List<String> producers;
public List<String> writers;
public List<String> composers;
public List<String> editors;
public List<String> designers;
public List<String> operators;
}

View File

@ -0,0 +1,15 @@
package com.backend.search.service.anyame_backend.component;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class KodikAPITokenProvider {
@Value("${KODIK_TOKEN}")
private String kodikToken;
public String getKodikToken() {
return kodikToken;
}
}

View File

@ -0,0 +1,27 @@
package com.backend.search.service.anyame_backend.config;
import com.backend.search.service.anyame_backend.api.KodikAPIService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import retrofit2.Retrofit;
import retrofit2.converter.jackson.JacksonConverterFactory;
@Configuration
public class APIConfig {
private static final String KODIK_API_URL = "https://kodikapi.com/";
@Bean
public Retrofit retrofit() {
return new Retrofit.Builder()
.baseUrl(KODIK_API_URL)
.addConverterFactory(JacksonConverterFactory.create())
.build();
}
@Bean
public KodikAPIService kodikAPIService(Retrofit retrofit) {
return retrofit.create(KodikAPIService.class);
}
}

View File

@ -0,0 +1,44 @@
package com.backend.search.service.anyame_backend.config;
import com.backend.search.service.anyame_backend.api.KodikAPIService;
import com.backend.search.service.anyame_backend.api.model.KodikResponse;
import com.backend.search.service.anyame_backend.component.KodikAPITokenProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.RestController;
import org.springframework.web.server.ResponseStatusException;
import retrofit2.Response;
import java.io.IOException;
@RestController
public class SearchController {
private static final Logger log = LoggerFactory.getLogger(SearchController.class);
private final KodikAPIService kodikAPIService;
private final KodikAPITokenProvider tokenProvider;
public SearchController(KodikAPIService kodikAPIService, KodikAPITokenProvider tokenProvider) {
this.kodikAPIService = kodikAPIService;
this.tokenProvider = tokenProvider;
}
@GetMapping("/search")
public KodikResponse search(@RequestParam("title") String title) {
try {
Response<KodikResponse> response = kodikAPIService.search(tokenProvider.getKodikToken(), title, 5, 1).execute();
if (!response.isSuccessful()) {
log.info("failed search request with title {}, response code {}, message {}", title, response.code(), response.message());
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "bad response, code: " + response.code());
}
return response.body();
} catch (IOException e) {
log.warn("i/o error", e);
throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE, "i/o error");
}
}
}

View File

@ -0,0 +1 @@
spring.application.name=anyame-backend

View File

@ -0,0 +1,13 @@
package com.backend.search.service.anyame_backend;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class AnyameBackendApplicationTests {
@Test
void contextLoads() {
}
}