{
"cells": [
{
"cell_type": "markdown",
"id": "1bb3ca20",
"metadata": {},
"source": [
"**NEEDS** ms-dotnettools.dotnet-interactive-vscode"
]
},
{
"cell_type": "markdown",
"id": "0f39a5b4",
"metadata": {},
"source": [
"# Hololive"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c53648c3",
"metadata": {
"language_info": {
"name": "polyglot-notebook"
},
"polyglot_notebook": {
"kernelName": "pwsh"
}
},
"outputs": [],
"source": [
"#!pwsh\n",
"$BaseUrl = \"http://10.16.1.100:8016/odata/HololiveSchedule\"\n",
"$TimeoutSec = 10\n",
"$ArchiveDir = \"/mnt/hdd/hololive-archive\"\n",
"\n",
"$JstTz = [TimeZoneInfo]::FindSystemTimeZoneById(\"Asia/Tokyo\")\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",
"}"
]
},
{
"cell_type": "markdown",
"id": "dbe66321",
"metadata": {},
"source": [
"# Pixiv"
]
},
{
"cell_type": "markdown",
"id": "044ca9c0",
"metadata": {},
"source": [
"#### 删除"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6a308a9e",
"metadata": {
"language_info": {
"name": "polyglot-notebook"
},
"polyglot_notebook": {
"kernelName": "pwsh"
}
},
"outputs": [],
"source": [
"#!pwsh\n",
"$BaseUrl = \"http://10.16.1.100:8016/odata\"\n",
"$PixivId = 139864802\n",
"$BaseDir = \"/mnt/media/Picture/pixiv\"\n",
"\n",
"# ===== 查 Id =====\n",
"$resp = Invoke-RestMethod `\n",
" -Uri \"$BaseUrl/PixivImages?`$select=Id&`$filter=PixivId eq $PixivId\" `\n",
" -Method Get\n",
"\n",
"$ids = $resp.value.Id\n",
"\n",
"# ===== 删数据库 =====\n",
"foreach ($id in $ids) {\n",
" Invoke-RestMethod `\n",
" -Uri \"$BaseUrl/PixivImages($id)\" `\n",
" -Method Delete\n",
" Write-Host \"db deleted:\" $id\n",
"}\n",
"\n",
"Write-Host \"db done, count=\" $ids.Count\n",
"\n",
"# ===== 删目录 =====\n",
"$targetDir = Join-Path $BaseDir $PixivId\n",
"\n",
"if (Test-Path $targetDir) {\n",
" Remove-Item -Path $targetDir -Recurse -Force\n",
" Write-Host \"dir deleted:\" $targetDir\n",
"}\n",
"else {\n",
" Write-Host \"dir not found:\" $targetDir\n",
"}\n",
"\n",
"Write-Host \"all done\""
]
},
{
"cell_type": "markdown",
"id": "6d4e854b",
"metadata": {},
"source": [
"#### XP分析器"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "83bdcecf",
"metadata": {
"language_info": {
"name": "polyglot-notebook"
},
"polyglot_notebook": {
"kernelName": "pwsh"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"R-18: 87 of 140\n",
"R-18 ratio: 62.1429%\n",
"ホロライブ: 27\n",
"乱交: 19\n",
"おっぱい: 18\n",
"バーチャルYouTuber: 16\n",
"ポケモン: 16\n",
"百合: 15\n",
"メイ(トレーナー): 14\n",
"トウコ(トレーナー): 14\n",
"尻神様: 13\n",
"この素晴らしい世界に祝福を!: 13\n",
"めぐみん: 13\n",
"ダクネス: 10\n",
"井ノ上たきな: 10\n",
"星街すいせい: 10\n",
"錦木千束: 10\n",
"リコリス・リコイル: 10\n",
"艦これ: 10\n",
"ポケモン人間絵: 9\n",
"加藤恵: 8\n",
"VTuber: 8\n"
]
}
],
"source": [
"#!pwsh\n",
"$BaseUrl = \"http://10.16.1.100:8016/odata/PixivImages\"\n",
"$PageSize = 1000\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",
"$pixivTags = @{}\n",
"$skip = 0\n",
"\n",
"while ($true) {\n",
" $params = @{\n",
" '$select' = \"PixivId,Tags\"\n",
" '$top' = $PageSize\n",
" '$skip' = $skip\n",
" }\n",
" $qs = Get-QueryString $params\n",
" $url = \"$BaseUrl`?$qs\"\n",
"\n",
" $data = Invoke-RestMethod -Uri $url -Method Get\n",
" $items = $data.value\n",
" if (-not $items -or $items.Count -eq 0) { break }\n",
"\n",
" foreach ($item in $items) {\n",
" $pixivId = $item.PixivId\n",
" $tags = $item.Tags\n",
"\n",
" if ($null -eq $pixivId -or [string]::IsNullOrWhiteSpace($tags)) {\n",
" continue\n",
" }\n",
"\n",
" if (-not $pixivTags.ContainsKey($pixivId)) {\n",
" $pixivTags[$pixivId] = [System.Collections.Generic.HashSet[string]]::new()\n",
" }\n",
"\n",
" foreach ($tag in $tags.Split(\",\")) {\n",
" $t = $tag.Trim()\n",
" if ($t) {\n",
" $pixivTags[$pixivId].Add($t) | Out-Null\n",
" }\n",
" }\n",
" }\n",
"\n",
" if ($items.Count -lt $PageSize) { break }\n",
" $skip += $PageSize\n",
"}\n",
"\n",
"$tagCounter = @{}\n",
"$r18PixivCount = 0\n",
"$totalPixivWithTags = 0\n",
"\n",
"foreach ($entry in $pixivTags.GetEnumerator()) {\n",
" $tags = $entry.Value\n",
" if (-not $tags -or $tags.Count -eq 0) { continue }\n",
"\n",
" $totalPixivWithTags += 1\n",
"\n",
" if ($tags.Contains(\"R-18\")) {\n",
" $r18PixivCount += 1\n",
" }\n",
"\n",
" foreach ($tag in $tags) {\n",
" if ($tag -ne \"R-18\") {\n",
" if (-not $tagCounter.ContainsKey($tag)) {\n",
" $tagCounter[$tag] = 0\n",
" }\n",
" $tagCounter[$tag] += 1\n",
" }\n",
" }\n",
"}\n",
"\n",
"$r18Ratio = if ($totalPixivWithTags -gt 0) { $r18PixivCount / $totalPixivWithTags } else { 0 }\n",
"Write-Host \"R-18: $r18PixivCount of $totalPixivWithTags\"\n",
"Write-Host (\"R-18 ratio: {0:P4}\" -f $r18Ratio)\n",
"\n",
"$tagCounter.GetEnumerator() |\n",
" Sort-Object Value -Descending |\n",
" Select-Object -First 20 |\n",
" ForEach-Object {\n",
" Write-Host (\"$($_.Key): $($_.Value)\")\n",
" }\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".NET (C#)",
"language": "C#",
"name": ".net-csharp"
},
"language_info": {
"name": "polyglot-notebook"
},
"polyglot_notebook": {
"kernelInfo": {
"defaultKernelName": "csharp",
"items": [
{
"aliases": [],
"name": "csharp"
}
]
}
}
},
"nbformat": 4,
"nbformat_minor": 5
}