Skip to content
On this page

Windows 本地部署

警告

本地部署可能会产生一些不可预料的问题,我们强烈推荐您使用 Docker 部署。

  1. 克隆并进入 AutoBangumi 的 git 仓库:

    powershell
    git clone https://github.com/EstrellaXD/Auto_Bangumi.git
    cd Auto_Bangumi
  2. backend\src\module 目录下创建 __version__.py 文件并写入 VERSION='local', 请注意文件编码格式为 UTF-8`:

  3. 新建 python 虚拟环境、激活并安装依赖(需保证 python -V 打印的版本符合 Dockerfile 中的要求,如 FROM python:3.11-alpine AS APP

    powershell
    python -m venv env
    .\env\Scripts\Activate.ps1
    python -m pip install -r backend\requirements.txt
  4. 下载 WebUI 并安装:

    powershell
    Invoke-WebRequest -Uri "https://github.com/EstrellaXD/Auto_Bangumi/releases/latest/download/dist.zip" -OutFile "dist.zip"
    Expand-Archive -Path "dist.zip"
    mv dist\* backend\src\templates
  5. 创建 dataconfig 目录和空白的 config_dev.json(如果有必要将这些目录存储在其他位置,建议使用 Junction Directory 链接即可)

    powershell
    mkdir backend\src\data
    mkdir backend\src\config
    echo "{}" > backend\src\config\config_dev.json

    默认情况下,PowerShell 输出文件编码为 UTF-16LE,你需要将 config_dev.json 的编码格式改为 UTF-8

  6. 运行程序测试是否配置正确:

    powershell
    cd backend\src
    python main.py
  7. 接下来配置成服务以实现开机自启,以下以 nssm 为例:

    powershell
    nssm install AutoBangumi (Get-Command python).Source
    nssm set AutoBangumi AppParameters (Get-Item .\main.py).FullName
    nssm set AutoBangumi AppDirectory (Get-Item ..).FullName
    nssm set AutoBangumi Start SERVICE_DELAYED_AUTO_START
  8. [可选] 由于 3.0 版本之前 AutoBangumi 没有修改规则或者批量移动下载位置的功能,可能遇到季名不符合需要 (如《鬼灭之刃 刀匠村篇》被视作一个仅具有一季的独立的影视作品,而不是系列动画的第三季) 或者中途想继续下载但是移出库防止出现在新剧集通知中等情况,可与考虑将下载目录和库目录区分开并用 Junction Directory 相连,这样在管理库时可以随意移动软链接而不影响 AutoBangumi 的工作。比如:

    powershell
    ### Configurations
    $downloadDir = "path\to\download_dir"
    $libraryDir = "path\to\library_dir"
    $logFile = $(Join-Path -Path $download_dir -ChildPath "downloadWatcher.log")
    $subfolderCreationTimeout = 10
    $watcher = New-Object System.IO.FileSystemWatcher
    $watcher.Path = $downloadDir
    $watcher.EnableRaisingEvents = $true  
    
    function CreateJunction(
    	# The path to the folder containing junction targets, e.g. $downloadDir\<ShowName>
    	# The junction targets are its subfolders e.g. $downloadDir\<ShowName>\<SeasonName>
    	$targetRoot 
    ) {
    	# The basename of $targetRoot, e.g. <ShowName>
    	$targetRootName = Split-Path -Path $targetRoot -Leaf
    	# The path the folder where junctions are created, e.g. $libraryDir\<ShowName>
    	$junctionRoot = $(Join-Path -Path $libraryDir -ChildPath $targetRootName)
    	# Create $junctionRoot if it does not exist
    	if (!(Test-Path $junctionRoot)) {
    		New-Item -ItemType Directory -Path $junctionRoot
    		Add-Content $logFile -Value "[Information] $(Get-Date) New folder created at $junctionRoot mirroring $targetRoot."
    	}
    	# Wait up to 10 secs for a subfolder to appear in $targetRoot
    	# This is because if $targetRoot is newly created the downloader may not have created the subfolder yet
    	$junctionTargetList = $(Get-ChildItem -Path $targetRoot -Directory)
    	$subfolderWaitCount = 0
    	while ($junctionTargetList.Count -eq 0) {
    		if ($subfolderWaitCount -ge $subfolderCreationTimeout) {
    			Add-Content $logFile -Value "[Warning]     $(Get-Date) No subfolders exist in $targetRoot for junctioning, skipping."
    			Return
    		}
    		Start-Sleep -Seconds 1
    		try {
    			$junctionTargetList = $(Get-ChildItem -Path $targetRoot -Directory)
    		}
    		# If $targetRoot is removed/renamed during the wait, skip
    		catch [System.IO.DirectoryNotFoundException] {
    			Add-Content $logFile -Value "[Warning]     $(Get-Date) $targetRoot is removed/renamed during the wait, skipping."
    			Return
    		}
    		$subfolderWaitCount++
    	}
    	Get-ChildItem $junctionRoot | Where-Object {$_.LinkType -eq "Junction"} | ForEach-Object {
    		# If a junction target is non-existent, remove it
    		if (!(Test-Path $_.Target)) {
    			Remove-Item $_.FullName
    			Add-Content $logFile -Value "[Information] $(Get-Date) Junction at $($_.FullName) is removed because its target $($_.Target) is non-existent."
    		}
    		else {
    			# Remove a junction target from $junctionTargetList if a junction in $junctionRoot is already pointing to it 
    			$existingTarget = $_.Target
    			$junctionTargetList = $junctionTargetList | Where-Object {$_.FullName -ne $existingTarget}
    			Add-Content $logFile -Value "[Debug]       $(Get-Date) $($_.FullName) already exists, skipping."
    		}
    	}
    	# Create junctions for each remaining target in $junctionTargetList
    	for ($i = 0; $i -lt $junctionTargetList.Count; $i++) {
    		$junctionTarget = $junctionTargetList[$i]
    		# The default name for the junction is the name of the junction target it self, e.g. <SeasonName>
    		$junctionName = $junctionTarget.Name
    		# If a junction with the same name already exists, append the current date to the name, e.g. <SeasonName>-yyyy-MM-dd
    		if (Test-Path $(Join-Path -Path $junctionRoot -ChildPath $junctionName)) {
    			$junctionName = "$junctionName-$(Get-Date -Format "yyyy-MM-dd")"
    			# If the new name is still taken, append a random string generated by taking first 5 chars from New-Guid to the name, e.g. <SeasonName>-yyyy-MM-dd-<RandomString>
    			while (Test-Path $(Join-Path -Path $junctionRoot -ChildPath $junctionName)) {
    				$junctionName = "$junctionName-$((New-Guid).ToString().Substring(0, 5))"
    			}
    		}
    		# Create the junction
    		New-Item -ItemType Junction -Path $(Join-Path -Path $junctionRoot -ChildPath $junctionName) -Value $junctionTarget.FullName
    		Add-Content $logFile -Value "[Information] $(Get-Date) New junction created at $(Join-Path -Path $junctionRoot -ChildPath $junctionName) pointing to $junctionTarget."
    	}
    }
    
    $action = {
    	# Event arguments, see https://learn.microsoft.com/en-us/dotnet/api/system.io.filesystemeventargs
    	$details = $event.SourceEventArgs
    	$path = $details.FullPath         # Gets the full path of the affected file or directory.
    	$changeType = $details.ChangeType # Gets the change type, e.g. Created, Deleted, Renamed
    	Add-Content $logFile -Value "[Debug]       $(Get-Date) $changeType event detected at $path."
    	if (!(Test-Path $path -PathType Container)) {
    		Add-Content $logFile -Value "[Debug]       $(Get-Date) $name is not mirrored because it is not a folder."
    		Return
    	}
    	# If the directory contains .nomirror file, skip
    	if (Test-Path $(Join-Path -Path $path -ChildPath ".nomirror")) {
    		Add-Content $logFile -Value "[Debug]       $(Get-Date) $path is not mirrored because it contains .nomirror file."
    		Return
    	}
    	# Process the directory as a root of junction targets
    	$targetRoot = $path
    	# If the directory is renamed, rename its mirror directory
    	if ($changeType -eq [System.IO.WatcherChangeTypes]::Renamed) {
    		$oldJunctionRoot = $(Join-Path -Path $libraryDir -ChildPath $details.OldName)
    		$newJunctionRoot = $(Join-Path -Path $libraryDir -ChildPath $details.Name)
    		if (Test-Path $oldJunctionRoot) {
    			Rename-Item -Path $oldJunctionRoot -NewName $details.Name
    			Add-Content $logFile -Value "[Information] $(Get-Date) $oldJunctionRoot is renamed to $newJunctionRoot."
    		}
    		else {
    			Add-Content $logFile -Value "[Warning]     $(Get-Date) Junction at $oldJunctionRoot does not exist, skipping."
    		}
    	}
    	# If a directory is modified or newly created, update/create its mirror directory by creating/updating junctions to point to its subfolders
    	if ($changeType -eq [System.IO.WatcherChangeTypes]::Changed -or `
    		$changeType -eq [System.IO.WatcherChangeTypes]::Renamed -or `
    		$changeType -eq [System.IO.WatcherChangeTypes]::Created) {
    		CreateJunction $targetRoot
    	}
    }    
    
    Register-ObjectEvent -InputObject $watcher -EventName Created -Action $action
    Register-ObjectEvent -InputObject $watcher -EventName Changed -Action $action
    Register-ObjectEvent -InputObject $watcher -EventName Renamed -Action $action
    while ($true) {Start-Sleep 5}

    上述脚本定义了一个 FileSystemWatcher 来监控下载目录的变化并镜像到库目录,可以用 nssm 安装为服务自动运行。如果需要排除一个目录,则只需要在该目录下新建一个名为 .nomirror 的文件即可。

AutoBangumi Released under the MIT License. (latest: v3.1)