-
-
Save YoOoster/8ea3644bb24c531271188fa40c90879b to your computer and use it in GitHub Desktop.
use 5.012; | |
use strict; | |
use warnings; | |
use File::Temp qw(tempfile); | |
use IPC::System::Simple qw(capture system); | |
use LWP::UserAgent; | |
use URI::QueryParam; | |
use Win32::GUI; | |
use Data::Dumper; | |
use integer; | |
use constant false => 0; | |
use constant true => 1; | |
my $PicJigsaw = Win32::GUI::Bitmap->new("jigsaw.bmp"); | |
my $PicSudoku = Win32::GUI::Bitmap->new("sudoku.bmp"); | |
my @board; | |
my $solveCount = 0; | |
my $Window_Main; | |
my $Window_Jigsaw; | |
my $Window_Sudoku; | |
######################################################### | |
# Main Window # | |
######################################################### | |
sub Create_Window_Main { | |
my $W1 = Win32::GUI::Window->new( | |
-name => "WindowMain", | |
-title => "Depuzzlefy", | |
-size => [ 800, 475 ], | |
-pos => [ Win32::GUI::Width(Win32::GUI::GetDesktopWindow())/2-400, Win32::GUI::Height(Win32::GUI::GetDesktopWindow())/2-237.50 ], | |
-sizable => 0, | |
-hasmaximize => 0, | |
-maximizebox => 0, | |
-hasminimize => 0, | |
-minimizebox => 0, | |
); | |
$W1->AddButton( | |
-name => "ButtonMainJigsaw", | |
-text => "Jigsaw puzzles", | |
-align => "center", | |
-valign => "center", | |
-picture=> $PicJigsaw, | |
-pos => [ 25, 60 ], | |
-size => [ 350, 350], | |
); | |
$W1->AddButton( | |
-name => "ButtonMainSudoku", | |
-text => "Sudoku", | |
-align => "center", | |
-valign => "center", | |
-picture=> $PicSudoku, | |
-pos => [ 400, 60 ], | |
-size => [ 350, 350], | |
); | |
$W1->AddLabel( | |
-name => "LabelMainJigsaw", | |
-text => "Jigsaw Puzzles", | |
-pos => [175, 45], | |
-size => [350, 15], | |
); | |
$W1->AddLabel( | |
-name => "LabelMainSudoku", | |
-text => "Sudoku", | |
-pos => [550, 45], | |
-size => [350, 15], | |
); | |
return $W1; | |
} | |
sub WindowMain_Terminate { | |
return -1; | |
} | |
sub ButtonMainJigsaw_Click { | |
$Window_Main->Hide(); | |
$Window_Jigsaw->DoModal(); | |
} | |
sub ButtonMainSudoku_Click { | |
$Window_Main->Hide(); | |
$Window_Sudoku->DoModal(); | |
} | |
######################################################### | |
# Jigsaw Window # | |
######################################################### | |
sub Create_Window_Jigsaw { | |
my $W1 = Win32::GUI::Window->new( | |
-name => "WindowJigsaw", | |
-title => "Depuzzlefy - Jigsaw", | |
-size => [ 300, 150 ], | |
-pos => [ Win32::GUI::Width(Win32::GUI::GetDesktopWindow())/2-150, Win32::GUI::Height(Win32::GUI::GetDesktopWindow())/2-75 ], | |
-sizable=> 0, | |
-parent => $Window_Main, | |
-hasmaximize => 0, | |
-maximizebox => 0, | |
-hasminimize => 0, | |
-minimizebox => 0, | |
); | |
$W1->AddButton( | |
-name => "ButtonWJDepuzzlefy", | |
-text => "Depuzzlefy", | |
-pos => [ 20, 60 ], | |
-size => [ 250, 30], | |
); | |
$W1->AddLabel( | |
-name => "LabelWJUrl", | |
-text => "Insert URL", | |
-pos => [20, 20], | |
-size => [250, 20], | |
); | |
$W1->AddTextfield( | |
-name => "TextfieldWJUrl", | |
-pos => [20,40], | |
-size => [250, 20], | |
); | |
return $W1; | |
} | |
sub WindowJigsaw_Terminate { | |
$Window_Main->Show(); | |
return -1; | |
} | |
sub ButtonWJDepuzzlefy_Click { | |
my $url = $Window_Jigsaw->TextfieldWJUrl->Text(); | |
if ($url =~ m[flash-gear.com]gi) { | |
FlashGearRequest(); | |
} elsif ($url =~ m[jigidi.com]gi) { | |
JigidiRequest(); | |
} else { | |
$Window_Jigsaw->TextfieldWJUrl->SelectAll(); | |
$Window_Jigsaw->TextfieldWJUrl->Clear(); | |
print "Website isn't supported.'\n\n"; | |
return; | |
} | |
} | |
######################################################### | |
# Sudoku Window # | |
######################################################### | |
sub Create_Window_Sudoku { | |
my $W1 = Win32::GUI::Window->new( | |
-name => "WindowSudoku", | |
-title => "Depuzzlefy - Sudoku", | |
-size => [ 315, 370 ], | |
-pos => [ Win32::GUI::Width(Win32::GUI::GetDesktopWindow())/2-157.5, Win32::GUI::Height(Win32::GUI::GetDesktopWindow())/2-185 ], | |
-sizable => 0, | |
-parent => $Window_Main, | |
-hasmaximize => 0, | |
-maximizebox => 0, | |
-hasminimize => 0, | |
-minimizebox => 0, | |
); | |
for (my $i = 0; $i < 9; $i++) { | |
for (my $j = 0; $j <9; $j++) { | |
my $tf = $W1->AddTextfield( | |
-name => "TextFieldSudoku$i$j", | |
-pos => [($j*30)+20, ($i*30)+30], | |
-size => [25,25], | |
-align => "center", | |
-number => 1, | |
); | |
$tf->MaxLength(1); | |
} | |
} | |
$W1->AddButton( | |
-name => "ButtonSudokuSolve", | |
-text => "Solve", | |
-pos => [ 120, 295 ], | |
-size => [ 85, 30 ], | |
); | |
return $W1; | |
} | |
sub WindowSudoku_Terminate { | |
$Window_Main->Show(); | |
return -1; | |
} | |
sub ButtonSudokuSolve_Click { | |
undef @board; | |
$solveCount = 0; | |
for (my $i = 0; $i < 9; $i++) { | |
for (my $j = 0; $j < 9; $j++) { | |
my $method = "TextFieldSudoku$i$j"; | |
if (($Window_Sudoku->$method->Text() + 0) != "") { | |
push @board, (($Window_Sudoku->$method->Text()) + 0); | |
} else { | |
push @board, 0; | |
} | |
} | |
} | |
SolveSudoku(); | |
} | |
######################################################### | |
sub SolveSudoku { | |
printf "Trying to solve Sudoku. Count:%s\n", $solveCount++; | |
my $i; | |
foreach $i ( 0 .. 80 ) { | |
next if $board[$i]; | |
my %t = map { | |
$_ / 9 == $i / 9 || | |
$_ % 9 == $i % 9 || | |
$_ / 27 == $i / 27 && $_ % 9 / 3 == $i % 9 / 3 | |
? $board[$_] : 0, | |
1; | |
} 0 .. 80; | |
SolveSudoku( $board[$i] = $_ ) for grep !$t{$_}, 1 .. 9; | |
return $board[$i] = 0; | |
} | |
# $i = 0; | |
# foreach (@board) { | |
# print "-----+-----+-----\n" if !($i%27) && $i; | |
# print !($i%9) ? '': $i%3 ? ' ' : '|', $_; | |
# print "\n" unless ++$i%9; | |
# } | |
for (my $i = 0; $i < 9; $i++) { | |
for (my $j = 0; $j < 9; $j++) { | |
my $method = "TextFieldSudoku$i$j"; | |
my $value = $board[($i * 9) + $j]; | |
$Window_Sudoku->$method->SelectAll(); | |
$Window_Sudoku->$method->Clear(); | |
$Window_Sudoku->$method->Append("$value"); | |
} | |
} | |
} | |
sub ClearHideJigsaw { | |
$Window_Jigsaw->TextfieldWJUrl->SelectAll(); | |
$Window_Jigsaw->TextfieldWJUrl->Clear(); | |
$Window_Jigsaw->Hide(); | |
} | |
sub SetUserAgent { | |
my $ua = LWP::UserAgent->new(); | |
$ua->agent('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0'); | |
$ua->cookie_jar({}); | |
$ua->protocols_allowed(['http','https']); | |
$ua->ssl_opts(verify_hostname => 0); | |
$ua->default_header('Accept-Encoding' => scalar HTTP::Message::decodable()); | |
return $ua; | |
} | |
# TODO: Find a way to make use of the normal temp map. using c:/dpf but this map is getting deleted at the end. Might be troublesome if someone made a own map. | |
# Using c:/dpf because otherwise large puzzles were getting errors because of too long commandprompt commands. | |
# This may still happen on really large puzzles but I haven't encountered them yet. | |
sub FlashGearRequest { | |
my $url = $Window_Jigsaw->TextfieldWJUrl->Text(); | |
ClearHideJigsaw(); | |
print "Requesting URL data\n\n"; | |
my $ua = SetUserAgent(); | |
my $res = $ua->get($url); | |
if(!$res->is_success) { | |
printf "%s\n\n", $res->status_line; | |
$Window_Jigsaw->Show(); | |
return; | |
} | |
my $content = $res->decoded_content // $res->content // die 'no content'; | |
my @url = $content =~ m[<embed(?: [^>]*?)? src="([^"]+)"]gi; | |
if(!@url) { | |
print "No Flash file found. Please insert a correct URL\n\n"; | |
$Window_Jigsaw->Show(); | |
return; | |
} | |
print "Found Flash file\n\n"; | |
print "Extracting pictures from the Flash file\n"; | |
print "This may take a while depending on the size of the puzzle\n\n"; | |
my $dir = "C:\\dpf"; | |
my $img = ''; | |
$url = $url[1]; | |
my $uri = URI->new($url); | |
my ($h, $w, $id) = map $uri->query_param($_), qw(h w id); | |
next unless $h and $w and $id; | |
$uri->query_param(c => 'z'); | |
my $swf = File::Temp->new(suffix => '.swf'); | |
$res = $ua->get($uri, ':content_file' => $swf->filename); | |
my $out = capture swfextract => $swf; | |
my ($ids) = $out =~ /^\s*\[-j\] \d+ JPEGs: ID\(s\) (\d+,.*)/m; | |
my @ids = split(", ", $ids); | |
mkdir $dir, 0666; | |
foreach my $id (@ids) { | |
system swfextract => '-j', $id, '--outputformat', "$dir/%05d.%s", $swf; | |
} | |
# FIX: Other jpgs will crash it. | |
my @jpg = glob "$dir/*.jpg"; | |
$out = capture identify => $jpg[0]; | |
my ($x, $y) = $out =~ / JPEG (\d+)x(\d+)/; | |
next unless $x and $y and $x == $y; | |
$_ = int $_ / $x * 2 for $w, $h; | |
# The edges of each puzzle piece image need to be overlapped. | |
$_ = int $_ / 4 for $x, $y; | |
$img = "$id.jpg"; | |
system montage => '-tile', "${w}x$h", '-geometry', "-$x-$y", @jpg, $img; | |
unlink @jpg; | |
system "cmd /c start $img"; | |
print "Done\n\n"; | |
$Window_Jigsaw->Show(); | |
} | |
sub JigidiRequest { | |
my $url = $Window_Jigsaw->TextfieldWJUrl->Text(); | |
ClearHideJigsaw(); | |
my @id = $url =~ m[\?id=([^"]+)]; | |
print "Requesting URL data\n\n"; | |
my $ua = SetUserAgent(); | |
my $res = $ua->get($url); | |
if(!$res->is_success) { | |
printf "%s\n\n", $res->status_line; | |
$Window_Jigsaw->Show(); | |
return; | |
} | |
my $content = $res->decoded_content // $res->content // die 'no content\n'; | |
my @token = $content =~ m[token:\"([^"]+)]; | |
printf "%s\n\n", "Found token"; | |
$res = $ua->get("https://www.jigidi.com/ajax/api/2/game_lookup.php?token=$token[0]"); | |
if(!$res->is_success) { | |
printf "%s\n\n", $res->status_line; | |
$Window_Jigsaw->Show(); | |
return; | |
} | |
$content = $res->decoded_content // $res->content // die 'no content\n'; | |
my @pic = $content =~ m[image\":\"([^"]+)]; | |
$pic[0] =~ s/[\\]//g ; | |
$pic[0] =~ s/.{5}$//; | |
print "Saving picture\n\n"; | |
unlink "$id[0].jpg"; | |
$res = $ua->mirror($pic[0], "$id[0].jpg"); | |
unless($res->is_success) { | |
printf "%s\n\n", $res->status_line; | |
$Window_Jigsaw->Show(); | |
return; | |
} | |
system "cmd /c start $id[0].jpg"; | |
print "Done\n\n"; | |
$Window_Jigsaw->Show(); | |
} | |
$Window_Main = Create_Window_Main(); | |
$Window_Jigsaw = Create_Window_Jigsaw(); | |
$Window_Sudoku = Create_Window_Sudoku(); | |
$Window_Main->Show(); | |
Win32::GUI::Dialog(); |
Including the completion message would be very, very nice for me too!
Is there a possibility?
Updated the program. Link
- It now gets the high definition picture of jigidi puzzles.
- I'm still figuring out how to get the completion message
- I added a sudoku solver. Some sudoku might not be solvable by it.
I'll wait if there is a chance to get the completion message in jigidi too. Thank you!
I have the same problems as Rhoenbussard.
The puzzles always split in two files xxxx-0 and xxxx-1.
Followed by the error code that it can#T find the file withe the name xxxx.
Thanks for your help!
Kai
@kaischmitt
Which puzzle?
This:
http://four.flash-gear.com/npuz/puz.php?c=v&id=4103396&k=7328868
gives theese files:
I have the same problem with this URL: http://six.flash-gear.com/npuz/puz.php?c=v&id=3544876&k=77212470.
I've installed the latest version on the latest version of Windows10. Maybe that helps a little.
Super Tool! I am also interested in a completion message. Is there any posibility?
Super Tool! I am also interested in a completion message. Is there any posibility?
Ditto!
Apart from the completion message which many people have already asked for, I'd very much like a non-windows option.
This script only works on Windows
I edited this script to add a User Interface, so people don't need to keep changing the script manually.
Supported websites:
http://flash-gear.com/puzzle/
https://www.jigidi.com/
Write a comment here if you want to add a website.
Using installer:
I made a installer for this script
(Last updated December 10, 2017)
For this to work, you need to install the following:
That's all :)
FAQ:
Q: I get a "montage" unexpectedly returned exit value 1 error
A: You need to run the program as administator. You can do this by:
Q: I get a the system cannot find the file error
A: You need to run the program as administator. You can do this by:
Q: I get a "identify" failed to start error
A: You have installed a newer version ImageMagick which no longer has the identify tool.
Uninstall ImageMagick and use the link above
Manual way:
For this script to work, you need to install the following:
After you have installed all these things you need to add Swftools to your PATH.
You do this by opening your system settings. You can do it ONE of the following ways:
You then open Advanced system settings on the left.
Then you click on Enviroment Variables on the bottom of the screen.
You will see atleast 2 or more variables (depends which Windows version) on the top part of the screen.
The two important ones are TEMP and TMP.
Select TEMP
On the bottom of your screen select Path. Press Edit.
You either get one of the following screens depending on your Windows version:
A small screen with two textboxes:
Make sure you don't delete anything here. It will f*ck up your Windows
Add ;C:\Program Files (x86)\SWFTools; to the end of the value textbox.
A big screen with a list and multiple buttons at the right side:
Press the New button and fill in C:\Program Files (x86)\SWFTools
Press OK
Do the same thing with TMP