Upload PonyXL.ps1
Browse files- PonyXL.ps1 +206 -0
PonyXL.ps1
ADDED
@@ -0,0 +1,206 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param (
|
2 |
+
[Parameter(Mandatory=$true)]
|
3 |
+
[string]$outputFilePath,
|
4 |
+
[string]$rentryUrl = "https://rentry.org/ponyxl_loras_n_stuff"
|
5 |
+
)
|
6 |
+
|
7 |
+
function Get-RemoteFileSize {
|
8 |
+
param (
|
9 |
+
[string]$url
|
10 |
+
)
|
11 |
+
|
12 |
+
try {
|
13 |
+
$ProgressPreference = 'SilentlyContinue'
|
14 |
+
$response = Invoke-WebRequest -Uri $url -Method Head
|
15 |
+
$ProgressPreference = 'Continue'
|
16 |
+
$fileSize = [int]$response.Headers['Content-Length']
|
17 |
+
return $fileSize;
|
18 |
+
} catch {
|
19 |
+
Write-Error "Failed to retrieve file size. $_"
|
20 |
+
}
|
21 |
+
}
|
22 |
+
|
23 |
+
function Create-Entry {
|
24 |
+
param (
|
25 |
+
[string]$name,
|
26 |
+
[string]$url,
|
27 |
+
[int]$size,
|
28 |
+
[string] $comment,
|
29 |
+
[int]$status
|
30 |
+
)
|
31 |
+
return [pscustomobject]@{Name=$name;Url=$url;Size=$size;Status=$status;Comment=$comment;Selected=0}
|
32 |
+
}
|
33 |
+
|
34 |
+
Clear-Host
|
35 |
+
|
36 |
+
#The path to the history file
|
37 |
+
$historyFile = Join-Path $outputFilePath "_history.txt"
|
38 |
+
|
39 |
+
# Initialize an empty dictionary for tracking the history
|
40 |
+
$historyDict = @{}
|
41 |
+
|
42 |
+
if (Test-Path $historyFile -PathType Leaf) {
|
43 |
+
# Read the file line by line and populate the dictionary
|
44 |
+
Get-Content -Path $historyFile | ForEach-Object {
|
45 |
+
# Split the line into key and value based on whitespace
|
46 |
+
$lineParts = $_ -split '\s+'
|
47 |
+
|
48 |
+
# Ensure there are at least two parts on the line
|
49 |
+
if ($lineParts.Length -ge 2) {
|
50 |
+
$key = $lineParts[0]
|
51 |
+
|
52 |
+
#$index = $_.IndexOf($lineParts[1])
|
53 |
+
#$comment = $_.Substring($index + $lineParts[1].Length).Trim()
|
54 |
+
#$value = @($lineParts[1], $comment)
|
55 |
+
|
56 |
+
# Add an entry to the dictionary
|
57 |
+
$historyDict[$key] = $lineParts[1]
|
58 |
+
}
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
Write-Host "Getting details about the Loras"
|
63 |
+
|
64 |
+
# Define a regular expression pattern to match URLs within <a> HTML elements ending with "safetensors"
|
65 |
+
$downloadLinkPattern = '<a [^>]*href=["'']?(https?://(?:www\.)?[^\s]+safetensors\b[^"''\s>]*)[^>]*>([^<]*)</a>([^<]*)'
|
66 |
+
|
67 |
+
# Download the content of the rentry.org page
|
68 |
+
$pageContent = Invoke-RestMethod -Uri $rentryUrl
|
69 |
+
|
70 |
+
# Find all matches using the regular expression pattern
|
71 |
+
$matches = $pageContent | Select-String -Pattern $downloadLinkPattern -AllMatches | ForEach-Object { $_.Matches }
|
72 |
+
|
73 |
+
# Initialize an empty list for tracking the available loras, each entry is a tuple with name, url, file size, integer indicating status (0 is new, 1 is updated), and integer indicating if user wants to download
|
74 |
+
$availableLoras = @()
|
75 |
+
|
76 |
+
# Process each match and extract download link, the first string inside <a> element, and the HTML content after </a>
|
77 |
+
foreach ($match in $matches) {
|
78 |
+
$url = $match.Groups[1].Value
|
79 |
+
$htmlAfterA = $match.Groups[3].Value
|
80 |
+
|
81 |
+
# Trim the string and split it into two variables
|
82 |
+
$trimmedString = $htmlAfterA.Trim()
|
83 |
+
$firstWord = $trimmedString.Split(' ', 2)[0]
|
84 |
+
$remainingText = $trimmedString.Split(' ', 2)[1]
|
85 |
+
|
86 |
+
$outputFileWithPath = Join-Path "$outputFilePath" "ponyxl_$firstWord.safetensors"
|
87 |
+
|
88 |
+
$comment = if($remainingText -ne $null) { $remainingText.Trim() } else { "" }
|
89 |
+
|
90 |
+
if($historyDict[$firstWord] -eq $null -or -Not (Test-Path $outputFileWithPath -PathType Leaf)) {
|
91 |
+
$fileSize = Get-RemoteFileSize -url $url
|
92 |
+
|
93 |
+
#We don't have the lora yet, add it to the list of options
|
94 |
+
$availableLoras += Create-Entry -name $firstWord -url $url -size $fileSize -comment $comment -status 0
|
95 |
+
} elseif(-Not ($historyDict[$firstWord] -eq $url)) {
|
96 |
+
#The Lora was updated
|
97 |
+
$fileSize = Get-RemoteFileSize -url $url
|
98 |
+
|
99 |
+
$availableLoras += Create-Entry -name $firstWord -url $url -size $fileSize -comment $comment -status 1
|
100 |
+
}
|
101 |
+
}
|
102 |
+
|
103 |
+
|
104 |
+
if($availableLoras.Count -eq 0) {
|
105 |
+
Write-Host "There are no available updates based on your history file."
|
106 |
+
Exit
|
107 |
+
}
|
108 |
+
|
109 |
+
Do {
|
110 |
+
Clear-Host
|
111 |
+
Write-Host "Below are the available LoRAs, asterisk indicates a LoRA is queued."
|
112 |
+
$index = 1
|
113 |
+
foreach ($availableLora in $availableLoras) {
|
114 |
+
$name = $availableLora.Name
|
115 |
+
$queued = if ($availableLora.Selected -eq 1) { "(*)" } else { "" }
|
116 |
+
$size = $availableLora.Size / 1048576
|
117 |
+
$status = if ($availableLora.Status -eq 0) { "New" } else { "Updated" }
|
118 |
+
|
119 |
+
$size = $size.ToString("F2")
|
120 |
+
|
121 |
+
Write-Host "[$index]) $queued $name - $status ($size MB)"
|
122 |
+
$index++;
|
123 |
+
}
|
124 |
+
|
125 |
+
Write-Host "Enter a number to toggle queued status, a to queue all, or c to continue to download the queued LoRAs."
|
126 |
+
$input = Read-Host "Command"
|
127 |
+
|
128 |
+
if($input -eq "a") {
|
129 |
+
foreach ($availableLora in $availableLoras) {
|
130 |
+
$availableLora.Selected = 1
|
131 |
+
}
|
132 |
+
} elseif($input -ne "c") {
|
133 |
+
$parsedInt = -1
|
134 |
+
$success = [int]::TryParse($input, [ref]$parsedInt)
|
135 |
+
if($success) {
|
136 |
+
$availableLoras[$parsedInt - 1].Selected = ($availableLoras[$parsedInt - 1].Selected + 1) % 2
|
137 |
+
}
|
138 |
+
}
|
139 |
+
} while($input -ne "c")
|
140 |
+
|
141 |
+
if (-not (Test-Path $outputFilePath -PathType Container)) {
|
142 |
+
# If the folder doesn't exist, create it
|
143 |
+
New-Item -Path $outputFilePath -ItemType Directory
|
144 |
+
}
|
145 |
+
|
146 |
+
#Download the selected LoRAs
|
147 |
+
$downloadedLoras = 0
|
148 |
+
foreach ($availableLora in $availableLoras) {
|
149 |
+
if($availableLora.Selected -eq 1) {
|
150 |
+
try {
|
151 |
+
$name = $availableLora.Name
|
152 |
+
$url = $availableLora.Url.Trim()
|
153 |
+
$comment = $availableLora.Comment
|
154 |
+
$outputFileWithPath = Join-Path $outputFilePath "ponyxl_$name.safetensors"
|
155 |
+
|
156 |
+
#if the file already exists, rename the old one before downloading the new one
|
157 |
+
if (Test-Path $outputFileWithPath) {
|
158 |
+
$counter = 1
|
159 |
+
$newName = "ponyxl_$($name)_old_$counter.safetensors"
|
160 |
+
$newPath = Join-Path $outputFilePath $newName
|
161 |
+
|
162 |
+
while (Test-Path $newPath) {
|
163 |
+
$newName = "ponyxl_$($name)_old_$counter.safetensors"
|
164 |
+
$newPath = Join-Path $outputFilePath $newName
|
165 |
+
$counter++
|
166 |
+
}
|
167 |
+
|
168 |
+
Rename-Item -LiteralPath $outputFileWithPath -NewName $newName
|
169 |
+
Write-Host "Renamed old $name LoRA to: $newName"
|
170 |
+
}
|
171 |
+
|
172 |
+
Write-Host "Downloading lora $name with url $url"
|
173 |
+
Invoke-WebRequest $url -OutFile $outputFileWithPath
|
174 |
+
|
175 |
+
++$downloadedLoras
|
176 |
+
$historyDict[$name] = $url
|
177 |
+
|
178 |
+
if ($comment -ne $null -and $comment -ne "") {
|
179 |
+
$commentFileWithPath = Join-Path "$outputFilePath" "ponyxl_$name.txt"
|
180 |
+
# Clear the existing content of the output text file
|
181 |
+
if (Test-Path $commentFileWithPath -PathType Leaf) {
|
182 |
+
Clear-Content -Path $commentFileWithPath
|
183 |
+
|
184 |
+
# Write the new string to the text file
|
185 |
+
Add-Content -Path $commentFileWithPath -Value $comment
|
186 |
+
}
|
187 |
+
}
|
188 |
+
} catch {
|
189 |
+
Write-Host "Error downloading lora $name, skipping, error was $_"
|
190 |
+
}
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
if (Test-Path $historyFile -PathType Leaf) {
|
195 |
+
# Clear the existing content of the history file
|
196 |
+
Clear-Content -Path $historyFile
|
197 |
+
}
|
198 |
+
|
199 |
+
#Write the new history
|
200 |
+
foreach ($entry in $historyDict.GetEnumerator()) {
|
201 |
+
$entryString = "{0} {1}" -f $entry.Key, $entry.Value
|
202 |
+
Add-Content -Path $historyFile -Value $entryString
|
203 |
+
}
|
204 |
+
|
205 |
+
Write-Host "Downloaded $downloadedLoras LoRAs."
|
206 |
+
Write-Host "Wrote the most recent urls for each model to _history.txt."
|