diff --git a/RuffiansMaintenance.ipynb b/RuffiansMaintenance.ipynb new file mode 100644 index 0000000..cc91ef9 --- /dev/null +++ b/RuffiansMaintenance.ipynb @@ -0,0 +1,124 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0f39a5b4", + "metadata": {}, + "source": [ + "# Hololive" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c53648c3", + "metadata": { + "vscode": { + "languageId": "polyglot-notebook" + } + }, + "outputs": [], + "source": [ + "#!pwsh\n", + "$BaseUrl = \"http://10.16.1.100:8016/odata/HololiveSchedule\"\n", + "$TimeoutSec = 10\n", + "$ArchiveDir = \"/mnt/hdd/hololive-archive\"\n", + "\n", + "try {\n", + " $JstTz = [TimeZoneInfo]::FindSystemTimeZoneById(\"Tokyo Standard Time\")\n", + "} catch {\n", + " $JstTz = [TimeZoneInfo]::FindSystemTimeZoneById(\"Asia/Tokyo\")\n", + "}\n", + "\n", + "$nowJst = [TimeZoneInfo]::ConvertTime([DateTimeOffset]::Now, $JstTz)\n", + "$today = $nowJst.Date\n", + "$yesterdayEndLocal = $today.AddDays(-1).AddHours(23).AddMinutes(59).AddSeconds(59)\n", + "$yesterdayEnd = [DateTimeOffset]::new($yesterdayEndLocal, $JstTz.GetUtcOffset($yesterdayEndLocal))\n", + "\n", + "$params = @{\n", + " '$filter' = \"StartDt le $($yesterdayEnd.ToString('o'))\"\n", + " '$select' = \"Id,StartDt,MemberName,StreamUrl,StreamTitle,StreamImage,Md5\"\n", + "}\n", + "\n", + "function Get-QueryString($p) {\n", + " if (-not $p) { return \"\" }\n", + " ($p.GetEnumerator() | ForEach-Object {\n", + " \"{0}={1}\" -f [uri]::EscapeDataString($_.Key), [uri]::EscapeDataString($_.Value)\n", + " }) -join \"&\"\n", + "}\n", + "\n", + "$rows = @()\n", + "$url = $BaseUrl\n", + "\n", + "while ($true) {\n", + " $reqUrl = $url\n", + " $qs = Get-QueryString $params\n", + " if ($qs) {\n", + " $reqUrl = \"$url`?$qs\"\n", + " }\n", + "\n", + " $data = Invoke-RestMethod -Uri $reqUrl -Method Get -TimeoutSec $TimeoutSec\n", + " if ($null -ne $data.value) {\n", + " $rows += $data.value\n", + " }\n", + " $url = $data.'@odata.nextLink'\n", + " $params = $null\n", + " if (-not $url) { break }\n", + "}\n", + "\n", + "if (-not $rows -or $rows.Count -eq 0) {\n", + " Write-Host \"没找到需要归档的数据\"\n", + "} else {\n", + " $byMonth = @{}\n", + " foreach ($r in $rows) {\n", + " $dtObj = [TimeZoneInfo]::ConvertTime([DateTimeOffset]::Parse($r.StartDt), $JstTz)\n", + " $ym = $dtObj.ToString(\"yyyy-MM\")\n", + " if (-not $byMonth.ContainsKey($ym)) { $byMonth[$ym] = @() }\n", + " $byMonth[$ym] += $r\n", + " }\n", + "\n", + " foreach ($ym in $byMonth.Keys) {\n", + " $items = $byMonth[$ym]\n", + " $path = Join-Path $ArchiveDir \"$ym.csv\"\n", + "\n", + " $existing = @{}\n", + " if (Test-Path $path) {\n", + " Import-Csv -Path $path | ForEach-Object {\n", + " $existing[$_.Md5] = $_\n", + " }\n", + " }\n", + "\n", + " foreach ($r in $items) {\n", + " $existing[$r.Md5] = [pscustomobject]@{\n", + " StartDt = $r.StartDt\n", + " MemberName = $r.MemberName\n", + " StreamUrl = $r.StreamUrl\n", + " StreamTitle = $r.StreamTitle\n", + " StreamImage = $(if ($null -eq $r.StreamImage) { \"\" } else { $r.StreamImage })\n", + " Md5 = $r.Md5\n", + " }\n", + " }\n", + "\n", + " $existing.Values | Sort-Object StartDt | Export-Csv -Path $path -NoTypeInformation -Encoding UTF8\n", + " Write-Host \"ARCHIVED $ym.csv : $($items.Count) 条\"\n", + " }\n", + "\n", + " foreach ($r in $rows) {\n", + " $deleteUrl = \"$BaseUrl($($r.Id))\"\n", + " Invoke-RestMethod -Uri $deleteUrl -Method Delete -TimeoutSec $TimeoutSec | Out-Null\n", + " Write-Host \"DELETE $($r.StartDt) | $($r.StreamTitle)\"\n", + " }\n", + "\n", + " Write-Host \"完成,归档并删除 $($rows.Count) 条\"\n", + "}\n" + ] + } + ], + "metadata": { + "language_info": { + "name": "csharp" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}