Skip to content

Commit abe5e0f

Browse files
authored
Merge pull request #94 from shinonomeow/shino_aio
remove some log
2 parents 6fd699d + cb88c95 commit abe5e0f

30 files changed

Lines changed: 1085 additions & 191 deletions

.github/workflows/build.yml

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,20 @@ jobs:
1313
runs-on: ubuntu-latest
1414
steps:
1515
- uses: actions/checkout@v4
16-
- name: Set up Python 3.11
17-
uses: actions/setup-python@v3
16+
- name: Install uv
17+
uses: astral-sh/setup-uv@v4
1818
with:
19-
python-version: "3.11"
19+
enable-cache: true
20+
- name: Set up Python 3.11
21+
run: uv python install 3.11
2022
- name: Install dependencies
21-
run: |
22-
python -m pip install --upgrade pip
23-
if [ -f backend/requirements.txt ]; then pip install -r backend/requirements.txt; fi
24-
pip install pytest pytest-asyncio
23+
working-directory: ./backend
24+
run: uv sync --group dev
2525
- name: Test
2626
working-directory: ./backend/src
2727
run: |
2828
mkdir -p config
29-
pytest
29+
uv run pytest
3030
3131
webui-test:
3232
runs-on: ubuntu-latest
@@ -295,9 +295,6 @@ jobs:
295295
echo ${{ needs.version-info.outputs.version }}
296296
echo "VERSION='${{ needs.version-info.outputs.version }}'" >> module/__version__.py
297297
298-
- name: Copy requirements.txt
299-
working-directory: ./backend
300-
run: cp requirements.txt src/requirements.txt
301298
302299
- name: Zip app
303300
run: |

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ __pycache__/
55

66
# C extensions
77
*.so
8+
.python-version
89

910
# Distribution / packaging
1011
.Python
@@ -176,6 +177,8 @@ cython_debug/
176177
.run
177178
/backend/src/templates/
178179
/backend/src/config/
180+
/backend/config/
181+
/backend/data/
179182
/src/debuger.py
180183
/backend/src/dist.zip
181184
/pyrightconfig.json

