RPA Express (WorkFussion) "No modal dialog is currently open" on second iteration, after "OK" click in modal dialog - selenium

My RPA Express project iterates through a number of URLs and if a certain condition is met, clicks on a icon that pops up a HTML "Confirm" modal dialog. The code clicks "OK" (tried also Keypress "Enter") and then goes into a next URL.
The problem is that after the first confirmation (click OK or press Enter) on the dialog box and processing to a next URL, all attempts to use Web Element (get by xpath) fail with:
Caused by: org.openqa.selenium.NoAlertPresentException: No modal dialog is currently open
I tried unsuccessfully:
to "CTRL+F5" the page on reload
set focus on the page (with MouseClick) after reload
It looks like the system does not recognize that the modal dialog was actually closed.
Any idea how to get it fixed?
Here is the main loop code:
event_id_list.each( {this_event_id ->
this_id = RString.of(RNumber.fromRepresentation("${this_event_id}","0;pl-PL").toRepresentation("0;pl-PL"))
this_url = event_url_patern.replaceFirstIgnoreCase("[id]", "${this_id}")
confirm_close_window = RBoolean.fromCanonical("false")
sleep(1000)
inDesktop {
sendKeys(StringTransformations.getKeyPressText(63, 0, 116, 2))
}
// Group of actions: Open Event URL
$(byImage("1536237127355-anchor-1536911026524.apng", Integer.valueOf(0), Integer.valueOf(0))).click()
setClipboardText(this_url as String)
inDesktop {
sendKeys(StringTransformations.getHotKeyText(97, 2))
}
inDesktop {
sendKeys(StringTransformations.getHotKeyText(118, 2))
}
inDesktop {
sendKeys(StringTransformations.getKeyPressText(28, 13, 10, 0))
}
def i1 = System.currentTimeMillis() + 8000
boolean i0 = true
while (i0) {
try {
$(byImage("1536912304113-anchor.apng")).getCoordinates()
even_opened = RBoolean.TRUE
break
} catch (Exception ignored) {
even_opened = RBoolean.FALSE
}
i0 = System.currentTimeMillis() < i1
}
$(byImage("1537167271142-anchor-1537167271149.apng", Integer.valueOf(0), Integer.valueOf(0))).click()
try {
this_crewx_vessel = RString.of($(byXpath("/html/body/form/div[3]/table[1]/tbody/tr[1]/td[2]/b")).text())
} catch (Exception i2) {
this_crewx_vessel = RString.of("N/A")
}
try {
this_crewx_port = RString.of($(byXpath("//*[#id=\"form1\"]/div[3]/table[1]/tbody/tr[1]/td[6]/b/a")).text())
} catch (Exception i3) {
this_crewx_port = RString.of("N/A")
}
sleep(4000)
Resource.append("${log_file_path}", "<p>Processing id ${this_id} (${this_crewx_vessel} at ${this_crewx_port}) - outcome: ", "UTF-8")
icon_src = RString.of($(byXpath("//*[#id=\"toggleEventImg\"]")).getAttribute("src"))
if ((RString.of("images/lock.gif")) in (icon_src)) {
$(byXpath("//*[#id=\"toggleEventImg\"]")).click()
def i5 = System.currentTimeMillis() + 3000
boolean i4 = true
while (i4) {
try {
$(byImage("1536910894370-anchor.apng")).getCoordinates()
confirm_close_window = RBoolean.TRUE
break
} catch (Exception ignored) {
confirm_close_window = RBoolean.FALSE
}
i4 = System.currentTimeMillis() < i5
}
if ((confirm_close_window) == (RBoolean.fromCanonical('true'))) {
inDesktop {
sendKeys(StringTransformations.getKeyPressText(28, 13, 10, 0))
}
sleep(4000)
Resource.append("${log_file_path}", "closed.</p>", "UTF-8")
// compare_item = RString.of($(byXpath("//*[#id=\"toggleEventImg\"]")).text())
} else {
sleep(4000)
Resource.append("${log_file_path}", "no action (confirm window no show)</p>", "UTF-8")
}
} else {
sleep(4000)
Resource.append("${log_file_path}", "no action (already closed).</p>", "UTF-8")
}
})
The error is thrown at:
icon_src = RString.of($(byXpath("//*[#id=\"toggleEventImg\"]")).getAttribute("src"))

