This commit is contained in:
2022-10-23 01:39:27 +02:00
parent 8c17aab483
commit 1929b84685
4130 changed files with 479334 additions and 0 deletions

Binary file not shown.

37
selenium/autogui.py Executable file
View File

@@ -0,0 +1,37 @@
#! python3
import pyautogui
#import pygetwindow as gw
import sys
# print('Press Ctrl-C to quit.')
# try:
# while True:
# x, y = pyautogui.position()
# positionStr = 'X: ' + str(x).rjust(4) + ' Y: ' + str(y).rjust(4)
# print(positionStr)
# except KeyboardInterrupt:
# print('\nDone.')
file = sys.argv[1]
print('File received as arg: ', file)
#fw = pyautogui.getActiveWindow()
#print('Active window: ', fw)
#print('Maximized: ', fw.isMaximized)
#print('Minimized: ', fw.isMinimized)
#print('isActive: ', fw.isActive)
#print('Title: ', fw.title)
#fileUploadWindow = gw.getWindowsWithTitle('File Upload')[0]
#print('Target window: ', fileUploadWindow)
#fileUploadWindow.activate()
#fileUploadWindow = pyautogui.getWindowsWithTitle('File Upload')[0]
#fileUploadWindow.activate()
pyautogui.PAUSE = 3
pyautogui.hotkey('ctrl', 'l')
pyautogui.typewrite(file, interval=0.1)
pyautogui.press('enter')
print('I am done.')
sys.exit(1)

BIN
selenium/cat.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
selenium/geckodriver Executable file

Binary file not shown.

BIN
selenium/geckodriver.exe Executable file

Binary file not shown.

299
selenium/get_page_source Executable file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"/home/pi/projects/instafeed/selenium/profiles/adobebestprices/images/UJAM Virtual Bassist DANDY v2.1.1 VST AAX [WIN].jpg":{"FILEPATH":"/home/pi/projects/instafeed/selenium/profiles/adobebestprices/images/UJAM Virtual Bassist DANDY v2.1.1 VST AAX [WIN].jpg","TIMESTAMP_UPLOADED":"19000100_000000"}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

356
selenium/selenium.pl Executable file
View File

