Click play button in Google Apps Script with Greasemonkey? - javascript

I am coding a Greasemonkey script to click the play button for a script in Google Apps Script every five 5 minutes to avoid the execution time limit set by Google.
I was able to identify with the script when the time is over but am unable to click the "run" button by using JavaScript. I have been inspecting the button with Google Chrome and tried a few things but I couldn't make it work.
Can anyone please help me?
I guess clicking any button in the toolbar of Google Sheets would be exactly the same..
Thanks!

You are approaching this in a completely wrong way. You should be including the possibility to restart the execution with a trigger internally in your script. I will show you how I did it. Keep in mind that my script is quite large and it performs a loop and I had to make it remember where in the loop it stopped, so it could continue with the same data.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Purpose: Check if there is enough time left for another data output run
// Input: Start time of script execution
// Output: Boolean value if time is up
function isTimeUp(start, need) {
var cutoff = 500000 // in miliseconds (5 minutes)
var now = new Date();
return cutoff - (now.getTime() - start.getTime()) < need;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Here the start is simply a new Date() that you create when you start the script. The need is simply an average time it takes for my script to perform 1 loop. If there is not enough time for a loop, we will cut off the script with another function.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Purpose: Store current properties and create a trigger to start the script after 1 min
// Input: propertyCarrier object (current script execution properties)
// Output: Created trigger ID
function autoTrigger(passProperties, sysKeys) {
var sysProperties = new systemProperties();
if (typeof sysKeys === 'undefined' || sysKeys === null) {
sysKeys = new systemKeys();
}
var triggerID = ScriptApp.newTrigger('stateRebuild')
.timeBased()
.after(60000)
.create()
.getUniqueId();
Logger.log('~~~ RESTART TRIGGER CREATED ~~~');
//--------------------------------------------------------------------------
// In order to properly retrieve the time later, it is stored in milliseconds
passProperties.timeframe.start = passProperties.timeframe.start.getTime();
passProperties.timeframe.end = passProperties.timeframe.end.getTime();
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// Properties are stored in User Properties using JSON
PropertiesService.getUserProperties()
.setProperty(sysKeys.startup.rebuildCache, JSON.stringify(passProperties));
//--------------------------------------------------------------------------
Logger.log('~~~ CURRENT PROPERTIES STORED ~~~');
return triggerID;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Yours can be more simplistic if you do not need to remember where you stopped (judging by your current implementation you do not care whether you start from the beginning or not).
The trigger you create should either aim at the main function or if you need to pass on the data like I do, you will need to have a separate starter function to get the data back from the user properties and pass it on.

Related

Can I get info about a trigger time interval used to launch google apps script?

I recently discovered google apps script and it's amazing. I wrote a script that adds label to messages using logic that would not be available in normal GMail filters. I have then set that filter script to run on a time trigger, as unfortunately it is not possible to run it when message is received.
How my filter works:
function processInbox(age = "2.5h") {
// process all recent threads in the Inbox
var threads = GmailApp.search("newer_than:"+age+" in:inbox");
Logger.log("Processing "+threads.length + " threads.");
for (const thread of threads) {
if(hasLabels(thread))
continue;
// get all messages in a given thread
var messages = thread.getMessages();
for (const message of messages) {
if(matchesMyFilter(message)) {
thread.addLabel(GmailApp.getUserLabelByName("My label"));
}
}
}
}
As you can see, there is an optional time parameter. Currently, the filter is set to run every 2 hours, so I check messages received in that timeframe with a little margin. However, if I want to set the trigger to run once per day, I would have to manually change the time in the script.
Is it possible to get information about the trigger used to launch the script and set the search range accordingly to the trigger timer interval?
You can create the time-based trigger programmatically instead and pass the timeframe wanted/needed by using the everyHours() method.
function createTimeDrivenTrigger() {
ScriptApp.newTrigger('processInbox')
.timeBased()
.everyHours(YOUR_NUMBER_HERE)
.create();
}
However, unfortunately, you cannot modify an already existing trigger using provided methods since the Trigger class doesn't offer any options of setting any properties to a trigger, unless a new one is created.
Reference
Trigger Class Apps Script;
Managing triggers programmatically.

How to prevent users from affecting number of button clicked times

I have a game written in JavaScript and what it basically does is start a ten seconds timer and register the number of times the user is able to click on a certain button, before the timer elapses.
How the code works:
When a user clicks on the button, an element gets added to an array, using push function, then a different function returns the length of the array as the number of times clicked.
The problem with this:
If a user opens up the dev tools and alters the number of times an element is added to the array per click, this will change the outcome of the result.
My Approach:
What I decided to do is to store the length before I ran the push function and also after I ran the push function, then compare their differences and if it's greater than 1, it means something is not right. This seemed to work in my head until I wrote it down in code and discovered that if the user pushed multiple times before I checked the differences then it would go unnoticed. Please big brained guys, help me.
My code:
$('body').on('click', '.btn.z', function () {
// start listening
startCountingClicks()
})
var timerStarted = false;
var tc = [];
function startCountingClicks () {
$('.btn.z').html('ClickZed');
$('.Score').html('Your Score: '+gettc()+" clicks");
if (timerStarted == false) {
startTimer(10, $('#time'));
}
// user does multiple push before this function: startCountingClicks is called
var previous_length = tc.length; // get length before push
tc.push(1);
var new_length = tc.length; // get length after push
if (new_length - previous_length !== 1) {
console.log("fraud"); // this is supposed to catch a thief!!!
}
console.log(new_length+" "+previous_length);
timerStarted = true;
}
function gettc (){
// get number of clicks
return tc.length ;
}
A code that totally breaks this:
$('button').click(function(){tc.push(1); tc.push(1)})
EDIT:
I do not wish to protect against dev tools, though I am not against that method if it works. I just wish to get a better way of counting my clicks, a way that can't be affected by writing code on the dev tools.
You can't really stop people from doing stuff on the client side. It is pointless trying to prevent that. The best thing you can do is make sure whatever is sent matches what you expect on the server side.

How to detect focus when reopening Safari on iPhone?

I have a web-application for iPhone, and I need to trigger a Javascript function when the web page is in focus, in other words, when Safari is open.
What I want to accomplish is to start a timer in some way when the user clicks on a tel-link and starts the call. When the call ends, Safari pops up again, and the timer ends.
Is there any way to do this?
Best Regards
Linus
try this:
if you trigger the link for the call set the actual time in a localStorage-item.
$("#yourButton").click(function() {
var actualTime = new Date().getTime();
window.localStorage.setItem('callStart', actualTime);
})
after that you need to read the Storage after user ends up the call.
You can set this in the document.ready on the opening page.
in $(document).ready(function() {})
// check for the localStorageItem
if (window.localStorage.getItem('callStart')) {
// get it
var timeStart = window.localStorage.getItem('callStart');
var now = new Date().getTime();
/*
Now calculate here the difference now - timeStart
and you will get seconds, minutes or whatever you want
*/
// !!! Dont forget to clear the localStorageItem
window.localStorage.removeItem('callStart');
}
This is what I would try. The Usage of the HTML5-localStorage gives you the possibility to store key/values and data isnt lost if user stops the app or device is automatically locked.
Hope this helps a bit.
ADDED: You even can store JSON as the value in the localStorageItem. So you can set an callID and implement a calling-history for your users.

How to call a javascript function after a fixed time delay from a fixed time considering page refresh

I have a use case in which a function needs to be called after 30 minutes from a fixed time. Say the fixed time is 16:30:48 and the function needs to be called after 30 minutes from 16:30:48. User might refresh the page but this should not affect the timing of calling the javascript function. The function should be called at 17:00:48 no matter how many page refreshes the user makes.
Is there a method in javascript that takes the time or Date in a function and execute the function at that time.
Is there a way in javascript to achieve that?
Thanks.
Some notes:
Because of the page refresh, the only real way to do this is to store the first page load time in a cookie or local storage if your target browsers support it.
You'll need to not replace that cookie or local storage item if you see it's already there.
If using a cookie, you'll need to store the date as a string, so probably best to get the "milliseconds since The Epoch" value (yourDate.getTime()) and then store the string version of that.
Compare the resulting epoch-ms value to the current date's epoch-ms value and, if it's been 30 minutes, issue your alert or what-have-you. If it hasn't (yet) been, set up a timer on the current page to fire when it has been.
So in pseudo-code:
var existingValue, remaining, THIRTY_MINUTES;
THIRTY_MINUTES = 30 * 60 * 1000;
existingValue = getExistingValueFromCookieOrLocalStorage("myvalue");
if (!existingValue || existingValue > SOME_STALE_AMOUNT) {
// First page load / existing value is stale, start again
putValueInStorage("myvalue", String(new Date().getTime()));
}
else {
// We have the value, how long left?
remaining = THIRTY_MINUTES - (new Date().getTime() - Number(existingValue));
if (remaining <= 0) {
// It's time!
trigger();
}
else {
// Not yet, schedule the timer -- this will get wiped out by
// a page reload
setTimeout(trigger, remaining);
}
}
function trigger() {
showTheAlert();
removeValueFromStorage("myvalue");
}
You could save a cookie with the time to execute the function and examine the cookie when the page is loaded. Otherwise for in-page timing, a setTimeout() should suffice.
Assuming cookies are enabled, you could set a cookie when the user first enters the site (checking one isn't already in existence) with the time +30 mins. Then do a window.setTimeOut () calling your function. This way, is the user refreshes the window you can pull back the cookie fetching your target time, then recalculate how long until your function should be called, then setup a new window.setTimeOut()

Js - detect if was page called from history [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Can you detect/redirect a back button press through javascript?
I am developing a small web application. In my application I must know when the user clicks the "back" button, so I can run some javascript code. Is there any such way to detect it?
thank you
Ok, so I discovered that the JS API cannot access the history object's next property without elevated permissions, which got me thinking in another direction.
Form fields are automatically fetched from the browser's cache, thus holding historic data. while this is true, javascript code is run independently each time.
So I created a small hidden field to hold a timestamp and compare it against the javascript's generated datatime.
Here is the code, I am sure it can be much better implemented, though time is short:
$(document).ready(function () {
var date = new Date();
var clientMiliseconds = date.getTime();
clientMiliseconds = roundTime(clientMiliseconds);
var serverTimeStamp = $('#' + '<%= hfTimeStamp.ClientID %>').val();
serverTimeStamp = roundTime(serverTimeStamp);
alert(serverTimeStamp == clientMiliseconds);
});
function roundTime(time) {
time = Math.floor(time);
//since the server renders the time components a few seconds before the page is downloaded
//which also depends on where you assign the date on the serverside
//we've got a small inaccuracy of few seconds. we neglect these seconds, assuming that it would take the user
//a few seconds to click the back button
time = time / 10000;
time = Math.floor(time);
return time;
}
You can't do that. you can bind an event so that something happens when your user navigates away from the page (use onbeforeunload or unload() to do that) but there is no way to know where he has gone

Categories

Resources