Instead of clicking an image and typing in the url, try opening the URL using OpenIE or OpenChrome
openIE(UrlOperations.ensureProtocol("${this_url}"))

Related

Google Reaptcha v3 still letting spam through

I just added Google Recaptcha V3 to a site and a lot of spam is still getting through. I know that Google needs to build up some traffic on the site to determine if something is spam. How long should that take? Like if this is still happening after X days there is a problem? What is X?
Here is how I implemented this. On the client side I get the token:
function validateCaptcha(form, callback) {
$("#captcha-error").addClass('hidden');
$("#captcha-error").hide();
$("#captcha-error").html('');
var formName = $('#formName').val();
if (!formName) formName = 'AmeriGasGenericForm';
var siteKey = $('#siteKey').val();
if (grecaptcha) {
try {
grecaptcha.ready(function() {
grecaptcha.execute(siteKey, { action: formName }).then(function(token) {
$.ajax({
url: "/recaptcha-validate?recaptchaResponse=" + token + "&actionName=" + formName,
async: false,
success: function (response) {
console.log("score:" + response.score);
if (response.Success == false) {
$("#captcha-error").html('Unable to verify reCAPTCHA. Please try again.');
$("#captcha-error").removeClass('hidden');
$("#captcha-error").show();
} else {
callback(form);
}
},
error: function(e) {
console.log(e);
}
});
});
});
} catch (err) {
console.log(err);
}
}
}
That calls a server side check to validate:
public JsonNetResult ValidateRecaptcha(string recaptchaResponse, string actionName)
{
var result = new RecaptchaResult();
if (string.IsNullOrEmpty(recaptchaResponse))
{
result.Success = false;
return new JsonNetResult(result);
}
var secretKey = Settings.GetSetting("reCAPTCHA.Secret");
var url = "https://www.google.com/recaptcha/api/siteverify?secret=" + secretKey + "&response=" + recaptchaResponse;
var recaptchaThresholdString = ConfigurationManager.AppSettings["reCaptchaThreshold"];
if (!float.TryParse(recaptchaThresholdString, out var threshold))
{
threshold = 0.5f;
}
using (var reCaptchaHttpClient = new HttpClient())
{
try
{
var reCaptchaResponseString = reCaptchaHttpClient.GetStringAsync(url).Result;
var response = JsonConvert.DeserializeObject<RecaptchaResponseModel>(reCaptchaResponseString);
result.Score = response.score;
if (response.Success && response.score >= threshold && string.Equals(response.action, actionName,
StringComparison.CurrentCultureIgnoreCase))
result.Success = true;
else
result.Success = false;
}
catch (Exception ex)
{
result.Success = false;
}
}
return new JsonNetResult(result);
}
I have the threshold set to allow anything higher than .5 through. But, when I look at the reCaptcha admin console in Google, like 99% of the requests are scored at .9. So Im not sure what to do here to prevent spam. It seems recaptcha thinks everything is a human but when I look at actual submissions I am receiving, they are clearly spam.

Interactive button doesn't work properly when using pub/sub

