6 Commits

Author SHA1 Message Date
Gitea CI
c7a6902799 Bump version: 0.1.1 → 0.1.2 2025-12-06 08:08:12 +00:00
71a4a5d657 Merge pull request 'dev' (#5) from dev into main
Reviewed-on: #5
2025-12-06 08:07:46 +00:00
ae4ea749f8 Refactor Gitea CI workflow inputs and streamline job steps in build.yaml 2025-12-06 09:07:28 +01:00
b232997ed8 fix changelog name 2025-12-06 09:04:28 +01:00
1acd848c4e Merge pull request 'update code' (#4) from dev into main
Reviewed-on: #4
2025-12-06 08:03:47 +00:00
254a8567e7 update code 2025-12-06 09:02:54 +01:00
9 changed files with 248 additions and 104 deletions

View File

@@ -1,5 +1,5 @@
[tool.bumpversion]
current_version = "0.1.1"
current_version = "0.1.2"
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
serialize = ["{major}.{minor}.{patch}"]
search = "{current_version}"

View File

@@ -0,0 +1,103 @@
{
"categories": [
{
"title": "## 🚀 Features",
"labels": [
"add",
"Add",
"Kind/Feature",
"feat",
"Feature",
"Feat"
]
},
{
"title": "## 🧰 Enhancements",
"labels": [
"enhancement",
"Enhancement",
"Kind/Enhancement",
"improvement",
"Improvement",
"Kind/Improvement"
]
},
{
"title": "## 🐛 Fixes",
"labels": [
"fix",
"Fix",
"Kind/Bug",
"Kind/Security"
]
},
{
"title": "## 🧪 Upgrade",
"labels": ["upgrade","Upgrade","Clean"]
}
,
{
"title": "## 📝 Documentation",
"labels": ["docs","Docs", "Kind/Documentation"]
},
{
"title": "## 🛠️ Maintenance",
"labels": [
"maintenance",
"Maintenance",
"Kind/Maintenance",
"chore",
"Chore",
"Kind/Chore"
]
},
{
"title": "## ⏪ Reverts",
"labels": [
"revert",
"Revert",
"Kind/Revert",
"Kind/Reverts",
"reverts",
"Reverts"
]
},
{
"title": "## 🗑️ Deprecation",
"labels": ["deprecation","Deprecation", "Kind/Deprecation"]
},
{
"title": "## ⚡️ Performance Improvements",
"labels": [
"perf",
"Perf",
"Kind/Performance"
]
},
{
"title": "## 🎨 Styling",
"labels": [
"style",
"Style",
"Kind/Style"
]
},
{
"title": "## 🎯 Other Changes",
"labels": []
}
],
"label_extractor": [
{
"pattern": "(\\w+) (.+)",
"target": "$1",
"on_property": "title"
}
],
"sort": "ASC",
"template": "${{CHANGELOG}}",
"pr_template": "- ${{TITLE}}\n - PR: #${{NUMBER}}",
"empty_template": "- no changes",
"max_pull_requests": 1000,
"max_back_track_time_days": 1000
}

View File

@@ -1,80 +1,83 @@
on:
workflow_dispatch:
inputs:
release_notes:
description: Release notes (use \n for newlines)
type: string
required: false
github_release:
description: 'Create Gitea Release'
description: "Create Gitea Release"
default: true
type: boolean
bump:
description: 'Bump type'
description: "Bump type"
required: true
default: 'patch'
default: "patch"
type: choice
options:
- 'major'
- 'minor'
- 'patch'
- "major"
- "minor"
- "patch"
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@master
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Set up Python
run: uv python install
- name: Set Git identity
run: |
git config user.name "Gitea CI"
git config user.email "ci@git.theprivateserver.de"
- name: Bump version
id: bump
run: |
uv tool install bump-my-version
uv tool run bump-my-version bump ${{ github.event.inputs.bump }}
# echo the version to github env, the version is shown by using uv tool run bump-my-version show current_version
echo "VERSION<<EOF" >> $GITHUB_ENV
echo "$(uv tool run bump-my-version show current_version)" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Push changes
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.ref }}
- name: Create release notes
run: |
mkdir release_notes
echo -e "${{ inputs.release_notes }}" >> release_notes/release_notes.md
echo "Release notes:"
cat release_notes/release_notes.md
echo ""
- name: Build package
run: uv build
- name: Publish package
env:
USERNAME: ${{ github.repository_owner }}
run: uv publish --publish-url https://git.theprivateserver.de/api/packages/$USERNAME/pypi/ -t ${{ secrets.TOKEN }}
- name: Checkout code
uses: actions/checkout@master
with:
fetch-depth: 0
fetch-tags: true
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Set up Python
run: uv python install
with:
python-version-file: "pyproject.toml"
- name: Set Git identity
run: |
git config user.name "Gitea CI"
git config user.email "ci@git.theprivateserver.de"
- name: Bump version
id: bump
run: |
uv tool install bump-my-version
uv tool run bump-my-version bump ${{ github.event.inputs.bump }}
# echo the version to github env, the version is shown by using uv tool run bump-my-version show current_version
echo "VERSION<<EOF" >> $GITHUB_ENV
echo "$(uv tool run bump-my-version show current_version)" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Push changes
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.ref }}
- name: Build Changelog
id: build_changelog
uses: https://github.com/mikepenz/release-changelog-builder-action@v5
with:
platform: "gitea"
baseURL: "http://192.168.178.110:3000"
configuration: ".gitea/changelog_config.json"
- name: Create release
id: create_release
if: ${{ github.event.inputs.github_release == 'true' }}
uses: softprops/action-gh-release@master
with:
tag_name: ${{ env.VERSION }}
release_name: Release ${{ env.VERSION }}
body_path: release_notes/release_notes.md
draft: false
prerelease: false
make_latest: true
files: |
dist/*
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}
env:
GITHUB_TOKEN: ${{ secrets.GITEA_TOKEN }}
- name: Build package
run: uv build
- name: Publish package
env:
USERNAME: ${{ github.repository_owner }}
run: uv publish --publish-url https://git.theprivateserver.de/api/packages/$USERNAME/pypi/ -t ${{ secrets.TOKEN }}
- name: Create release
uses: softprops/action-gh-release@master
id: create_release
if: ${{ github.event.inputs.github_release == 'true' }}
with:
tag_name: v${{ env.VERSION }}
release_name: Release v${{ env.VERSION }}
body: ${{steps.build_changelog.outputs.changelog}}
draft: false
prerelease: false
make_latest: true
files: |
dist/*
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}

View File

@@ -1,6 +1,6 @@
[project]
name = "anilistapi"
version = "0.1.1"
version = "0.1.2"
description = "Add your description here"
readme = "README.md"
authors = [{ name = "WorldTeacher", email = "coding_contact@pm.me" }]
@@ -12,7 +12,10 @@ requires = ["hatchling"]
build-backend = "hatchling.build"
[dependency-groups]
test = ["pytest>=8.3.4"]
test = [
"pytest>=8.3.4",
"pytest-cov>=6.2.1",
]
[tool.pytest.ini_options]
testpaths = ["tests"]

View File

@@ -2,4 +2,5 @@ from importlib.metadata import version
__version__ = version("anilistapi")
__contact__ = "coding_contact@pm.me"
from .api import AnilistAPI
__all__ = ["AnilistAPI", "MediaFormat"]
from .api import AnilistAPI, MediaFormat

View File

@@ -1,19 +1,37 @@
import requests
from .schemas.manga import Manga, Tag
from .queries.manga import (
MANGA_QUERY,
MANGA_ID_QUERY,
REQUESTS_QUERY,
GENRES_QUERY,
TAGS_QUERY,
)
from limit import limit
from anilistapi import __version__, __contact__
import os
import time
from enum import Enum
REQUEST_LIMIT = 90
REQUEST_PERIOD = 60
import requests
from limit import limit
from anilistapi import __contact__, __version__
from .queries.manga import (
GENRES_QUERY,
ID_QUERY,
REQUESTS_QUERY,
TAGS_QUERY,
)
from .schemas.manga import Manga, Tag
REQUEST_LIMIT = 1
REQUEST_PERIOD = 1
class MediaFormat(str, Enum):
MANGA = "MANGA"
NOVEL = "NOVEL"
ONE_SHOT = "ONE_SHOT"
TV = "TV"
TV_SHORT = "TV_SHORT"
MOVIE = "MOVIE"
OVA = "OVA"
ONA = "ONA"
MUSIC = "MUSIC"
SPECIAL = "SPECIAL"
# add a function to get
class AnilistAPI:
@@ -25,16 +43,24 @@ class AnilistAPI:
@limit(REQUEST_LIMIT, REQUEST_PERIOD)
def request(self, query: str, variables: dict) -> dict:
url = "https://graphql.anilist.co"
response = requests.post(url, json={"query": query, "variables": variables})
time.sleep(1)
if response.status_code != 200:
try:
response = requests.post(url, json={"query": query, "variables": variables})
time.sleep(1)
if response.status_code != 200:
return {}
# raise Exception(f"Error: {response}, response: {response.json()}, query: {query}, variables: {variables}")
return response.json()
except:
return {}
# raise Exception(f"Error: {response}, response: {response.json()}, query: {query}, variables: {variables}")
return response.json()
def search_manga(self, search: str) -> list[Manga]:
variables = {"search": search, "format": "MANGA"}
response = self.request(REQUESTS_QUERY, variables)
def search_manga(self, search: str, format: MediaFormat) -> list[Manga]:
variables = {"search": search, "format": format, "type": "MANGA"}
try:
response = self.request(REQUESTS_QUERY, variables)
except:
time.sleep(15)
return self.search_manga(search, format)
# check if reponse has data Page and media
if not response.get("data", {}).get("Page", {}).get("media"):
return []
@@ -44,15 +70,17 @@ class AnilistAPI:
return res
def get_manga(self, id: int) -> Manga:
if str(id).isnumeric():
id = int(id)
assert isinstance(id, int), "id must be an integer"
variables = {"id": id}
response = self.request(MANGA_ID_QUERY, variables)
response = self.request(ID_QUERY, variables)
if not response.get("data", {}).get("Media"):
return None
return Manga(**response["data"]["Media"])
def kompage_search(self, search: str) -> list[Manga]:
variables = {"search": search}
def kompage_search(self, search: str, format: MediaFormat) -> list[Manga]:
variables = {"search": search, "format": format, "type": "MANGA"}
response = self.request(REQUESTS_QUERY, variables)
# check if reponse has data Page and media
if not response.get("data", {}).get("Page", {}).get("media"):

View File

@@ -1,5 +1,5 @@
MANGA_QUERY = """
query media($search: String) {
QUERY = """
query media($search: String, $type: MediaType) {
Page {
pageInfo {
hasNextPage
@@ -8,7 +8,7 @@ Page {
currentPage
lastPage
}
media(type: MANGA, search: $search) {
media(type: $type, search: $search) {
id
title {
romaji
@@ -21,9 +21,9 @@ Page {
}
"""
MANGA_ID_QUERY = """
ID_QUERY = """
query media($id: Int) { # Define which variables will be used in the query (id)
Media (type: MANGA, id:$id) { # Insert our variables into the query arguments (id)
Media (id:$id) { # Insert our variables into the query arguments (id)
id
title {
romaji
@@ -53,11 +53,12 @@ Media (type: MANGA, id:$id) { # Insert our variables into the query arguments (i
type
}
countryOfOrigin
siteUrl
}
}
"""
REQUESTS_QUERY = """query query($search: String, $genres:[String], $tags:[String], $format: MediaFormat) {
REQUESTS_QUERY = """query query($search: String, $genres:[String], $tags:[String], $format: MediaFormat, $type: MediaType) {
Page(perPage: 100) {
pageInfo {
hasNextPage
@@ -66,7 +67,7 @@ Page(perPage: 100) {
currentPage
lastPage
}
media(type: MANGA, search: $search, genre_in: $genres, tag_in: $tags, sort: SEARCH_MATCH, format: $format) {
media(type: $type, search: $search, genre_in: $genres, tag_in: $tags, sort: SEARCH_MATCH, format: $format) {
id
title {
romaji
@@ -102,8 +103,8 @@ Page(perPage: 100) {
}
}"""
REQUESTED_QUERY = """query query($search: Int) {
Media(type: MANGA, id: $search, sort: SEARCH_MATCH) {
REQUESTED_QUERY = """query query($search: Int, $type: MediaType) {
Media(type: $type, id: $search, sort: SEARCH_MATCH) {
id
title {
romaji

View File

@@ -44,3 +44,7 @@ class Manga:
@property
def isLightNovel(self):
return self.format == "NOVEL"
@property
def name(self):
return self.title.__repr__()

View File

@@ -8,10 +8,11 @@ class Title:
native: str = None
def __repr__(self):
return self.english if self.english else self.native
return self.english if self.english else self.romaji if self.romaji else self.native
def __str__(self):
return self.english if self.english else self.native
return self.english if self.english else self.romaji if self.romaji else self.native
@property
def alternateTitles(self):