-
Notifications
You must be signed in to change notification settings - Fork 10
/
OFMetadataToStash.ps1
1551 lines (1359 loc) · 87.1 KB
/
OFMetadataToStash.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
param ([switch]$ignorehistory, [switch]$randomavatar, [switch]$v)
<#
---OnlyFans Metadata DB to Stash PoSH Script 0.9---
AUTHOR
JuiceBox
URL
https://github.com/ALonelyJuicebox/OFMetadataToStash
DESCRIPTION
Using the metadata database from an OnlyFans scraper script, imports metadata such as the URL, post associated text, and creation date into your stash DB
REQUIREMENTS
- The Powershell module "PSSQLite" must be installed https://github.com/RamblingCookieMonster/PSSQLite
Download a zip of the PSSQlite folder in that repo, extract it, run an Admin window of Powershell
in that directory then run 'install-module pssqlite' followed by the command 'import-module pssqlite'
#>
#Powershell Dependencies
#requires -modules PSGraphQL
#requires -modules PSSQLite
#requires -Version 7
#Import Modules now that we know we have them
Import-Module PSGraphQL
Import-Module PSSQLite
#Command Line Arguments
### Functions
#Set-Config is a wizard that walks the user through the configuration settings
function Set-Config{
clear-host
write-host "OnlyFans Metadata DB to Stash PoSH Script" -ForegroundColor Cyan
write-output "Configuration Setup Wizard"
write-output "--------------------------`n"
write-output "(1 of 3) Define the URL to your Stash"
write-output "Option 1: Stash is hosted on the computer I'm using right now (localhost:9999)"
write-output "Option 2: Stash is hosted at a different address and/or port (Ex. 192.168.1.2:6969)`n"
do{
do {
$userselection = read-host "Enter your selection (1 or 2)"
}
while (($userselection -notmatch "[1-2]"))
if ($userselection -eq 1){
$StashGQL_URL = "http://localhost:9999/graphql"
}
#Asking the user for the Stash URL, with some error handling
else {
while ($null -eq $StashGQL_URL ){
$StashGQL_URL = read-host "`nPlease enter the URL to your Stash"
$StashGQL_URL = $StashGQL_URL + '/graphql' #Tacking on the gql endpoint
while (!($StashGQL_URL.contains(":"))){
write-host "Error: Oops, looks like you forgot to enter the port number (Ex. <URL>:9999)." -ForegroundColor red
$StashGQL_URL = read-host "`nPlease enter the URL to your Stash"
}
if (!($StashGQL_URL.contains("http"))){
$StashGQL_URL = "http://"+$StashGQL_URL
}
}
}
do{
write-host "`nDo you happen to have a username/password configured on your Stash?"
$userselection = read-host "Enter your selection (Y/N)"
}
while(($userselection -notlike "Y" -and $userselection -notlike "N"))
if($userselection -like "Y"){
write-host "As you have set a username/password on your Stash, You'll need to provide this script with your API key."
write-host "Navigate to this page in your browser to generate one in Stash"
write-host "$StashGQL_URL/settings?tab=security"
write-host "`n- WARNING: The API key will be stored in cleartext in the config file of this script. - "
write-host "If someone who has access to your Stash gets access to the config file, they may be able to use it to bypass the username and password you've set."
$StashAPIKey = read-host "`nWhat is your API key?"
}
#Now we can check to ensure this address is valid-- we'll use a very simple GQL query and get the Stash version
$StashGQL_Query = 'query version{version{version}}'
try{
$stashversion = Invoke-GraphQLQuery -Query $StashGQL_Query -Uri $StashGQL_URL -Headers $(if ($StashAPIKey){ @{ApiKey = "$StashAPIKey" }})
}
catch{
write-host "(0) Error: Could not communicate to Stash at the provided address ($StashGQL_URL)"
read-host "No worries, press [Enter] to start from the top"
}
}
while ($null -eq $stashversion)
clear-host
write-host "OnlyFans Metadata DB to Stash PoSH Script" -ForegroundColor Cyan
write-output "Configuration Setup Wizard"
write-output "--------------------------`n"
write-output "(2 of 3) Define the path to your OnlyFans content`n"
write-host " * OnlyFans metadata database files are named 'user_data.db' and they are commonly `n located under <performername> $directorydelimiter metadata $directorydelimiter , as defined by your OnlyFans scraper of choice"
write-output "`n * You have the option of linking directly to the 'user_data.db' file, `n or you can link to the top level OnlyFans folder of several metadata databases."
write-output "`n * When multiple database are detected, this script can help you select one (or even import them all in batch!)`n"
if ($null -ne $PathToOnlyFansContent){
#If the user is coming to this function with this variable set, we set it to null so that there is better user feedback if a bad filepath is provided by the user.
$PathToOnlyFansContent = $null
}
do{
#Providing some user feedback if we tested the path and it came back as invalid
if($null -ne $PathToOnlyFansContent){
write-output "Oops. Invalid filepath"
}
if($IsWindows){
write-output "Option 1: I want to point to a folder containing all my OnlyFans content/OnlyFans metadata databases"
write-output "Option 2: I want to point to a single OnlyFans Metadata file (user_data.db)`n"
do {
$userselection = read-host "Enter your selection (1 or 2)"
}
while (($userselection -notmatch "[1-2]"))
#If the user wants to choose a folder instead of a file there's a different Windows File Explorer prompt to bring up so we'll use this condition tree to sort that out
if ($userselection -eq 1){
Add-Type -AssemblyName System.Windows.Forms
$FileBrowser = New-Object System.Windows.Forms.FolderBrowserDialog
$null = $FileBrowser.ShowDialog()
$PathToOnlyFansContent = $FileBrowser.SelectedPath
}
else {
Add-Type -AssemblyName System.Windows.Forms
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{
Filter = 'OnlyFans Metadata Database File (*.db)|*.db'
}
$null = $FileBrowser.ShowDialog()
$PathToOnlyFansContent = $FileBrowser.filename
}
}
else{
$PathToOnlyFansContent = read-host "Enter the folder containing your OnlyFans content or a direct link to your OnlyFans Metadata Database"
}
}
while(!(test-path $PathToOnlyFansContent))
clear-host
write-host "OnlyFans Metadata DB to Stash PoSH Script" -ForegroundColor Cyan
write-output "Configuration Setup Wizard"
write-output "--------------------------`n"
write-output "(3 of 3) Define your Metadata Match Mode"
write-output " * When importing OnlyFans Metadata, some users may want to tailor how this script matches metadata to files"
write-output " * If you are an average user, just set this to 'Normal'"
write-output "`nOption 1: Normal - Will match based on Filesize and the Performer name being somewhere in the file path (Recommended)"
write-output "Option 2: Low - Will match based only on a matching Filesize"
write-output "Option 3: High - Will match based on Filename and a matching Filesize"
$specificityselection = 0;
do {
$specificityselection = read-host "`nEnter selection (1-3)"
}
while (($specificityselection -notmatch "[1-3]"))
#Code for parsing metadata files
if($specificityselection -eq 1){
$SearchSpecificity = "Normal"
}
elseif($specificityselection -eq 2){
$SearchSpecificity = "Low"
}
else{
$SearchSpecificity = "High"
}
clear-host
write-host "OnlyFans Metadata DB to Stash PoSH Script" -ForegroundColor Cyan
write-output "Configuration Setup Wizard"
write-output "--------------------------`n"
write-output "(Summary) Review your settings`n"
write-output "URL to Stash API:`n - $StashGQL_URL`n"
write-output "Path to OnlyFans Content:`n - $PathToOnlyFansContent`n"
write-output "Metadata Match Mode:`n - $SearchSpecificity`n"
read-host "Press [Enter] to save this configuration and return to the Main Menu"
#Now to make our configuration file
try {
Out-File $PathToConfigFile
}
catch{
write-output "Error - Something went wrong while trying to save the config file to the filesystem ($PathToConfigFile)" -ForegroundColor red
read-output "Press [Enter] to exit" -ForegroundColor red
exit
}
try{
Add-Content -path $PathToConfigFile -value "#### OFMetadataToStash Config File v1 ####"
Add-Content -path $PathToConfigFile -value "------------------------------------------"
Add-Content -path $PathToConfigFile -value "## URL to the Stash GraphQL API endpoint ##"
Add-Content -path $PathToConfigFile -value $StashGQL_URL
Add-Content -path $PathToConfigFile -value "## Direct Path to OnlyFans Metadata Database or top level folder containing OnlyFans content ##"
Add-Content -path $PathToConfigFile -value $PathToOnlyFansContent
Add-Content -path $PathToConfigFile -value "## Search Specificity mode. (Normal | High | Low) ##"
Add-Content -path $PathToConfigFile -value $SearchSpecificity
Add-Content -path $PathToConfigFile -value "## Stash API Key (Danger!)##"
Add-Content -path $PathToConfigFile -value $StashAPIKey
}
catch {
write-output "Error - Something went wrong while trying add your configurations to the config file ($PathToConfigFile)" -ForegroundColor red
read-output "Press [Enter] to exit" -ForegroundColor red
exit
}
} #End Set-Config
#DatabaseHasBeenImported does a check to see if a particular metadata database file actually needs to be parsed based on a history file. Returns true if this database needs to be parsed
function DatabaseHasAlreadyBeenImported{
if ($ignorehistory -eq $true){
return $false
}
else{
#Location for the history file to be stored
$PathToHistoryFile = "."+$directorydelimiter+"Utilities"+$directorydelimiter+"imported_dbs.sqlite"
#Let's go ahead and create the history file if it does not exist
if(!(test-path $pathtohistoryfile)){
try{
new-item $PathToHistoryFile
}
catch{
write-host "Error 1h - Unable to write the history file to the filesystem. Permissions issue?" -ForegroundColor red
read-host "Press [Enter] to exit"
exit
}
#Query for defining the schema of the SQL database we're creating
$historyquery = 'CREATE TABLE "history" ("historyID" INTEGER NOT NULL UNIQUE,"performer" TEXT NOT NULL UNIQUE COLLATE BINARY,"import_date" TEXT NOT NULL,PRIMARY KEY("historyID" AUTOINCREMENT));'
try{
Invoke-SqliteQuery -Query $historyQuery -DataSource $PathToHistoryFile
}
catch{
write-host "Error 2h - Unable to create a history file using SQL." -ForegroundColor red
read-host "Press [Enter] to exit"
exit
}
}
#First let's check to see if this performer is even in the history file
try{
$historyQuery = 'SELECT * FROM history WHERE history.performer = "'+$performername+'"'
$performerFromHistory = Invoke-SqliteQuery -Query $historyQuery -DataSource $PathToHistoryFile
}
catch{
write-host "Error 3h - Something went wrong while trying to read from history file ($PathToHistoryFile)" -ForegroundColor red
read-host "Press [Enter] to exit"
exit
}
#If this performer DOES exist in the history file...
if ($performerFromHistory){
#Let's get the timestamp from the metdata database file
$metadataLastWriteTime = get-item $currentdatabase
$metadataLastWriteTime = $metadataLastWriteTime.LastWriteTime
#If the metdata database for this performer has been modified since the last time we read this metadata database in, let's go ahead and parse it
if([datetime]$metadataLastWriteTime -gt [datetime]$performerFromHistory.import_date){
$currenttimestamp = get-date -format o
try {
$historyQuery = 'UPDATE import_date SET import_date = "'+$currenttimestamp+'" WHERE history.performer = "'+$performername+'"'
Invoke-SqliteQuery -Query $historyQuery -DataSource $PathToHistoryFile
}
catch{
write-host "Error 4h - Something went wrong while trying to update the history file ($PathToHistoryFile)" -ForegroundColor red
read-output "Press [Enter] to exit"
exit
}
return $false
}
else{
write-host "- The metadata database for $performername hasn't changed since your last import! Skipping..."
return $true
}
}
#Otherwise, this performer is entirely new to us, so let's add the performer to the history file
else{
$currenttimestamp = get-date -format o
try {
$historyQuery = 'INSERT INTO history(performer, import_date) VALUES ("'+$performername+'", "'+$currenttimestamp+'")'
Invoke-SqliteQuery -Query $historyQuery -DataSource $PathToHistoryFile
}
catch{
write-host "Error 5h - Something went wrong while trying to add this performer to the history file ($PathToHistoryFile)" -ForegroundColor red
read-output "Press [Enter] to exit"
exit
}
return $false
}
}
} #End DatabaseHasBeenImported
#Add-MetadataUsingOFDB adds metadata to Stash using metadata databases.
function Add-MetadataUsingOFDB{
#Playing it safe and asking the user to back up their database first
$backupConfirmation = Read-Host "`nBefore we begin, would you like to make a backup of your Stash Database? [Y/N] (Default is 'No')"
if (($backupConfirmation -like "Y*")) {
$StashGQL_Query = 'mutation BackupDatabase($input: BackupDatabaseInput!) {
backupDatabase(input: $input)
}'
$StashGQL_QueryVariables = '{
"input": {}
}'
try{
Invoke-GraphQLQuery -Query $StashGQL_Query -Uri $StashGQL_URL -Variables $StashGQL_QueryVariables -Headers $(if ($StashAPIKey){ @{ApiKey = "$StashAPIKey" }}) | out-null
}
catch{
write-host "(10) Error: There was an issue with the GraphQL query/mutation." -ForegroundColor red
write-host "Additional Error Info: `n`n$StashGQL_Query `n$StashGQL_QueryVariables"
read-host "Press [Enter] to exit"
exit
}
write-output "...Done! A backup was successfully created."
}
else{
write-output "OK, a backup will NOT be created."
}
write-output "`nScanning for existing OnlyFans Metadata Database files..."
#Finding all of our metadata databases.
$OFDatabaseFilesCollection = Get-ChildItem -Path $PathToOnlyFansContent -Recurse | where-object {$_.name -in "user_data.db","posts.db"}
#For the discovery of a single database file
if ($OFDatabaseFilesCollection.count -eq 1){
#More modern OF DB schemas include the name of the performer in the profile table. If this table does not exist we will have to derive the performer name from the filepath, assuming the db is in a /metadata/ folder.
$Query = "PRAGMA table_info(medias)"
$OFDBColumnsToCheck = Invoke-SqliteQuery -Query $Query -DataSource $OFDatabaseFilesCollection[0].FullName
#There's probably a faster way to do this, but I'm throwing the collection into a string, with each column result (aka table name) seperated by a space.
$OFDBColumnsToCheck = [string]::Join(' ',$OFDBColumnsToCheck.name)
$performername = $null
if ($OFDBColumnsToCheck -match "profiles"){
$Query = "SELECT username FROM profiles LIMIT 1" #I'm throwing that limit on as a precaution-- I'm not sure if multiple usernames will ever be stored in that SQL table
$performername = Invoke-SqliteQuery -Query $Query -DataSource $OFDatabaseFilesCollection[0].FullName
}
#Either the query resulted in null or the profiles table didnt exist, so either way let's use the alternative directory based method.
if ($null -eq $performername){
$performername = $OFDatabaseFilesCollection.FullName | split-path | split-path -leaf
if ($performername -eq "metadata"){
$performername = $OFDatabaseFilesCollection.FullName | split-path | split-path | split-path -leaf
}
}
write-output "Discovered a metadata database for '$performername' "
}
#For the discovery of multiple database files
elseif ($OFDatabaseFilesCollection.count -gt 1){
$totalNumMetadataDatabases = $OFDatabaseFilesCollection.count
write-host "...Discovered $totalnummetadatadatabases metadata databases."
write-host "`nHow would you like to import metadata for these performers?"
write-host "1 - Import metadata for all discovered performers"
write-host "2 - Import metadata for a specific performer"
write-host "3 - Import metadata for a range of performers"
$selectednumberforprocess = read-host "Make your selection [Enter a number]"
while([int]$selectednumberforprocess -notmatch "[1-3]" ){
write-host "Invalid input"
$selectednumberforprocess = read-host "Make your selection [Enter a number]"
}
if ([int]$selectednumberforprocess -eq 1){
write-host "OK, all performers will be processed."
}
#Logic for handling the process for selecting a single performer
elseif([int]$selectednumberforprocess -eq 2){
write-host " " #Just adding a new line for a better UX
#logic for displaying all found performers for user to select
$i=1 # just used cosmetically
Foreach ($OFDBdatabase in $OFDatabaseFilesCollection){
#Getting the performer name from the profiles table (if it exists)
$Query = "PRAGMA table_info(medias)"
$OFDBColumnsToCheck = Invoke-SqliteQuery -Query $Query -DataSource $OFDBdatabase.FullName
#There's probably a faster way to do this, but I'm throwing the collection into a string, with each column result (aka table name) seperated by a space.
$OFDBColumnsToCheck = [string]::Join(' ',$OFDBColumnsToCheck.name)
$performername = $null
if ($OFDBColumnsToCheck -match "profiles"){
$Query = "SELECT username FROM profiles LIMIT 1" #I'm throwing that limit on as a precaution-- I'm not sure if multiple usernames will ever be stored in that SQL table
$performername = Invoke-SqliteQuery -Query $Query -DataSource $OFDatabaseFilesCollection[0].FullName
}
#Either the query resulted in null or the profiles table didnt exist, so either way let's use the alternative directory based method.
if ($null -eq $performername){
$performername = $OFDBdatabase.FullName | split-path | split-path -leaf
if ($performername -eq "metadata"){
$performername = $OFDBdatabase.FullName | split-path | split-path | split-path -leaf
}
}
write-output "$i - $performername"
$i++
}
$selectednumber = read-host "`n# Which performer would you like to select? [Enter a number]"
#Checking for bad input
while ($selectednumber -notmatch "^[\d\.]+$" -or ([int]$selectednumber -gt $totalNumMetadataDatabases)){
$selectednumber = read-host "Invalid Input. Please select a number between 0 and" $totalNumMetadataDatabases".`nWhich performer would you like to select? [Enter a number]"
}
$selectednumber = $selectednumber-1 #Since we are dealing with a 0 based array, i'm realigning the user selection
$performername = $OFDatabaseFilesCollection[$selectednumber].FullName | split-path | split-path -leaf
if ($performername -eq "metadata"){
$performername = $OFDatabaseFilesCollection[$selectednumber].FullName | split-path | split-path | split-path -leaf #Basically if we hit the metadata folder, go a folder higher and call it the performer
}
#Specifically selecting the performer the user wants to parse.
$OFDatabaseFilesCollection = $OFDatabaseFilesCollection[$selectednumber]
write-output "OK, the performer '$performername' will be processed."
}
#Logic for handling the range process
else{
#Logic for displaying all found performers
$i=1 # just used cosmetically
write-host "`nHere are all the performers that you can import metadata for:"
Foreach ($OFDBdatabase in $OFDatabaseFilesCollection){
#Getting the performer name from the profiles table (if it exists)
$Query = "PRAGMA table_info(medias)"
$OFDBColumnsToCheck = Invoke-SqliteQuery -Query $Query -DataSource $OFDBdatabase.FullName
#There's probably a faster way to do this, but I'm throwing the collection into a string, with each column result (aka table name) seperated by a space.
$OFDBColumnsToCheck = [string]::Join(' ',$OFDBColumnsToCheck.name)
$performername = $null
if ($OFDBColumnsToCheck -match "profiles"){
$Query = "SELECT username FROM profiles LIMIT 1" #I'm throwing that limit on as a precaution-- I'm not sure if multiple usernames will ever be stored in that SQL table
$performername = Invoke-SqliteQuery -Query $Query -DataSource $OFDatabaseFilesCollection[0].FullName
}
#Either the query resulted in null or the profiles table didnt exist, so either way let's use the alternative directory based method.
if ($null -eq $performername){
$performername = $OFDBdatabase.FullName | split-path | split-path -leaf
if ($performername -eq "metadata"){
$performername = $OFDBdatabase.FullName | split-path | split-path | split-path -leaf
}
}
write-output "$i - $performername"
$i++
}
#Some input handling/error handling for the user defined start of the range
$StartOfRange = read-host "Which performer is the first in the range? [Enter a number]"
$rangeInputCheck = $false
while($rangeInputCheck -eq $false){
if($StartOfRange -notmatch "^[\d\.]+$"){
write-host "`nInvalid Input: You have to enter a number"
$StartOfRange = read-host "Which performer is at the start of the range? [Enter a number]"
}
elseif($StartOfRange -le 0){
write-host "`nInvalid Input: You can't enter a number less than 1"
$StartOfRange = read-host "Which performer is at the start of the range? [Enter a number]"
}
elseif($StartOfRange -ge $totalNumMetadataDatabases){
write-host "`nInvalid Input: You can't enter a number greater than or equal to $totalNumMetadataDatabases"
$StartOfRange = read-host "Which performer is at the start of the range? [Enter a number]"
}
else{
$rangeInputCheck = $true
}
}
#Some input handling/error handling for the user defined end of the range
$endOfRange = Read-Host "Which performer is at the end of the range? [Enter a number]"
$rangeInputCheck = $false
while($rangeInputCheck -eq $false){
if($EndOfRange -notmatch "^[\d\.]+$"){
write-host "`nInvalid Input: You have to enter a number"
$endOfRange = read-host "Which performer is at the end of the range? [Enter a number]"
}
elseif($EndOfRange -le 0){
write-host "`nInvalid Input: You can't enter a number less than 1"
$endOfRange = read-host "Which performer is at the end of the range? [Enter a number]"
}
elseif($endOfRange -gt $totalNumMetadataDatabases){
write-host "`nInvalid Input: You can't enter a number greater than $totalNumMetadataDatabases"
$endOfRange = read-host "Which performer is at the end of the range? [Enter a number]"
}
elseif($endOfRange -le $StartOfRange){
write-host "`nInvalid Input: Number has to be greater than $StartofRange"
$endOfRange = read-host "Which performer is at the end of the range? [Enter a number]"
}
else{
$rangeInputCheck = $true
}
}
write-host "OK, all the performers between $startofrange and $endofrange will be processed."
#We subtract 1 to account for us presenting the user with a 1 based start while PS arrays start at 0
$endofrange = $endOfRange - 1
$StartOfRange = $StartOfRange - 1
#Finally, let's define the new array of metadata databases based on the defined range
$OFDatabaseFilesCollection = $OFDatabaseFilesCollection[$startofrange..$endOfRange]
write-host $OFDatabaseFilesCollection
}
#Let's ask the user what type of media they want to parse
write-host "`nWhich types of media do you want to import metadata for?"
write-host "1 - Both Videos & Images`n2 - Only Videos`n3 - Only Images"
$mediaToProcessSelector = 0;
do {
$mediaToProcessSelector = read-host "Make your selection [1-3]"
}
while (($mediaToProcessSelector -notmatch "[1-3]"))
write-host "`nQuick Tips :" -ForegroundColor Cyan
write-host " * Be sure to run a Scan task in Stash of your OnlyFans content before running this script!`n * Be sure your various OnlyFans metadata database(s) are located either at`n <performername>"$directorydelimiter"user_data.db or at <performername>"$directorydelimiter"metadata"$directorydelimiter"user_data.db"
read-host "`nPress [Enter] to begin"
}
#We use these values after the script finishes parsing in order to provide the user with some nice stats
$numModified = 0
$numUnmodified = 0
$nummissingfiles = 0
$scriptStartTime = get-date
#Getting the OnlyFans Studio ID or creating it if it does not exist.
$StashGQL_Query = '
query FindStudios($filter: FindFilterType, $studio_filter: StudioFilterType) {
findStudios(filter: $filter, studio_filter: $studio_filter) {
count
studios {
id
name
}
}
}
'
$StashGQL_QueryVariables = '{
"filter": {
"q": ""
},
"studio_filter": {
"name": {
"value": "OnlyFans",
"modifier": "EQUALS"
}
}
}'
try{
$StashGQL_Result = Invoke-GraphQLQuery -Query $StashGQL_Query -Uri $StashGQL_URL -Variables $StashGQL_QueryVariables -Headers $(if ($StashAPIKey){ @{ApiKey = "$StashAPIKey" }})
}
catch{
write-host "(1) Error: There was an issue with the GraphQL query/mutation." -ForegroundColor red
write-host "Additional Error Info: `n`n$StashGQL_Query `n$StashGQL_QueryVariables"
read-host "Press [Enter] to exit"
exit
}
$OnlyFansStudioID = $StashGQL_Result.data.findStudios.Studios[0].id
#If Stash returns with an ID for 'OnlyFans', great. Otherwise, let's create a new studio
if ($null -eq $OnlyFansStudioID){
$StashGQL_Query = 'mutation StudioCreate($input: StudioCreateInput!) {
studioCreate(input: $input) {
name
url
}
}'
$StashGQL_QueryVariables = '{
"input": {
"name": "OnlyFans",
"url": "www.onlyfans.com/"
}
}'
try{
$StashGQL_Result = Invoke-GraphQLQuery -Query $StashGQL_Query -Uri $StashGQL_URL -Variables $StashGQL_QueryVariables -Headers $(if ($StashAPIKey){ @{ApiKey = "$StashAPIKey" }})
}
catch{
write-host "(9) Error: There was an issue with the GraphQL query/mutation." -ForegroundColor red
write-host "Additional Error Info: `n`n$StashGQL_Query `n$StashGQL_QueryVariables"
read-host "Press [Enter] to exit"
exit
}
$StashGQL_Query = '
query FindStudios($filter: FindFilterType, $studio_filter: StudioFilterType) {
findStudios(filter: $filter, studio_filter: $studio_filter) {
count
studios {
id
name
}
}
}
'
$StashGQL_QueryVariables = '{
"filter": {
"q": "OnlyFans"
}
}'
try{
$StashGQL_Result = Invoke-GraphQLQuery -Query $StashGQL_Query -Uri $StashGQL_URL -Variables $StashGQL_QueryVariables -Headers $(if ($StashAPIKey){ @{ApiKey = "$StashAPIKey" }})
}
catch{
write-host "(9a) Error: There was an issue with the GraphQL query/mutation." -ForegroundColor red
write-host "Additional Error Info: `n`n$StashGQL_Query `n$StashGQL_QueryVariables"
read-host "Press [Enter] to exit"
exit
}
$OnlyFansStudioID = $StashGQL_Result.data.findStudios.Studios[0].id
write-host "`nInfo: Added the OnlyFans studio to Stash's database" -ForegroundColor Cyan
}
$totalprogressCounter = 1 #Used for the progress UI
foreach ($currentdatabase in $OFDatabaseFilesCollection) {
#Let's help the user see how we are progressing through this metadata database (this is the parent progress UI, there's an additional child below as well)
$currentTotalProgress = [int]$(($totalprogressCounter/$OFDatabaseFilesCollection.count)*100)
Write-Progress -id 1 -Activity "Total Import Progress" -Status "$currentTotalProgress% Complete" -PercentComplete $currentTotalProgress
$totalprogressCounter++
#Gotta reparse the performer name as we may be parsing through a full collection of performers.
#Otherwise you'll end up with a whole bunch of performers having the same name
#This is also where we will make the determination if this onlyfans database has the right tables to be used here
#First step, let's check to ensure this OF db is valid for use
$Query = "PRAGMA table_info(medias)"
$OFDBColumnsToCheck = Invoke-SqliteQuery -Query $Query -DataSource $currentdatabase.FullName
#There's probably a faster way to do this, but I'm throwing the collection into a string, with each column result (aka table name) seperated by a space.
#Then we use a match condition and a whole lot of or statements to determine if this db has all the right columns this script needs.
$OFDBColumnsToCheck = [string]::Join(' ',$OFDBColumnsToCheck.name)
if (($OFDBColumnsToCheck -notmatch "media_id") -or ($OFDBColumnsToCheck -notmatch "post_id") -or ($OFDBColumnsToCheck -notmatch "directory") -or ($OFDBColumnsToCheck -notmatch "filename") -or ($OFDBColumnsToCheck -notmatch "size") -or ($OFDBColumnsToCheck -notmatch "media_type") -or ($OFDBColumnsToCheck -notmatch "created_at")){
$SchemaIsValid = $false
}
else {
$SchemaIsValid = $true
}
#If the OF metadata db is no good, tell the user and skip the rest of this very massive conditional block (I need to refactor this)
if ((!$SchemaIsValid)){
write-host "Error: The following OnlyFans metadata database doesn't contain the metadata in a format that this script expects." -ForegroundColor Red
write-host "This can occur if you've scraped OnlyFans using an unsupported tool. " -ForegroundColor Red
write-output $currentdatabase.FullName
read-host "Press [Enter] to continue"
}
else{
#More modern OF DB schemas include the name of the performer in the profile table. If this table does not exist we will have to derive the performer name from the filepath, assuming the db is in a /metadata/ folder.
$performername = $null
if ($OFDBColumnsToCheck -match "profiles"){
$Query = "SELECT username FROM profiles LIMIT 1" #I'm throwing that limit on as a precaution-- I'm not sure if multiple usernames will ever be stored in that SQL table
$performername = Invoke-SqliteQuery -Query $Query -DataSource $currentdatabase.FullName
}
#Either the query resulted in null or the profiles table didnt exist, so either way let's use the alternative directory based method.
if ($null -eq $performername){
$performername = $currentdatabase.FullName | split-path | split-path -leaf
if ($performername -eq "metadata"){
$performername = $currentdatabase.FullName | split-path | split-path | split-path -leaf
}
}
#Let's see if we can find this performer in Stash
$StashGQL_Query = '
query FindPerformers($filter: FindFilterType, $performer_filter: PerformerFilterType) {
findPerformers(filter: $filter, performer_filter: $performer_filter) {
count
performers {
id
name
}
}
}
'
$StashGQL_QueryVariables = '{
"filter": {
"q": "'+$performername+'"
}
}'
try{
$StashGQL_Result = Invoke-GraphQLQuery -Query $StashGQL_Query -Uri $StashGQL_URL -Variables $StashGQL_QueryVariables -Headers $(if ($StashAPIKey){ @{ApiKey = "$StashAPIKey" }})
}
catch{
write-host "(2) Error: There was an issue with the GraphQL query/mutation." -ForegroundColor red
write-host "Additional Error Info: `n`n$StashGQL_Query `n$StashGQL_QueryVariables"
read-host "Press [Enter] to exit"
exit
}
$PerformerID = $StashGQL_Result.data.findPerformers.performers[0].id
#If we had no luck finding the performer, lets create one, then get the ID
if($null -eq $performerID){
$StashGQL_Query = 'mutation PerformerCreate($input: PerformerCreateInput!) {
performerCreate(input: $input) {
name
url
}
}'
$StashGQL_QueryVariables = '{
"input": {
"name": "'+$performername+'",
"url": "www.onlyfans.com/'+$performername+'"
}
}'
try{
Invoke-GraphQLQuery -Query $StashGQL_Query -Uri $StashGQL_URL -Variables $StashGQL_QueryVariables -Headers $(if ($StashAPIKey){ @{ApiKey = "$StashAPIKey" }}) | out-null
}
catch{
write-host "(3) Error: There was an issue with the GraphQL query/mutation." -ForegroundColor red
write-host "Additional Error Info: `n`n$StashGQL_Query `n$StashGQL_QueryVariables"
read-host "Press [Enter] to exit"
exit
}
$StashGQL_Query = '
query FindPerformers($filter: FindFilterType, $performer_filter: PerformerFilterType) {
findPerformers(filter: $filter, performer_filter: $performer_filter) {
count
performers {
id
name
}
}
}
'
$StashGQL_QueryVariables = '{
"filter": {
"q": "'+$performername+'"
}
}'
try{
$StashGQL_Result = Invoke-GraphQLQuery -Query $StashGQL_Query -Uri $StashGQL_URL -Variables $StashGQL_QueryVariables -Headers $(if ($StashAPIKey){ @{ApiKey = "$StashAPIKey" }})
}
catch{
write-host "(22) Error: There was an issue with the GraphQL query/mutation." -ForegroundColor red
write-host "Additional Error Info: `n`n$StashGQL_Query `n$StashGQL_QueryVariables"
read-host "Press [Enter] to exit"
exit
}
$PerformerID = $StashGQL_Result.data.findPerformers.performers[0].id
$creatednewperformer = $true #We'll use this later after images have been added in order to give the performer a profile picture
$boolGetPerformerImage = $true #We'll use this to get an image to use for the profile picture
}
else{
$creatednewperformer = $false
$boolGetPerformerImage = $false
}
#Let's check to see if we need to import this performer based on the history file using the DatabaseHasBeenImported function
#The ignorehistory variable is a command line flag that the user may set if they want to have the script ignore the use of the history file
if (!(DatabaseHasAlreadyBeenImported)){
#Select all the media (except audio) and the text the performer associated to them, if available from the OFDB
$Query = "SELECT messages.text, medias.directory, medias.filename, medias.size, medias.created_at, medias.post_id, medias.media_type FROM medias INNER JOIN messages ON messages.post_id=medias.post_id UNION SELECT posts.text, medias.directory, medias.filename, medias.size, medias.created_at, medias.post_id, medias.media_type FROM medias INNER JOIN posts ON posts.post_id=medias.post_id WHERE medias.media_type <> 'Audios'"
$OF_DBpath = $currentdatabase.fullname
$OFDBQueryResult = Invoke-SqliteQuery -Query $Query -DataSource $OF_DBpath
$progressCounter = 1 #Used for the progress UI
foreach ($OFDBMedia in $OFDBQueryResult){
#Let's help the user see how we are progressing through this performer's metadata database
$currentProgress = [int]$(($progressCounter/$OFDBQueryResult.count)*100)
Write-Progress -parentId 1 -Activity "$performername Import Progress" -Status "$currentProgress% Complete" -PercentComplete $currentProgress
$progressCounter++
#Generating the URL for this post
$linktoOFpost = "https://www.onlyfans.com/"+$OFDBMedia.post_ID+"/"+$performername
#Reformatting the date to something stash appropriate
$creationdatefromOF = $OFDBMedia.created_at
$creationdatefromOF = Get-Date $creationdatefromOF -format "yyyy-MM-dd"
$OFDBfilesize = $OFDBMedia.size #filesize (in bytes) of the media, from the OF DB
$OFDBfilename = $OFDBMedia.filename #This defines filename of the media, from the OF DB
$OFDBdirectory = $OFDBMedia.directory #This defines the file directory of the media, from the OF DB
$OFDBFullFilePath = $OFDBdirectory+$directorydelimiter+$OFDBfilename #defines the full file path, using the OS appropriate delimeter
#Storing separate variants of these variables with apostrophy and backslash sanitization so they don't ruin our SQL/GQL queries
$OFDBfilenameForQuery = $OFDBfilename.replace("'","''")
$OFDBdirectoryForQuery = $OFDBdirectory.replace("'","''")
$OFDBfilenameForQuery = $OFDBfilename.replace("\","\\")
$OFDBdirectoryForQuery = $OFDBdirectory.replace("\","\\")
#Note that the OF downloader quantifies gifs as videos for some reason
#Since Stash doesn't (and rightfully so), we need to account for this
if(($OFDBMedia.media_type -eq "videos") -and ($OFDBfilename -notlike "*.gif")){
$mediatype = "video"
}
#Condition for images. Again, we have to add an extra condition just in case the image is a gif due to the DG database
elseif(($OFDBMedia.media_type -eq "images") -or ($OFDBfilename -like "*.gif")){
$mediatype = "image"
}
#Depending on the user preference, we may not want to actually process the media we're currently looking at. Let's check before continuing.
if (($mediaToProcessSelector -eq 2) -and ($mediatype -eq "image")){
#There's a scenario where because the user has not pulled any images for this performer, there will be no performer image. In that scenario, lets pull exactly one image for this purpose
if ($boolGetPerformerImage){
$boolGetPerformerImage = $false #Let's make sure we don't pull any more photos
}
else{
continue #Skip to the next item in this foreach, user only wants to process videos
}
}
if (($mediaToProcessSelector -eq 3) -and ($mediatype -eq "video")){
continue #Skip to the next item in this foreach, user only wants to process images
}
#Depending on user preference, we want to be more/less specific with our SQL queries to the Stash DB here, as determined by this condition tree (defined in order of percieved popularity)
#Normal specificity, search for videos based on having the performer name somewhere in the path and a matching filesize
if ($mediatype -eq "video" -and $searchspecificity -match "normal"){
$StashGQL_Query = 'mutation {
querySQL(sql: "SELECT folders.path, files.basename, files.size, files.id AS files_id, folders.id AS folders_id, scenes.id AS scenes_id, scenes.title AS scenes_title, scenes.details AS scenes_details FROM files JOIN folders ON files.parent_folder_id=folders.id JOIN scenes_files ON files.id = scenes_files.file_id JOIN scenes ON scenes.id = scenes_files.scene_id WHERE path LIKE ''%'+$performername+'%'' AND size = '''+$OFDBfilesize+'''") {
rows
}
}'
}
#Normal specificity, search for images based on having the performer name somewhere in the path and a matching filesize
elseif ($mediatype -eq "image" -and $searchspecificity -match "normal"){
$StashGQL_Query = 'mutation {
querySQL(sql: "SELECT folders.path, files.basename, files.size, files.id AS files_id, folders.id AS folders_id, images.id AS images_id, images.title AS images_title FROM files JOIN folders ON files.parent_folder_id=folders.id JOIN images_files ON files.id = images_files.file_id JOIN images ON images.id = images_files.image_id WHERE path LIKE ''%'+$performername+'%'' AND size = '''+$OFDBfilesize+'''") {
rows
}
}'
}
#Low specificity, search for videos based on filesize only
elseif ($mediatype -eq "video" -and $searchspecificity -match "low"){
$StashGQL_Query = 'mutation {
querySQL(sql: "SELECT folders.path, files.basename, files.size, files.id AS files_id, folders.id AS folders_id, scenes.id AS scenes_id, scenes.title AS scenes_title, scenes.details AS scenes_details FROM files JOIN folders ON files.parent_folder_id=folders.id JOIN scenes_files ON files.id = scenes_files.file_id JOIN scenes ON scenes.id = scenes_files.scene_id WHERE size = '''+$OFDBfilesize+'''") {
rows
}
}'
}
#Low specificity, search for images based on filesize only
elseif ($mediatype -eq "image" -and $searchspecificity -match "low"){
$StashGQL_Query = 'mutation {
querySQL(sql: "SELECT folders.path, files.basename, files.size, files.id AS files_id, folders.id AS folders_id, images.id AS images_id, images.title AS images_title FROM files JOIN folders ON files.parent_folder_id=folders.id JOIN images_files ON files.id = images_files.file_id JOIN images ON images.id = images_files.image_id WHERE size = '''+$OFDBfilesize+'''") {
rows
}
}'
}
#High specificity, search for videos based on matching file name between OnlyFans DB and Stash DB as well as matching the filesize.
elseif ($mediatype -eq "video" -and $searchspecificity -match "high"){
$StashGQL_Query = 'mutation {
querySQL(sql: "SELECT folders.path, files.basename, files.size, files.id AS files_id, folders.id AS folders_id, scenes.id AS scenes_id, scenes.title AS scenes_title, scenes.details AS scenes_details FROM files JOIN folders ON files.parent_folder_id=folders.id JOIN scenes_files ON files.id = scenes_files.file_id JOIN scenes ON scenes.id = scenes_files.scene_id WHERE files.basename ='''+$OFDBfilenameForQuery+''' AND size = '''+$OFDBfilesize+'''") {
rows
}
}'
}
#High specificity, search for images based on matching file name between OnlyFans DB and Stash DB as well as matching the filesize.
else{
$StashGQL_Query = 'mutation {
querySQL(sql: "SELECT folders.path, files.basename, files.size, files.id AS files_id, folders.id AS folders_id, images.id AS images_id, images.title AS images_title FROM files JOIN folders ON files.parent_folder_id=folders.id JOIN images_files ON files.id = images_files.file_id JOIN images ON images.id = images_files.image_id WHERE files.basename ='''+$OFDBfilenameForQuery+''' AND size = '''+$OFDBfilesize+'''") {
rows
}
}'
}
#Now lets try running the GQL query and see if we have a match in the Stash DB
try{
$StashGQL_Result = Invoke-GraphQLQuery -Query $StashGQL_Query -Uri $StashGQL_URL -Headers $(if ($StashAPIKey){ @{ApiKey = "$StashAPIKey" }})
}
catch{
write-host "(4) Error: There was an issue with the GraphQL query/mutation." -ForegroundColor red
write-host "Additional Error Info: `n`n$StashGQL_Query `n$StashGQL_QueryVariables"
read-host "Press [Enter] to exit"
exit
}
if ($StashGQL_Result.data.querySQL.rows.length -ne 0){
#Because of how GQL returns data, these values are just positions in the $StashGQLQuery array. Not super memorable, so I'm putting them in variables.
$CurrentFileID = $StashGQL_Result.data.querySQL.rows[0][5] #This represents either the scene ID or the image ID. To be generic, I'm defining it as "CurrentFileID"
$CurrentFileTitle = $StashGQL_Result.data.querySQL.rows[0][6]
}
#If our search for matching media in Stash itself comes up empty, let's check to see if the file even exists on the file system
if ($StashGQL_Result.data.querySQL.rows.length -eq 0 ){
#Let's be extra about this error message. If there's no match, swap the directory path delimeters and try again.
if (!(Test-Path $OFDBFullFilePath)){
if ($OFDBFullFilePath.Contains('/')){
$OFDBFullFilePath = $OFDBFullFilePath.Replace("/","\")
}
else{
$OFDBFullFilePath = $OFDBFullFilePath.Replace("\","/")
}
if (!(Test-Path $OFDBFullFilePath)){
write-host "`nInfo: There's a file in this OnlyFans metadata database that we couldn't find in your Stash database.`nThis file also doesn't appear to be on your filesystem (we checked with both Windows and *nix path delimeters).`nTry rerunning the script you used to scrape this OnlyFans performer and redownloading the file." -ForegroundColor Cyan
write-host "- Scan Specificity Mode: $SearchSpecificity"
write-host "- Filename: $OFDBfilename"
write-host "- Directory: $OFDBdirectory"
write-host "- Filesize: $OFDBfilesize"
write-host "^ (Filename, Directory and Filesize are as defined by the OF Metadata Database) ^"
Add-Content -Path $PathToMissingFilesLog -value " $OFDBFullFilePath"
$nummissingfiles++
}
else{
write-host "`nInfo: There's a file in this OnlyFans metadata database that we couldn't find in your Stash database but the file IS on your filesystem.`nTry running a Scan Task in Stash then re-running this script." -ForegroundColor Cyan
write-host "- Filename: $OFDBfilename"
write-host "- Directory: $OFDBdirectory"
write-host "- Filesize: $OFDBfilesize"
write-host "^ (Filename, Directory and Filesize are as defined by the OF Metadata Database) ^"
Add-Content -Path $PathToMissingFilesLog -value " $OFDBFullFilePath"
$nummissingfiles++
}
}
}
#Otherwise we have found a match! let's process the matching result and add the metadata we've found
else{
#Before processing, and for the sake of accuracy, if there are multiple filesize matches (specifically for the normal specificity mode), add a filename check to the query to see if we can match more specifically. If not, just use whatever matched that initial query.
if (($StashGQL_Result.data.querySQL.rows.length -gt 1) -and ($searchspecificity -match "normal") ){
#Search for videos based on having the performer name somewhere in the path and a matching filesize (and filename in this instance)
if ($mediatype -eq "video"){
$StashGQL_Query = 'mutation {
querySQL(sql: "SELECT folders.path, files.basename, files.size, files.id AS files_id, folders.id AS folders_id, scenes.id AS scenes_id, scenes.title AS scenes_title, scenes.details AS scenes_details FROM files JOIN folders ON files.parent_folder_id=folders.id JOIN scenes_files ON files.id = scenes_files.file_id JOIN scenes ON scenes.id = scenes_files.scene_id path LIKE ''%'+$performername+'%'' AND files.basename ='''+$OFDBfilenameForQuery+''' AND size = '''+$OFDBfilesize+'''") {
rows
}
}'
}
#Search for images based on having the performer name somewhere in the path and a matching filesize (and filename in this instance)
elseif ($mediatype -eq "image" ){
$StashGQL_Query = 'mutation {
querySQL(sql: "SELECT folders.path, files.basename, files.size, files.id AS files_id, folders.id AS folders_id, images.id AS images_id, images.title AS images_title FROM files JOIN folders ON files.parent_folder_id=folders.id JOIN images_files ON files.id = images_files.file_id JOIN images ON images.id = images_files.image_id WHERE path LIKE ''%'+$performername+'%'' AND files.basename ='''+$OFDBfilenameForQuery+''' AND size = '''+$OFDBfilesize+'''") {
rows
}
}'
}
#Now lets try running the GQL query and try to find the file in the Stash DB
try{
$AlternativeStashGQL_Result = Invoke-GraphQLQuery -Query $StashGQL_Query -Uri $StashGQL_URL -Headers $(if ($StashAPIKey){ @{ApiKey = "$StashAPIKey" }})
}
catch{
write-host "(5) Error: There was an issue with the GraphQL query/mutation." -ForegroundColor red
write-host "Additional Error Info: `n`n$StashGQL_Query `n$StashGQL_QueryVariables"
read-host "Press [Enter] to exit"
exit
}
#If we have a match, substitute it in and lets get that metadata into the Stash DB
if($StashGQL_Result_2.data.querySQL.rows -eq 1){
$StashGQL_Result = $AlternativeStashGQL_Result
$CurrentFileID = $StashGQL_Result.data.querySQL.rows[0][5] #This represents either the scene ID or the image ID
$CurrentFileTitle = $StashGQL_Result.data.querySQL.rows[0][6]
}
}
#Creating the title we want for the media, and defining Stash details for this media.
$proposedtitle = "$performername - $creationdatefromOF"
$detailsToAddToStash = $OFDBMedia.text
#Performers love to put links in their posts sometimes. Let's scrub those out in addition to any common HTML bits
$detailsToAddToStash = $detailsToAddToStash.Replace("<br />","")
$detailsToAddToStash = $detailsToAddToStash.Replace("<a href=","")
$detailsToAddToStash = $detailsToAddToStash.Replace("<a href =","")
$detailsToAddToStash = $detailsToAddToStash.Replace('"/',"")
$detailsToAddToStash = $detailsToAddToStash.Replace('">',"")
$detailsToAddToStash = $detailsToAddToStash.Replace("</a>"," ")
$detailsToAddToStash = $detailsToAddToStash.Replace('target="_blank"',"")
#For some reason the invoke-graphqlquery module doesn't quite escape single/double quotes ' " (or their curly variants) or backslashs \ very well so let's do it manually for the sake of our JSON query
$detailsToAddToStash = $detailsToAddToStash.replace("\","\\")