I'm writing a Hangouts Chat bot in C# that uses pub/sub so I can host the bot on our side of a firewall. Everything seems to work well except interactive buttons within cards. If I create a button with a specific action method name, the bot does receive the CARD_CLICKED message with the appropriate action method name. However, it doesn't seem like the card in the Hangouts Chat app knows a response was sent because the bot ends up getting the CARD_CLICKED message three times before the Hangouts Chat app finally says "Unable to contact Bot. Try again later". I've been using the Google.Apis.HangoutsChat.v1 and Google.Cloud.PubSub.V1 packages from NuGet for the bot.
This is speculation, but it seems like the issue might be that interactive buttons don't work properly through pub/sub. Any help would be appreciated.
Here is a snippet of the code I have:
SubscriptionName subscriptionName = new SubscriptionName(PROJECT_ID, SUBSCRIPTION_ID);
SubscriberServiceApiClient client = SubscriberServiceApiClient.Create();
GoogleCredential credential = GoogleCredential.FromFile(CREDENTIALS_PATH_ENV_PROPERTY).CreateScoped(HANGOUTS_CHAT_API_SCOPE);
HangoutsChatService chatService = new HangoutsChatService(new BaseClientService.Initializer
{
ApplicationName = "My Bot",
HttpClientInitializer = credential
});
while (true)
{
PullResponse response = client.Pull(subscriptionName, false, 3, CallSettings.FromCallTiming(CallTiming.FromExpiration(Expiration.FromTimeout(TimeSpan.FromSeconds(90)))));
if ((response.ReceivedMessages == null) || (response.ReceivedMessages.Count == 0))
Console.WriteLine("Pulled no messages.");
else
{
foreach (ReceivedMessage message in response.ReceivedMessages)
{
try
{
byte[] jsonBytes = message.Message.Data.ToByteArray();
JObject json = JObject.Parse(Encoding.UTF8.GetString(jsonBytes));
string messageType = (string)json["type"];
switch (messageType)
{
case "MESSAGE":
{
// Get text
string messageText = (string)json["message"]["text"];
Console.WriteLine($"[{messageType}] {messageText}");
// Send response
string spaceName = (string)json["space"]["name"];
SpacesResource.MessagesResource.CreateRequest request = chatService.Spaces.Messages.Create(new Message
{
Cards = new[]
{
new Card
{
Header = new CardHeader
{
Title = "Message Received!"
},
Sections = new[]
{
new Section
{
Widgets = new[]
{
new WidgetMarkup
{
Buttons = new[]
{
new Button
{
TextButton = new TextButton
{
Text = "Click Me!",
OnClick = new OnClick
{
Action = new FormAction
{
ActionMethodName = "ClickedAction"
}
}
}
}
}
}
}
}
}
}
},
Thread = new Thread
{
Name = (string)json["message"]["thread"]["name"]
}
}, spaceName);
Message responseMsg = request.Execute();
break;
}
case "CARD_CLICKED":
{
string actionMethodName = (string)json["action"]["actionMethodName"];
Console.WriteLine($"[{messageType}] {actionMethodName} at {((DateTime)json["message"]["createTime"]).ToString()}");
// Send response
string spaceName = (string)json["space"]["name"];
SpacesResource.MessagesResource.CreateRequest request = chatService.Spaces.Messages.Create(new Message
{
ActionResponse = new ActionResponse
{
Type = "UPDATE_MESSAGE"
},
Text = $"You clicked on '{actionMethodName}'.",
Thread = new Thread
{
Name = (string)json["message"]["thread"]["name"]
}
}, spaceName);
Message responseMsg = request.Execute();
break;
}
default:
{
Console.WriteLine($"[{messageType}]");
break;
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error parsing message: {ex}");
}
}
// Acknowledge the message so we don't see it again.
string[] ackIds = new string[response.ReceivedMessages.Count];
for (int i = 0; i < response.ReceivedMessages.Count; ++i)
ackIds[i] = response.ReceivedMessages[i].AckId;
client.Acknowledge(subscriptionName, ackIds);
}
}
Using buttons with Hangouts Chat API requires a custom answer including:
{
'thread': {
'name': thread_id
},
'actionResponse': {
'type': 'UPDATE_MESSAGE'
}
}
I'd recommend using Hangouts Chat API with a bot URL.

Alarms & Notifications for plasmoids

I'm having a hard time finding any literature or examples on how to write notifications for plasmoids.
My plasmoid can so far display notifications and sound alarms when certain conditions are met but i don't know how to:
add a 'Dismiss' button to the notification to stop playing a continuous alarm, or
get the alarm to stop sounding when the notification is closed.
This is my (abridged) code so far:
PlasmaCore.DataSource {
id: notificationSource
engine: "notifications"
}
SoundEffect {
id: notificationSound
source: plasmoid.file("data", "beep-alarm.wav")
loops: SoundEffect.Infinite
}
function createNotification(text) {
var service = notificationSource.serviceForSource("notification");
var operation = service.operationDescription("createNotification");
operation["appName"] = root.appName;
operation["appIcon"] = plasmoid.configuration.icon;
operation.summary = root.title;
operation["body"] = '<b>' + text + '</b>';
operation["expireTimeout"] = 0;
operation["isPersistent"] = 'isPersistent';
operation["urgency"] = 2;
var tmp = service.startOperationCall(operation);
if (plasmoid.configuration.alarmEnabled) {
notificationSound.play();
}
}
Plasmoid.compactRepresentation: Item {
...
PlasmaComponents.Label {
text: {
if (Number(root.x) >= plasmoid.configuration.y) {
root.createNotification(root.x);
}
root.x
}
}
...
}

Arguments passed to WorkerScript source

I need to load documents which filepath is provided by a FileDialog. The document are rather long to load so I want to display a BusyIndicator while loading the docs. In order to get the UI spinned while loading my doc I need to load my docs in a WorkerScript. Now I need to provide my filepath to the functions in the .js file pointed by WorkerScript::source. I could not find any way to do so.
Any idea?
Here is my source code:
WorkerScript
{
id: importScanWorkerScript
source: "script.js"
}
FileDialog
{
id: importScanDialog
visible: false
title: "Import a [scan] file"
folder: "/home/arennuit/Desktop/living_room_traj0n_scannedScene"
nameFilters: [ "STL files (*stl)" ]
selectedNameFilter: "STL files (*stl)"
onAccepted:
{
importScanDialog.visible = false;
busyIndicator.running = true;
uiController.onImportScanDevMenuClicked(importScanDialog.fileUrl);
busyIndicator.running = false;
}
}
BusyIndicator
{
id: busyIndicator
running: false
anchors.centerIn: parent
}
WorkerScript allows you to send custom object to a thread and also to get a custom object back, I guess the documentation is pretty clear. So the answer to your question is WorkerScript.sendMessage(). In the simple example below the WorkerScript receives random number of iterations from main.qml and so generates and sent back generated text, displayed by main.qml. The GUI doesn't freeze while waiting:
main.qml
import QtQuick 2.9
import QtQuick.Window 2.0
import QtQuick.Controls 2.2
Window {
id: window
width: 600
height: 400
visible: true
ScrollView {
id: view
anchors.fill: parent
clip: true
TextArea {
id: myText
text: ""
enabled: false
}
}
Component.onCompleted: {
var cnt = 1000 + Math.round(Math.random() * 1000);
myText.text = "Please wait, generating text (" + cnt + " characters) ...";
myWorker.sendMessage({count: cnt});
}
WorkerScript {
id: myWorker
source: "script.js"
onMessage: {
myText.text = messageObject.reply;
myText.enabled = true;
spinner.running = false;
}
}
BusyIndicator {
id: spinner
anchors.centerIn: parent
running: true
}
}
script.js
function pause(millis)
{
var date = new Date();
var curDate = null;
do {
curDate = new Date();
} while((curDate - date) < millis);
}
WorkerScript.onMessage = function(message) {
var txt = "";
var count = message.count;
for(var i = 0;i < count;i ++)
{
var ch = 97 + Math.round(Math.random() * 25);
txt += String.fromCharCode(ch);
var eol = Math.round(Math.random() * 30);
if(eol === 1)
txt += "\r\n";
else if(!(eol % 5))
txt += " ";
pause(10);
}
WorkerScript.sendMessage({ 'reply': txt })
}

Pausing a game with ActionScript 2

I'm making a game where the player must avoid random falling objects. I dont know how to implement pausing. I've been stuck on this for 2 days!
I tried using gotoAndPlay and such, but the objects continue to run in the background. When I resume the game, they're still falling and it seems like the frame resets and loads new random falling objects.
var steps:Number = 10;
var spriteX:Number = 280;
var spriteY:Number = 650;
var alienCounter=1;
var asteroidCounter=1;
var live:Number=3;
var depthLevel=3000;
var score:Number = 0;
var gamePaused;
dropTimer=setInterval(createAlien,2000);
drpTimer2=setInterval(createAsteroid,1000);
//---- functions ----
function checkKeys()
{
if (Key.isDown(Key.RIGHT))
{
spriteX += steps;
}
else if (Key.isDown(Key.LEFT))
{
spriteX -= steps;
}
}
function updateSpaceship()
{
ship._x = spriteX;
ship._y = spriteY;
}
function createAlien()
{
var curr_alien;
curr_alien=attachMovie("alien","alien"+alienCounter,depthLevel);
curr_alien._y=40;
curr_alien._x=Math.random()*510+20;
curr_alien._xscale=curr_alien._yscale=50;
curr_alien.speed=Math.random()*10+3;
alienCounter+=1;
depthLevel+=1;
curr_alien.onEnterFrame=alienMove;
}
function alienMove()
{
if(!gamePaused)
{
this._y+=this.speed;
if(this.hitTest(ship))
{
score += 1;
trace(score);
removeMovieClip(this);
}
}
}
function createAsteroid()
{
var curr_asteroid;
curr_asteroid=attachMovie("asteroid","asteroid"+asteroidCounter,depthLevel);
curr_asteroid._y=40;
curr_asteroid._x=Math.random()*510+20;
curr_asteroid._xscale=curr_asteroid._yscale=50;
curr_asteroid.speed=Math.random()*10+3;
asteroidCounter+=1;
depthLevel+=1;
curr_asteroid.onEnterFrame=asteroidMove;
}
function asteroidMove()
{
if(!gamePaused)
{
this._y+=this.speed;
if(this.hitTest(ship))
{
live -= 1;
trace(live);
removeMovieClip(this);
if(live<=0)
{
gotoAndPlay(5);
}
}
}
}
this.onEnterFrame = function()
{
checkKeys();
updateSpaceship();
if(Key.isDown(80))
{
if(!gamePaused)
{
gamePaused=true;
gotoAndPlay(4);
}
else
{
gamePaused=false;
gotoAndStop(3);
}
}
};
i decided to use a key instead because i cannot find any solutions when trying to use a button. The pause function is not working as i expected, i need to enter key 'p' several times to pause it, but i dont want the frame resets and loads more random objects when i resume it.
try this:
remove your:
this.onEnterFrame = function()
{
checkKeys();
updateSpaceship();
if(Key.getCode() == 80)
{
if(!gamePaused)
{
gamePaused=true;
gotoAndPlay(4);
trace("AAA")
}
else
{
gamePaused=false;
gotoAndStop(3);
trace("BBB")
}
}
};
Add this (pause by pressing the 'P' key on your keyboard):
var keyListener:Object = new Object();
keyListener.onKeyUp = function() {
if(Key.getCode() == 80) {
gamePaused = !gamePaused;
mainLoop();
}
};
Key.addListener(keyListener);
function mainLoop() {
if (gamePaused) {
gotoAndStop(4); // update game actions here
trace("game is paused");
return;
}
gotoAndStop(3); // update game actions here
trace("game is running");
}
Alternatively if you need to pause using a button:
my_pause_Button.onRelease = function() { // your button instance name 'my_pause_Button'
gamePaused = !gamePaused;
mainLoop();
};
Put this in your button function or keydown function:
stage.frameRate = 0.01;