@@ -0,0 +1,356 @@
#!usr/bin/perl
use feature qw(say);
use JSON::XS qw(encode_json decode_json);
use Selenium::Firefox::Profile;
use Data::Dumper;
use HTML::TreeBuilder::XPath;
use File::Slurp qw(read_file write_file);
use Selenium::Remote::WDKeys;
use Selenium::Firefox;
use Cwd;
use Getopt::Long qw(GetOptions);
use File::Basename;
use List::Util 'shuffle';
use Selenium::Waiter qw/wait_until/;
my (%config, $driver_profile, $driver);
sub Init {
%config = (
'xpath' => {
'input_username_classic' => '//*[@id="id_username"]',
'input_password_classic' => '//*[@id="id_enc_password"]',
'button_login_classic' => '//*[@id="login-form"]/p[3]/input',
'button_addtohomescreen' => '/html/body/div[4]/div/div/div/div[3]/button[1][text()="Add to Home screen"]',
'button_addtohomescreen_cancel' => '/html/body/div[4]/div/div/div/div[3]/button[2][text()="Cancel"]',
'button_newpost' => '//div[contains(@data-testid, "new-post-button")]',
'input_newpostupload' => '//*[@id="react-root"]/section/nav[2]/div/div/form/input',
'button_expand' => '//span[text()="Expand"]',
'button_next' => '//button[text()="Next"]',
'button_share' => '//button[text()="Share"]',
'textarea_caption' => '//textarea[contains(@placeholder,"Write a caption")]',
},
'profile' => {
'adobebestprices' => {
'DBFilepath' => cwd() . '/profiles/adobebestprices/db/db_adobebestprices.dat',
'imageDir' => cwd() . '/profiles/adobebestprices/images',
'filename_as_title' => 1,
'tags' => ['#Beats', '#FLStudio20', '#Producer', '#Ableton', '#Beatmaker', '#Studio', '#ProTools', '#Music', '#DAW', '#LogicPro', '#VST', '#VSTplugins', '#NativeInstruments', '#Drums', '#MIDI', '#Omnisphere', '#Keyscape', '#Trilian', '#Logic', '#Waves', '#Antares', '#AutoTune', '#Kontakt', '#SoundToys', '#FABFilter', '#Arturia', '#Windows', '#MAC'],
},
},
'dumpToFile' => cwd() . '/get_page_source',
'pyautogui_cmd' => 'python3 ' . cwd() . '/autogui.py',
'profile_selected' => undef,
'wipe_after' => 0,
);
&CheckParameter();
&UndumpFromFile();
&SelectImage();
$driver_profile = Selenium::Firefox::Profile->new;
$driver_profile->set_preference(
'intl.accept_languages' => 'en-US',
# 'general.useragent.override' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_1 like Mac OS X) AppleWebKit/605.1.15',
'general.useragent.override' => 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16',
);
# $driver_profile->set_boolean_preference("options.headless" => 1);
$driver = Selenium::Remote::Driver->new( 'browser_name' => 'firefox',
'platform' => 'LINUX',
'remote_server_addr' => 'localhost',
'port' => 4444,
'firefox_profile' => $driver_profile,
'extra_capabilities' => {
'moz:firefoxOptions' => {
#"args" => [ "--headless" ],
},
},
);
# $driver = Selenium::Firefox->new( 'browser_name' => 'firefox',
# 'platform' => 'LINUX',
# 'binary' => '/usr/local/bin/geckodriver',
# 'firefox_profile' => $driver_profile,
# 'extra_capabilities' => {
# 'moz:firefoxOptions' => {
# #"args" => [ "--headless" ],
# },
# },
# );
$driver->set_implicit_wait_timeout(5000);
$driver->set_window_size(812, 375);
say 'starting...';
say $driver->get_title();
say $driver->get_user_agent();
}
&Init();
&Login();
&NewPost();
&Finish();
sub RndHashtagString {
my $i = shift;
my $RndArr = &RndArrItems($config{profile}{'adobebestprices'}{tags}, $i);
my $hastags = join(' ', @$RndArr[0..$#{$RndArr}]);
return $hastags;
}
sub RndArrItems {
my ($arr_ref, $num_picks) = @_;
# Shuffled list of indexes into @deck
my @shuffled_indexes = shuffle(0..$#{$arr_ref});
# Get just N of them.
my @pick_indexes = @shuffled_indexes[ 0 .. $num_picks - 1 ];
# Pick cards from @deck
my @picks;
for my $index (@pick_indexes) {
push(@picks, $$arr_ref[$index]);
}
return \@picks;
}
sub SelectImage {
&DirectoryListing();
&FindNewDataset();
$config{image_backslash} = $config{image_selected};
# $config{image_backslash} =~ s/\//\\/g;
print Dumper \%config;
}
sub Login {
say 'Logging in...';
$driver->get('https://instagram.com/accounts/login/?force_classic_login');
my $tree = HTML::TreeBuilder::XPath->new_from_content($driver->get_page_source());
&Rndwait(1,3);
if( $tree->exists($config{xpath}{input_username_classic}) && $tree->exists($config{xpath}{input_password_classic}) ) {
say 'Found: Login elements.';
# Username & password
$driver->find_element($config{xpath}{input_username_classic})->click;
$driver->send_keys_to_active_element('adobebestprices');
&Rndwait(1,3);
$driver->find_element($config{xpath}{input_password_classic})->click();
$driver->send_keys_to_active_element('vst#1337');
&Rndwait(1,3);
# Click login button
$driver->find_element($config{xpath}{button_login_classic})->click();
}
else {
die 'Not found: Login elements.';
}
}
sub NewPost {
&Rndwait(5,10); # We see the home screen
my $tree = HTML::TreeBuilder::XPath->new_from_content($driver->get_page_source());
# add to homescreen popup?
&ClickXpath($config{xpath}{button_addtohomescreen}, $tree, 0); # click cancel button
&ClickXpath($config{xpath}{button_newpost}, $tree); # click new post button
&Rndwait(5,10);
# Bypass file dialog using pyautogui
my $cmd = $config{pyautogui_cmd} . ' "' . $config{image_backslash} . '"'; # image path needs to use backslash for python
my $ret = system($cmd) or die "system $cmd failed: $?";
# print `$cmd`;
# system($cmd);
# &Rndwait(30,45);
&FillNewPost();
}
sub FillNewPost {
# Wait for page reload after selecting an image
wait_until { $driver->find_element($config{xpath}{button_next}) };
my $tree = HTML::TreeBuilder::XPath->new_from_content($driver->get_page_source());
# Expand button
&ClickXpath($config{xpath}{button_expand}, $tree, 0); # click expand button to show image in full size
&Rndwait(2,4);
&ClickXpath($config{xpath}{button_next}, $tree); # click next button
&Rndwait(5,10);
# Caption
my $tree2 = HTML::TreeBuilder::XPath->new_from_content($driver->get_page_source());
my $profile = $config{profile_selected};
my $caption;
my $hastags = &RndHashtagString(9);
if ($config{profile}{$profile}{'filename_as_title'}) {
my $filename = basename($config{image_selected});
$filename =~ s/(NO INSTALL)|(SymLink Installer)//g;
$filename =~ s/( , )|(\.[^.]+$)//g;
$caption = "$filename\n\n" . $hastags;
}
&ClickXpath($config{xpath}{textarea_caption}, $tree2);
&Rndwait(5,6);
$driver->send_keys_to_active_element($caption);
&Rndwait(5,10);
# Share
&ClickXpath($config{xpath}{button_share}, $tree2);
&Rndwait(20,40);
}
sub Finish {
say 'Sleep and then quit';
&Rndwait(5,5);
&AddImageToDB();
&WipeImage() if $config{wipe_after};
$driver->quit();
}
sub ClickXpath {
my $die = 1;
my ($xpath, $tree, $die) = @_;
if( $tree->exists($xpath) ) {
say "Found: $xpath";
$driver->find_element($xpath)->click();
}
else {
die "Not found: $xpath" if $die;
warn "Not found: $xpath" if !$die;
}
}
sub Rndwait {
my ($minimum, $maximum) = @_;
# $seconds = $minimum + int(rand($maximum - $minimum));
$seconds = $minimum + rand($maximum - $minimum);
$milliseconds = int($seconds * 1000);
say "Sleeping for ${milliseconds}ms now...";
$driver->pause($milliseconds);
}
sub dumpToFile {
# &Delimiter((caller(0))[3]);
my ($filepath, $ref) = @_;
# DATA DUMPER UTF8 HACK
# no warnings 'redefine';
local *Data::Dumper::qquote = sub { qq["${\(shift)}"] };
local $Data::Dumper::Useperl = 1;
open my $FILE, '>:encoding(UTF-8)', $filepath;
print $FILE Dumper $ref;
close $FILE;
}
sub Delimiter {
my $SubName = shift;
print "\n" . "-" x 80 . "\nSUB " . $SubName . "\n" . '-' x 80 . "\n";
}
sub CheckParameter {
&Delimiter((caller(0))[3]);
GetOptions ('profile=s' => \$config{'profile_selected'}) or die &PrintUsage();
die &PrintUsage() if !$config{'profile_selected'};
my $profile = $config{'profile_selected'};
if (!exists $config{'profile'}{$profile}) {
print "Profile '$config{'profile'}' does not exist.\n";
&PrintUsage();
die;
}
}
sub UndumpFromFile {
&Delimiter((caller(0))[3]);
my $profile = $config{profile_selected};
if (-e $config{profile}{$profile}{'DBFilepath'}) {
my $json = read_file($config{profile}{$profile}{'DBFilepath'}, { binmode => ':raw' });
if (!$json) {
warn "DB file $config{'profile'}{$profile}{'DBFilepath'} is empty.\n";
return;
}
%{$config{db}} = %{ decode_json $json };
print "INFO: $config{'profile'}{$profile}{'DBFilepath'} has " . scalar(keys(%{$config{db}})) . " keys.\n";
}
elsif ( !-e $config{'profile'}{$profile}{'DBFilepath'} ) {
print "INFO: NO DB file found at $config{'profile'}{$profile}{'DBFilepath'}. Creating now... ";
write_file( $config{'profile'}{$profile}{'DBFilepath'}, '' );
&UndumpFromFile();
}
}
sub PrintUsage {
print "Usage: $0 --profile *name*\n";
print "Following profiles are available:\n";
print "* $_\n" for keys( %{$config{'profile'}} );
}
sub DirectoryListing {
&Delimiter((caller(0))[3]);
my $profile = $config{profile_selected};
my @files = glob ( "$config{profile}{$profile}{imageDir}/*" );
%{$config{images_available}} = map { $_ => { 'FILEPATH' => "$_" } } @files;
}
sub FindNewDataset {
&Delimiter((caller(0))[3]);
my $i = 0;
for my $key (keys %{$config{images_available}}) {
if (exists $config{db}{$key}) {
print "OLD: $key\n";
}
elsif (!exists $config{db}{$key}) {
print "NEW: $key\n";
$config{image_selected} = $key;
last;
}
$i++;
}
if ($i == scalar(keys(%{$config{images_available}}))) {
die "\nNO NEW FILES AVAILABLE.\n";
}
}
sub AddImageToDB {
&Delimiter((caller(0))[3]);
my $profile = $config{profile_selected};
my $selected = $config{image_selected};
$config{'images_available'}{$selected}{'TIMESTAMP_UPLOADED'} = sprintf ( "%04d%02d%02d_%02d%02d%02d", $year+1900,$mon+1,$mday,$hour,$min,$sec);
$config{db}{$selected} = $config{images_available}{$selected};
my $json = encode_json(\%{$config{db}});
write_file($config{profile}{$profile}{'DBFilepath'}, { binmode => ':raw' }, $json);
}
sub WipeImage {
&Delimiter((caller(0))[3]);
my $image = $config{image_selected};
print "Deleting $image...";
unlink($image) or die "Could not delete $image!\n";
print " done.\n";
}
# SERVER:
# java -Dwebdriver.gecko.driver=C:\Users\vstbestprices\Seafile\INSTAFEED_SYNC\selenium\geckodriver.exe -jar C:\Users\vstbestprices\Seafile\INSTAFEED_SYNC\selenium\selenium-server-standalone-3.141.59.jar
# java -jar /home/pi/projects/instafeed/selenium/selenium-server-standalone-3.141.59.jar