Create custom cron in wordpress? - cron

I have a wordpress page and i need to set this page in cron. How can i do it?
My wordpress page link is:
http://example.com/wp-admin/admin.php?page=popshop-import&category=32194&cate_id=1279
This page works fine when i run this url in browser. How can i set this to wordpress cron?

Well i dont have any experience with popshop api, but using the wordpress crons is pretty simple. You just have to create a function that does what ever you want, and then hook it into the wp_schedule_event function.
Lets suppose POPSHOP API is a simple REST API. This is how you will make the cron job.
if ( ! wp_next_scheduled( 'popshop_api' ) ) {
wp_schedule_event( time(), 'hourly', 'popshop_api' );
}
add_action( 'popshop_api', 'running_popshop_api' );
function my_task_function() {
$service_url = 'http://example.com/wp-admin/admin.php?page=popshop-import&category=32194&cate_id=1279';
$curl = curl_init($service_url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$curl_response = curl_exec($curl);
if ($curl_response === false) {
$info = curl_getinfo($curl);
curl_close($curl);
die('error occured during curl exec. Additioanl info: ' . var_export($info));
}
curl_close($curl);
$decoded = json_decode($curl_response);
if (isset($decoded->response->status) && $decoded->response->status == 'ERROR') {
die('error occured: ' . $decoded->response->errormessage);
}
echo 'response ok!';
var_export($decoded->response);
}
So the code uses curl to and looks for the response, if the response is not false it saves the data to the $curl_response variable, then you can var_dump/var_export it and do what ever you want with it.

Related

Horseman/PhantomJS - How to check for errors and prevent creating cookies?

I'm using node-horseman on a project that creates RSS Alerts on Google Alerts. The user that hasn't connected yet must log-in with his/her Google account through our application, to then be able to retrieve the feed list (s)he has. The application is basically used to auto-post on Facebook Pages news about any RSS feed created.
So far, the login function is the following:
* login() {
if (!this.email || !this.password) {
this.addError(HTTPResponse.STATUS_FORBIDDEN, 'E-mail and Password are necessary')
return false
}
const horseman = new Horseman({ cookiesFile })
return new Promise((resolve, reject) => {
horseman
.open('https://accounts.google.com')
.type('input[type="email"]', this.email)
.click('#next')
.wait(1000)
.type('input[type="password"]', this.password)
.click('#signIn')
.wait(3000)
.close()
setTimeout(function() {
resolve(true)
}, 3000)
})
}
Very simple. It logs in and create a cookiesFile to be able to create new feeds and retrieve the existing ones. But it's totally not fail proof since there's no way to check for errors, and I couldn't find an example or make anything wok. I tried to use evaluate() and check if there's the .error_msg tag, but it throws an error in the phantomJS Unhandled rejection fn:
...
.wait(1000)
.evaluate(function() {
if (jQuery('.error-msg').length > 0) {
this.addError(HTTPResponse.STATUS_INTERNAL_SERVER_ERROR, 'Error!')
return false
}
})
...
It doesn't throw any errors not interrupts the execution and still creates a bad cookies file.
When working with PhantomJS-like libraries it's very important to get the concept of two main different contexts: one is the context of the script (which you write to automate dealing with a target site) and the other is the context of the target site's page. These contexts to do not intersect, they have different variables and capabilities.
Everything that happens inside of page.evaluate(), happens in the context of a browser page. You can actually visualise that code as being executed in console of your (Chrome|Firefox|Safari) browser at that site.
You can execute this in console at Google login page
if (jQuery('.error-msg').length > 0) {
// ...
}
But when you write
if (jQuery('.error-msg').length > 0) {
this.addError(HTTPResponse.STATUS_INTERNAL_SERVER_ERROR, 'Error!')
return false
}
it will throw an error, because you've mixed the two contexts. There is no .addError method on that Google page, it's in your script context.
Instead you could write
.evaluate(function() {
if (jQuery('.error-msg').length > 0) {
return {
errors : jQuery('.error-msg').length,
message : "Some message about errors"
}
}
})
.then(function(result){
if(result.errors > 0)
{
// ...
}
})
See the docs on using evaluate in Horseman: https://github.com/johntitus/node-horseman#evaluatefn-arg1-arg2

Intern and Leadfoot conditional wait until

If there a way to perform .click() after the element become visible.
My function chain is built like that:
this.remote.findByXpath("//div[#data-index='blockContainer']/button[text()='Create new']").then(function(element) {
return element.click().end();
})
Sometimes I got error says 'the element is not visible', is it possible to perform click after the element displayed in browser? I know Leadfoot supplies pollUntil to do similar thing but I don't want to execute xpath at browser side, instead of I want to do until at running server side.
To solve my problem I tried following two ways but doesn't help:
I tried to pass Leadfoot Element to browser side script and check if it is visible. But it seems browser side code doesn't recognize leadfoot/element object.
command.find(...).then(function(element) {
return command.then(pollUntil(
function(element) {
if (element.style.display == 'none') return null;
return true;
}, [element], 60000, 500)).then(function(el){
});
}).click().end();
Also tried to customize pollUntil myself but doesn't work as well
function pollVisible(element, timeout) {
var dfd = new Deferred();
var endTime = Number(new Date()) + timeout;
(function poll() {
element.isDisplayed().then(function (displayed) {
if (displayed) {
dfd.resolve();
}
else if (Number(new Date()) < endTime) {
setTimeout(poll, 500);
}
else {
var error = new Error('timed out; final url is ' + url);
dfd.reject(error);
}
});
})();
return dfd.promise;
}
You've probably had an answer to this by now but here's my solution to this just in case you're still unsure or if anyone else comes across this issue.
I'm not sure why you are polling until an element is visible here. What I would do is set the find timeout of your leadfoot/Session as follows:
this.remote.setFindTimeout(60000)
Then when you invoke the this.remote.findByXPath method, it will automatically search for your element for a maximum of 1 minute (in the case of my above example). If it finds the element within that time, it will then proceed to the next step in your code. If it doesn't find the element within that time, the test case will time out.
You can then simplify your code to (for example):
this.remote
.setFindTimeout(60000)
.findByXpath("//div[#data-index='blockContainer']/button[text()='Create new']")
.click()
.end();
Of course there's no need to set the find timeout every time you wish to find an element in the UI. You can set it once somewhere more appropriate (ie. at the beginning of your test) and it will remain in place for the duration of your test. I'm just doing it here as a means of documenting a full example for you.
Hope this helps!

understanding node.js callback structure

I am working on really simple node.js projects to better understand its callback functioning.
Suppose I have a login "system" like this one here:
if( req.query["username"] == "john" && req.query["password"] == "smith" ) {
req.session.gatekeeper = req.query["username"];
res.end( "succesfully logged in" );
} else { res.end( "wrong username or password" ); }
so far, so easy. Now suppose that instead of simply having "john:smith", I'd have it stored on redis. With PHP I'd have done it this way:
if( $r->get("$usernameIn") == $passwordIn ) {
$_SESSION['gatekeeper'] = $usernameIn;
echo "succesfully logged in";
}
but now, by having a look at the redis documentation (https://github.com/mranney/node_redis/) for node, I see that the get command is like this:
client.get("foo", function(err, reply) {
console.log(reply);
});
It is really complicated for me to understand how to "structure" the first code I provided with this last one.
Any help? Thanks in advance.
Nearly everything in node.js is asynchronous. So, nearly every method that is called, you must specify a callback method to handle the result of the method call. Normally, the callback function takes two parameters: error, result. So it is up to you to check for the error and then handle the result. There are other node modules that will allow for cleaner code (node promises), but that is out of scope for your question.
As a disclaimer I have not used redis before, so my code example below is based on your code example from above and a quick overview of the redis node.js module.
var redis = require("redis"),
client = redis.createClient();
client.on("connect", function () {
client.get(userName, function(err,returnedPassword){
if(password === returnedPassword) {
req.session.gatekeeper = req.query["username"];
res.end( "succesfully logged in" );
} else {
res.end( "wrong username or password" );
}
});
});

How to make chrome.tabs.update works with content script

I work on a little extension on Google Chrome, I want to create a new tab, go on the url "sample"+i+".com", launch a content script on this url, update the current tab to "sample"+(i+1)+".com", and launch the same script. I looked the Q&A available on stackoverflow and I google it but I didn't found a solution who works. This is my actually code of background.js (it works), it creates two tabs (i=21 and i=22) and load my content script for each url, when I tried to do a chrome.tabs.update Chrome launchs directly a tab with i = 22 (and the script works only one time) :
function extraction(tab) {
for (var i =21; i<23;i++)
{
chrome.storage.sync.set({'extraction' : 1}, function() {}); //for my content script
chrome.tabs.create({url: "http://example.com/"+i+".html"}, function() {});
}
}
chrome.browserAction.onClicked.addListener(function(tab) {extraction(tab);});
If anyone can help me, the content script and manifest.json are not the problem. I want to make that 15000 times so I can't do otherwise.
Thank you.
I guess chrome.tabs.create is an async function so you need to create a separate function so that the i variable is copied each time:
try this:
var func = function(i)
{
chrome.storage.sync.set({'extraction' : 1}, function() {}); //for my content script
chrome.tabs.create({url: "http://example.com/"+i+".html"}, function() {});
}
function extraction(tab) {
for (var i =21; i<23;i++)
{
func(i);
}
}
chrome.browserAction.onClicked.addListener(function(tab) {extraction(tab);});
You need to make sure that the tab finished loading, and that your content script finished running, before updating the tab to the next url. One way to achieve that would be by sending a message from the content script to the background page. You can include the following in your content script:
chrome.extension.sendMessage("finished");
In your background script you can do the following:
var current = 21, end = 23;
chrome.extension.onMessage.addListener(
function(request, sender) {
if( request == "finished" && current <= end ) {
chrome.tabs.update( sender.tab.id,
{url: "http://example.com/"+current+".html"});
current++;
}
}
);
chrome.tabs.create({url: "http://example.com/"+current+".html"});

How to tell if a script is run as content script or background script?

In a Chrome extension, a script may be included as a content script or background script.
Most stuff it does is the same, but there are some would vary according to different context.
The question is, how could a script tell which context it is being run at?
Thank you.
I think this is a fairly robust version that worked in my initial tests and does not require a slower try catch, and it identifies at least the three primary contexts of a chrome extension, and should let you know if you are on the base page as well.
av = {};
av.Env = {
isChromeExt: function(){
return !!(window['chrome'] && window['chrome']['extension'])
},
getContext: function(){
var loc = window.location.href;
if(!!(window['chrome'] && window['chrome']['extension'])){
if(/^chrome/.test(loc)){
if(window == chrome.extension.getBackgroundPage()){
return 'background';
}else{
return 'extension';
}
}else if( /^https?/.test(loc) ){
return 'content';
}
}else{
return window.location.protocol.replace(':','');
}
}
};
Well I managed to work out this:
var scriptContext = function() {
try {
if (chrome.bookmarks) {
return "background";
}
else {
return "content";
}
}
catch (e) {
return "content";
}
}
It's because an exception would be thrown if the content script tries to access the chrome.* parts except chrome.extension.
Reference: http://code.google.com/chrome/extensions/content_scripts.html
The best solution I've found to this problem comes from over here.
const isBackground = () => location.protocol === 'chrome-extension:'
The background service worker at Manifest v3 does not contain a window.
I use this as part of my extension error handling which reloads the content scripts, when i receive an Extension context invalidated error:
...
if (!self.window) {
console.warn('Background error: \n', error);
} else {
location.reload();
}
...

Resources