CLAUDE.md

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,28 @@ This sets up a Python virtual environment, installs dependencies with Tsinghua m
1515
cd backend/src && python main.py
1616
```
1717

18+
**Frontend Development:**
19+
```bash
20+
cd webui && pnpm install && pnpm run dev # Development server
21+
cd webui && pnpm run build # Production build
22+
./build-frontend.sh # Build and move to backend/src/dist
23+
```
24+
1825
**Linting and Formatting:**
1926
```bash
2027
cd backend && ./venv/bin/ruff check .
2128
cd backend && ./venv/bin/ruff format .
2229
cd backend && ./venv/bin/black .
30+
cd webui && pnpm run lint # Frontend linting
31+
cd webui && pnpm run format # Frontend formatting
2332
```
2433

2534
**Testing:**
2635
```bash
2736
cd backend && ./venv/bin/pytest
2837
cd backend && ./venv/bin/pytest test/test_specific_module.py # Run specific test
38+
cd webui && pnpm run test # Frontend tests
39+
cd webui && pnpm run test:build # TypeScript type checking
2940
```
3041

3142
## Architecture
@@ -36,9 +47,9 @@ Auto_Bangumi is an RSS-based automatic anime downloading and organization tool w
3647
- `main.py`: FastAPI application entry point with poster serving and static file mounting
3748
- `module/core/`: Core async application framework
3849
- `aiocore.py`: AsyncApplicationCore manages service lifecycle and task scheduling
39-
- `services.py`: BaseService abstract class and service implementations (RSS, Download, Renamer)
50+
- `services/`: Service implementations extending BaseService (RSS, Download, Renamer)
51+
- `monitors/`: Background monitors for downloads, notifications, and renaming
4052
- `task_manager.py`: TaskManager handles async task scheduling and execution
41-
- `events.py`: Event system for inter-service communication
4253
- `module/api/`: REST API endpoints organized by feature (auth, bangumi, config, etc.)
4354
- `module/parser/`: Content parsing system for RSS feeds, torrents, and metadata
4455
- `module/downloader/`: Download client abstractions (qBittorrent, Aria2, Transmission)
@@ -48,9 +59,12 @@ Auto_Bangumi is an RSS-based automatic anime downloading and organization tool w
4859
- `module/network/`: HTTP client abstractions with proxy and caching support
4960

5061
**Frontend Structure (Vue.js + TypeScript):**
51-
- Located in `webui/` with standard Vue project structure
62+
- Located in `webui/` with Vite build system
63+
- Uses UnoCSS for styling, Naive UI for components
64+
- Auto-import configuration for Vue Composition API
5265
- API client in `src/api/` matching backend endpoints
53-
- Component-based UI with reusable elements in `src/components/`
66+
- Pinia for state management
67+
- Vue Router with file-based routing
5468

5569
**Key Data Flow:**
5670
1. RSS feeds are parsed and analyzed for anime information
@@ -65,8 +79,22 @@ The application uses an async service-based architecture where:
6579
- AsyncApplicationCore manages service lifecycle
6680
- TaskManager schedules periodic service execution
6781
- Services communicate via events system
82+
- Monitors handle background tasks like download tracking
6883

6984
**Configuration:**
7085
- Main config in `config/config.json`
7186
- Search providers in `config/search_provider.json`
72-
- Environment variables for runtime settings
87+
- Environment variables for runtime settings
88+
89+
## Development Guidelines
90+
91+
**Branch Strategy:**
92+
- `main`: Stable releases only
93+
- `<version>-dev`: Development branches for each minor version (e.g., `3.1-dev`)
94+
- Bug fixes go to current version dev branch
95+
- New features go to next version dev branch
96+
97+
**Code Style:**
98+
- Backend: Ruff + Black formatting, Python 3.10+ target
99+
- Frontend: ESLint + Prettier, TypeScript strict mode
100+
- Pre-commit hooks enforce formatting

Dockerfile

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,35 @@ ENV LANG="C.UTF-8" \
1010

1111
WORKDIR /app
1212

13-
COPY backend/requirements.txt .
13+
# Copy Python project files
14+
COPY backend/pyproject.toml backend/uv.lock ./
15+
1416
RUN set -ex && \
1517
apk add --no-cache \
1618
bash \
1719
busybox-suid \
1820
python3 \
1921
py3-aiohttp \
2022
py3-bcrypt \
21-
py3-pip \
23+
curl \
2224
su-exec \
2325
shadow \
2426
tini \
2527
openssl \
2628
tzdata && \
27-
python3 -m pip install --no-cache-dir --upgrade pip && \
28-
sed -i '/bcrypt/d' requirements.txt && \
29-
pip install --no-cache-dir -r requirements.txt && \
29+
# Install uv
30+
curl -LsSf https://astral.sh/uv/install.sh | sh && \
31+
. $HOME/.cargo/env && \
32+
# Install dependencies using uv
33+
uv sync --frozen --no-dev && \
3034
# Add user
3135
mkdir -p /home/ab && \
3236
addgroup -S ab -g 911 && \
3337
adduser -S ab -G ab -h /home/ab -s /sbin/nologin -u 911 && \
3438
# Clear
3539
rm -rf \
3640
/root/.cache \
41+
/root/.cargo \
3742
/tmp/*
3843

3944
COPY --chmod=755 backend/src/. .

backend/README.md

Whitespace-only changes.

backend/pyproject.toml

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,89 @@
1+
[project]
2+
name = "backend"
3+
version = "0.1.0"
4+
description = "Add your description here"
5+
readme = "README.md"
6+
requires-python = ">=3.11"
7+
dependencies = [
8+
"bcrypt==4.2.0",
9+
"beautifulsoup4>=4.13.4",
10+
"bencode-py>=4.0.0",
11+
"dotenv>=0.9.9",
12+
"fastapi>=0.116.1",
13+
"httpx[http2,socks]>=0.28.1",
14+
"jinja2>=3.1.6",
15+
"packaging>=25.0",
16+
"passlib>=1.7.4",
17+
"python-jose>=3.5.0",
18+
"python-multipart>=0.0.20",
19+
"sqlmodel>=0.0.24",
20+
"sse-starlette>=3.0.2",
21+
"urllib3>=2.5.0",
22+
"uvicorn>=0.35.0",
23+
]
124
[tool.ruff]
225
select = [
326
# pycodestyle(E): https://beta.ruff.rs/docs/rules/#pycodestyle-e-w
4-
"E",
27+
"E",
528
# Pyflakes(F): https://beta.ruff.rs/docs/rules/#pyflakes-f
6-
"F",
29+
"F",
730
# isort(I): https://beta.ruff.rs/docs/rules/#isort-i
8-
"I"
31+
"I",
932
]
1033
ignore = [
1134
# E501: https://beta.ruff.rs/docs/rules/line-too-long/
12-
'E501',
35+
'E501',
1336
# F401: https://beta.ruff.rs/docs/rules/unused-import/
1437
# avoid unused imports lint in `__init__.py`
1538
'F401',
1639
]
1740

1841
# Allow autofix for all enabled rules (when `--fix`) is provided.
19-
fixable = ["A", "B", "C", "D", "E", "F", "G", "I", "N", "Q", "S", "T", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "EM", "ERA", "EXE", "FBT", "ICN", "INP", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PTH", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "TRY", "UP", "YTT"]
42+
fixable = [
43+
"A",
44+
"B",
45+
"C",
46+
"D",
47+
"E",
48+
"F",
49+
"G",
50+
"I",
51+
"N",
52+
"Q",
53+
"S",
54+
"T",
55+
"W",
56+
"ANN",
57+
"ARG",
58+
"BLE",
59+
"COM",
60+
"DJ",
61+
"DTZ",
62+
"EM",
63+
"ERA",
64+
"EXE",
65+
"FBT",
66+
"ICN",
67+
"INP",
68+
"ISC",
69+
"NPY",
70+
"PD",
71+
"PGH",
72+
"PIE",
73+
"PL",
74+
"PT",
75+
"PTH",
76+
"PYI",
77+
"RET",
78+
"RSE",
79+
"RUF",
80+
"SIM",
81+
"SLF",
82+
"TID",
83+
"TRY",
84+
"UP",
85+
"YTT",
86+
]
2087
unfixable = []
2188

2289
# Exclude a variety of commonly ignored directories.
@@ -52,12 +119,18 @@ line-length = 88
52119
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
53120

54121
# Assume Python 3.10.
55-
target-version = "py310"
122+
target-version = "py311"
56123

57124
[tool.ruff.mccabe]
58125
# Unlike Flake8, default to a complexity level of 10.
59126
max-complexity = 10
60127

61128
[tool.black]
62129
line-length = 88
63-
target-version = ['py310', 'py311']
130+
target-version = ['py311']
131+
132+
[dependency-groups]
133+
dev = [
134+
"pytest>=8.4.1",
135+
"pytest-asyncio>=1.1.0",
136+
]

backend/requirements.txt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
1-
anyio==3.7.0
21
bencode.py ==4.0.0
32
bs4==0.0.1
43
certifi==2023.5.7
54
charset-normalizer==3.1.0
6-
click==8.1.3
75
fastapi==0.97.0
8-
h11==0.14.0
96
idna==3.4
10-
pydantic~=1.10
117
httpx[http2,socks]==0.25.0
128
six==1.16.0
139
sniffio==1.3.0
1410
soupsieve==2.4.1
15-
typing_extensions==4.6.3
1611
urllib3==2.0.3
1712
uvicorn==0.22.0
1813
attrdict==2.0.1

backend/src/main.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
}
3030

3131

32-
3332
def create_app() -> FastAPI:
3433
app = FastAPI(lifespan=lifespan)
3534

@@ -66,8 +65,6 @@ async def get_poster(path: str):
6665
logger.warning(f"[Poster] Path outside allowed directory: {path}")
6766
raise HTTPException(status_code=400, detail="Path outside allowed directory")
6867

69-
logger.debug(f"[Poster] Accessing poster: {post_path}")
70-
7168
# 如果文件不存在,尝试下载
7269
if not post_path.exists():
7370
try:

backend/src/module/conf/config.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,10 @@ def check_config_key(
5858
data: dict | BaseModel, updated_data: BaseModel, config_name: str
5959
) -> bool:
6060
if isinstance(data, BaseModel):
61-
data = data.dict()
62-
updated_data = updated_data.dict()
61+
data = data.model_dump()
62+
# data = data.dict()
63+
64+
updated_data = updated_data.model_dump()
6365
for key in updated_data.keys():
6466
if key not in data:
6567
return False
@@ -96,10 +98,12 @@ def update_config(base_config: BaseModel | dict, data: dict):
9698
# 部份更新 Config
9799
# # 获取 baseconfig 的当前字段数据
98100
if isinstance(base_config, BaseModel):
99-
updated_data = base_config.dict()
101+
updated_data = base_config.model_dump()
102+
# updated_data = base_config.dict()
100103
updated_data = deep_update(updated_data, data)
101104
updated_instance = base_config.__class__.validate(updated_data)
102-
updata_dict = updated_instance.dict()
105+
updata_dict = updated_instance.model_dump()
106+
# updata_dict = updated_instance.dict()
103107
else:
104108
# 当 baseconfig 是 dict 类型时, 直接更新
105109
updated_data = base_config
@@ -142,7 +146,7 @@ def load(self):
142146

143147
def save(self, config_dict: dict | None = None):
144148
if not config_dict:
145-
config_dict = self.dict()
149+
config_dict = self.model_dump()
146150
with open(CONFIG_PATH, "w", encoding="utf-8") as f:
147151
json.dump(config_dict, f, indent=4, ensure_ascii=False)
148152

@@ -152,7 +156,7 @@ def init(self):
152156
self.save()
153157

154158
def __load_from_env(self):
155-
config_dict = self.dict()
159+
config_dict = self.model_dump()
156160
for key, section in ENV_TO_ATTR.items():
157161
for env, attr in section.items():
158162
if env in os.environ:
@@ -170,9 +174,6 @@ def __load_from_env(self):
170174
self.__dict__.update(config_obj.__dict__)
171175
logger.info("Config loaded from env")
172176

173-
def model_dump(self, **kwargs):
174-
return self.dict()
175-
176177
@staticmethod
177178
def __val_from_env(env: str, attr: tuple[str, Callable[..., Any]] | str):
178179
if isinstance(attr, tuple):

0 commit comments

Comments
 (0)