mirror of
https://github.com/gabehf/sonarr-anime-importer.git
synced 2026-03-17 19:26:26 -07:00
Github Repo Updates
- Upgrades Docker Go to 1.24 - Fixes lint errors - Adds github docker build and push workflow - Adds github golang lint workflow - Exposes port in Dockerfile - Adds gitignore file
This commit is contained in:
parent
925dc8a40b
commit
866cd4e580
7 changed files with 113 additions and 15 deletions
47
.github/workflows/docker.yml
vendored
Normal file
47
.github/workflows/docker.yml
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
name: Create and publish Docker image
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
env:
|
||||||
|
REGISTRY: ghcr.io
|
||||||
|
IMAGE_NAME: ${{ github.repository }}
|
||||||
|
jobs:
|
||||||
|
build-and-push-image:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Log in to the Container registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
|
- name: Build and push Docker image
|
||||||
|
id: push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: ${{ github.ref == 'refs/heads/main' }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
- name: Generate artifact attestation
|
||||||
|
uses: actions/attest-build-provenance@v2
|
||||||
|
with:
|
||||||
|
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
|
||||||
|
subject-digest: ${{ steps.push.outputs.digest }}
|
||||||
|
push-to-registry: ${{ github.ref == 'refs/heads/main' }}
|
||||||
23
.github/workflows/golangci-lint.yml
vendored
Normal file
23
.github/workflows/golangci-lint.yml
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
name: golangci-lint
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- v*
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
jobs:
|
||||||
|
golangci:
|
||||||
|
name: lint
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: golangci-lint
|
||||||
|
uses: golangci/golangci-lint-action@v7
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
args: -E bodyclose,misspell,gosec,goconst,errorlint
|
||||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
sonarr-anime-importer
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
## syntax=docker/dockerfile:1
|
## syntax=docker/dockerfile:1
|
||||||
FROM golang:1.23
|
FROM golang:1.24
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY go.mod go.sum ./
|
COPY go.mod go.sum ./
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
|
|
|
||||||
20
anilist.go
20
anilist.go
|
|
@ -102,9 +102,13 @@ func handleAniListAnimeSearch(idMap *ConcurrentMap, permaSkipIds []string) http.
|
||||||
search, err := getAniListAnimeSearch(idMap, permaSkipIds, r)
|
search, err := getAniListAnimeSearch(idMap, permaSkipIds, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(500)
|
w.WriteHeader(500)
|
||||||
w.Write([]byte(err.Error()))
|
if _, writeErr := w.Write([]byte(err.Error())); writeErr != nil {
|
||||||
|
log.Printf("Error writing error response: %v", writeErr)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
w.Write(search)
|
if _, writeErr := w.Write(search); writeErr != nil {
|
||||||
|
log.Printf("Error writing response: %v", writeErr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -187,7 +191,7 @@ func makeAniListApiCall(q url.Values) (*AniListApiResponse, error) {
|
||||||
// Build the GraphQL request body
|
// Build the GraphQL request body
|
||||||
variables := BuildGraphQLVariables(q)
|
variables := BuildGraphQLVariables(q)
|
||||||
|
|
||||||
body := map[string]interface{}{
|
body := map[string]any{
|
||||||
"query": anilistQuery,
|
"query": anilistQuery,
|
||||||
"variables": variables,
|
"variables": variables,
|
||||||
}
|
}
|
||||||
|
|
@ -201,7 +205,11 @@ func makeAniListApiCall(q url.Values) (*AniListApiResponse, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer func() {
|
||||||
|
if closeErr := resp.Body.Close(); closeErr != nil {
|
||||||
|
log.Printf("Error closing response body: %v", closeErr)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
respData := new(AniListApiResponse)
|
respData := new(AniListApiResponse)
|
||||||
err = json.NewDecoder(resp.Body).Decode(respData)
|
err = json.NewDecoder(resp.Body).Decode(respData)
|
||||||
|
|
@ -212,8 +220,8 @@ func makeAniListApiCall(q url.Values) (*AniListApiResponse, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildGraphQLVariables converts URL query parameters into a GraphQL variables map.
|
// BuildGraphQLVariables converts URL query parameters into a GraphQL variables map.
|
||||||
func BuildGraphQLVariables(params url.Values) map[string]interface{} {
|
func BuildGraphQLVariables(params url.Values) map[string]any {
|
||||||
vars := make(map[string]interface{})
|
vars := make(map[string]any)
|
||||||
|
|
||||||
// Helper to convert comma-separated strings into slices
|
// Helper to convert comma-separated strings into slices
|
||||||
parseList := func(key string) []string {
|
parseList := func(key string) []string {
|
||||||
|
|
|
||||||
27
main.go
27
main.go
|
|
@ -20,11 +20,13 @@ type ResponseItem struct {
|
||||||
AniListId int `json:"anilistId,omitempty"`
|
AniListId int `json:"anilistId,omitempty"`
|
||||||
TvdbId int `json:"tvdbId"`
|
TvdbId int `json:"tvdbId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AnimeEntry struct {
|
type AnimeEntry struct {
|
||||||
TvdbId int `json:"tvdb_id"`
|
TvdbId int `json:"tvdb_id"`
|
||||||
MalId interface{} `json:"mal_id"`
|
MalId any `json:"mal_id"`
|
||||||
AniListId int `json:"anilist_id"`
|
AniListId int `json:"anilist_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConcurrentMap struct {
|
type ConcurrentMap struct {
|
||||||
mal map[int]int
|
mal map[int]int
|
||||||
mut sync.RWMutex
|
mut sync.RWMutex
|
||||||
|
|
@ -38,8 +40,10 @@ func (m *ConcurrentMap) GetByMalId(i int) int {
|
||||||
|
|
||||||
var lastBuiltAnimeIdList time.Time
|
var lastBuiltAnimeIdList time.Time
|
||||||
|
|
||||||
|
const Version = "v0.2.1"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.Println("sonarr-anime-importer v0.2.1")
|
log.Printf("sonarr-anime-importer %s", Version)
|
||||||
log.Println("Building Anime ID Associations...")
|
log.Println("Building Anime ID Associations...")
|
||||||
var idMap = new(ConcurrentMap)
|
var idMap = new(ConcurrentMap)
|
||||||
buildIdMap(idMap)
|
buildIdMap(idMap)
|
||||||
|
|
@ -57,7 +61,14 @@ func main() {
|
||||||
http.HandleFunc("/v1/mal/anime", loggerMiddleware(buildIdMapMiddleware(handleMalAnimeSearch(idMap, permaSkipMalIds))))
|
http.HandleFunc("/v1/mal/anime", loggerMiddleware(buildIdMapMiddleware(handleMalAnimeSearch(idMap, permaSkipMalIds))))
|
||||||
http.HandleFunc("/v1/anilist/anime", loggerMiddleware(buildIdMapMiddleware(handleAniListAnimeSearch(idMap, permaSkipAniListIds))))
|
http.HandleFunc("/v1/anilist/anime", loggerMiddleware(buildIdMapMiddleware(handleAniListAnimeSearch(idMap, permaSkipAniListIds))))
|
||||||
log.Println("Listening on :3333")
|
log.Println("Listening on :3333")
|
||||||
log.Fatal(http.ListenAndServe(":3333", nil))
|
|
||||||
|
srv := &http.Server{
|
||||||
|
Addr: ":3333",
|
||||||
|
ReadTimeout: 10 * time.Second,
|
||||||
|
WriteTimeout: 10 * time.Second,
|
||||||
|
IdleTimeout: 120 * time.Second,
|
||||||
|
}
|
||||||
|
log.Fatal(srv.ListenAndServe())
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildIdMap(idMap *ConcurrentMap) {
|
func buildIdMap(idMap *ConcurrentMap) {
|
||||||
|
|
@ -69,7 +80,11 @@ func buildIdMap(idMap *ConcurrentMap) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Error fetching anime_ids.json: ", err)
|
log.Fatal("Error fetching anime_ids.json: ", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer func() {
|
||||||
|
if closeErr := resp.Body.Close(); closeErr != nil {
|
||||||
|
log.Printf("Error closing response body: %v", closeErr)
|
||||||
|
}
|
||||||
|
}()
|
||||||
idListBytes, err = io.ReadAll(resp.Body)
|
idListBytes, err = io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Error reading anime_ids.json: ", err)
|
log.Fatal("Error reading anime_ids.json: ", err)
|
||||||
|
|
|
||||||
8
mal.go
8
mal.go
|
|
@ -17,9 +17,13 @@ func handleMalAnimeSearch(idMap *ConcurrentMap, permaSkipMalIds []string) http.H
|
||||||
search, err := getJikanAnimeSearch(idMap, permaSkipMalIds, r)
|
search, err := getJikanAnimeSearch(idMap, permaSkipMalIds, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(500)
|
w.WriteHeader(500)
|
||||||
w.Write([]byte(err.Error()))
|
if _, writeErr := w.Write([]byte(err.Error())); writeErr != nil {
|
||||||
|
log.Printf("Error writing error response: %v", writeErr)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
w.Write([]byte(search))
|
if _, writeErr := w.Write([]byte(search)); writeErr != nil {
|
||||||
|
log.Printf("Error writing response: %v", writeErr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue