I have just started my journey with Python and am just amazed at how much one can do in less than 50 lines of code.
I got stuck, however, writing an app which is to:
connect with a web site
log in using my credentials
fill a form
choose a link from the results returned by the form
use the link to confirm an appointment
use the link to book an appointment
I went all the way through but got stuck at point 6 above. Maybe this is due to something going wrong at point 5, so please let me start with what happens in step 4 :-).
I enter step 4 with the form site generating a list of available appointments. Those are links attached to buttons, like:
<a class="button strong" href="/your_account/confirm?CityId=500&VisitId=42204&HasReferral=False" target="popup"> click to book </a>
NOTE: the button opens a pop-up.
I use BeatifulSoup to pick one of the links, then I convert it to a dictionary
entry = {'CityId' : '500',
'VisitId' : '42204',
'HasReferral' : 'False'}
In step 5 I continue a session which I had created with Python's requests module and POST:
a = my_session.post( 'https://the_website.com/your_account/confirm', data = entry)
What is returned in the a object is the pop-up. In the the pop-up's code there is a function and a button, like the ones below:
accept = function () {
if (canRedirect()) {
var url = '/your_account/reserve?key=55924c2b-9b30-4714-ad6c-8f47c72893cd';
$.post(url, function(html) {
$("#dynamicReservationDivCntainer").html(html);
});
}
};
<button onclick="accept()" id="okButton" class="button strong right reserveConfirmButton">Click here to hit the deal</button>
So here is the step 6 and my problem. When I extract the site address and key from a.text, like in step 5 and POST it:
key_dict = {'key' : '55924c2b-9b30-4714-ad6c-8f47c72893cd'}
b = my_session.post( 'https://the_website.com/your_account/reserve', data = key_dict )
It turns out that b contains a site with something like : "Failure. The key already exists in the database. Please enter another key." and nothing gets booked.
Ah, please let me know if I missed something important in the story. I tried to extract what I believe is the crux of the matter and am afraid I may have oversimplified.
Related
This question already has answers here:
How can I get form data with JavaScript/jQuery?
(31 answers)
Closed 10 months ago.
I'm trying to create an HTML/JS action "choose your zip code from a list." If the user's zip code is found, they are brought to a form that collects their contact info and once the form is completed - is emailed to the form's administrator.
If the zip code isn't present, they are shown a window that says 'sorry, try here [insert URL here] instead.
This question is a bit redundant, because you're pretty much asking us to build the entire app for you, but you can validate zip codes like this:
const validZipCodes = ['000000']
const zipCode = document.getElementById('zipcode').textContent;
if (validZipCodes.includes(zipCode)) {
// Valid, now redirect
window.location = '/info' // any other link
} else {
// Maybe add custom alert
alert('Invalid zip code!');
}
My answer took to long but it's worthile to share anyway...
This is a demo showing the concept you asked for in your question.
Anyway if we want to discuss your idea there are some weak points. The list of allowed zips is no secret and is embedded on the page. Is it a critical leak? Do you want the list to be dynamic and served externally? you might do an ajax request here to feed that list but yet its logic would be transparent and easy to temper. Or you could use this form just as a messenger where it just forward your input to a service like tellMeIfThisZipIsAllowed(zip) so that the logic won't be known publicly but here you'd just need to collect the input, call the ajax function and do the redirect if its response is positive. But yet the redirect address would be known so you would be forced to check again the zip inside that step and kickout the user in case the zip isn't valid. Yet another weak approach. So the point is why do you need this frontpage before the rest of the registration and if its security measure should be hard to bypass or not.
So to make sure you understand that warning, you should really validate that zip inside the action following the next step (server side).
const allowed_zips = ['12345', '00000', '90210'];
function checkZip(){
document.querySelectorAll('.msg').forEach((o,i)=>{o.remove();});
const zip = document.getElementById('zip');
const msg = document.createElement('div');
msg.classList.add('msg');
if( allowed_zips.includes(zip.value) ){
msg.innerText = `Your Zip is valid.. redirecting to next step`;
}
else{
msg.innerText = `Your Zip is invalid`;
}
zip.after(msg);
//here we are redirecting to next step of registration form
//but I would recommend to pass the zip to it for further inspection
//like here through GET or using a different strategy with an hidden form
//to submit a POST action.
//window.location.href = "path/to/next/url?zip=${zip.value}";
}
<input id="zip" type="text" placeholder="Insert your zip code...">
<button type="button" onclick="checkZip();">Next step</button>
I am trying to create an apify crawler, which has multiple clickable element. First click is to paginate, second click to visit each result, third is to visit a section of each result to extract more information.
function pageFunction(context) {
var $ = context.jQuery;
if (context.request.label === 'category'|| context.request.label === 'detail') {
context.skipLinks();
var result = {
item_name: $('name').text(),
categories: $('.categories').text(),
email: $('email').text(),
kvk: $('kvk').text()
};
return result;
} else {
context.skipOutput();
}
}
The first 2 clicks are happening, it paginates and visits the results and extract first 3 values : item_name, categories and email
The fourth value : kvk is not returned. I think either the third click is not happening or the code I used have some errors. Can anyone please help me to fix this?
One of the problems can the context.skipLinks() a function that prevents any new enqueued pages. Also, did you check all the selectors in the developer console? For debugging I would advise you to log the content of the page so you know it loaded. First, you need to find the source of the problem.
ONe side note, I would advice you to start developing is our modern web-scraper. Crawler platform is no longer maintained and may perform worse for some cases.
I'm trying to create a basic time clock web app.
So far, I'm using this script to create this web app which takes the input values and puts them in this spreadsheet for the time stamping part.
I need it to use one of the values from the form and perform a lookup in this sheet (take the longId and find me the name) and return the (name) value to the html page as a verification for the end user that they were identified correctly. Unfortunately, I don't know enough to grasp what I'm doing wrong. Let me know if I need to provide more info.
Edit 1
I'm thinking that I wasn't clear enough. I don't need the user info from entry, I need the user from a lookup. The user will be entering their ID anonymously, I need to match the ID to their info, and bring the info back for them to verify.
Edit 2
Using the link provided by Br. Sayan, I've created this script using this spreadsheet as above to test one piece of this. The web app here spits out: undefined. It should spit out "Student 3" Still not sure what I'm doing wrong.
One way for the next button to grab the student input field:
<input type="submit" onclick="studentName(document.getElementById('student').value)" value="Next..."/>
That sends the value to this func in Javascript.html:
function studentName(value) {
google.script.run
.withSuccessHandler(findSuccess)
.findStudent(value);
}
Which sends it to a findStudent(value) in Code.gs
You do the lookup and the return value goes back to findSuccess( result ) back in Javascript.html. Handle the result from there.
Also consider keeping the stock preventDefault() code that comes with the Web App template in the Help > Welcome Screen.
Please try this one:
(source: technokarak.com)
Also please have a look at:
Retrieve rows from spreadsheet data using GAS
EDIT:
Please make these changes in your function and let us know.
function findValue() {
var data = SpreadsheetApp.openById("15DRZRQ2Hcd7MNnAsu_lnZ6n4kiHeXW_OMPP3squbTLE").getSheetByName("Volatile Data").getDataRange().getValues();
for(i in data) {
if(data[i][3] == 100000003) {
Logger.log("yes");
Logger.log(data[i][0]);
var student = [];
student.push(data[i][0]);
return student;
}
}
}
It is a complicated answer, I have had a lot of success with:
function process(object){
var user = Session.getActiveUser().getEmail();
var key = object.Key;
send(key);
}
function send(k){
var ss =
SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lastR = ss.GetLastRow();
ss.GetRange(lastR,1).SetValue(k);
}
On your html button you will need to have inside the tags
onClick="google.script.run
.withSuccessHandler(Success)
.process(this.parentNode);"
In order for this to work, obviously you will need to have your fields named accordingly.
Edit: The only thing I did not include in the code was a Success handler, which will be in your html of the GAS script. This should point you in a direction that can resolve that.
Hope this helps.
Hello I have a small website where data is passed between pages over URL.
My question is can someone break into it and make it pass the same data always?
For example let say, when you click button one, page below is loaded.
example.com?clicked=5
Then at that page I take value 5 and get some more data from user through a form. Then pass all the data to a third page. In this page data is entered to a database. While I observe collected data I saw some unusual combinations of records. How can I verify this?
yes. as javascript is open on the website, everyone can hack it.
you will need to write some code on you backend to validade it.
always think that you user/costumer will try to hack you sytem.
so take precautions like, check if user is the user of the session, if he is logged, if he can do what he is trying to do. check if the record that he is trying get exists.
if u are using a stand alone site, that u made the entire code from the ashes, you will need to implement this things by yourself.
like using the standard php session, making the data validation etc.
or you can find some classes that other people have made, you can find a lot o this on google. as it is a common problem of web programing.
if u are using a backed framework that isnt from another world, probably already has one. sp, go check its documentation.
html:
<a id = 'button-one' name = '5'> Button One </a>
javascript:
window.onload = function() {
document.getElementById('button-one').onclick = function() {
changeURL(this.attributes.name.value);
};
};
function changeURL(data) {
location.hash = data;
}
i developed a simply.js app that fetches bus arrival time from a webservice, problem is that as of now it work only for one stop.
i want to create a configuration page with a multiselect where i could choose multiple stops , sending them to the pebble as an array and at the press of up/down buttons i want to cycle the array to show different bus stops.
Im not good in C, i prefere javascript thats because i used simply.js.
id like to know and learn how to do it, because i think online there isnt much documentation and examples.
Found a similar question/ issue at simply.js github page https://github.com/Meiguro/simplyjs/issues/11. The code example below comes from Meiguros first answer. The code sends the user to your configuration website, which you should configure to send json back.
You can probably copy the code example for enabling the configuration window and paste it in the begining of your main pebble app.js file. Do not forget to add "capabilities": [ "configurable" ], in your appinfo.json file. If you are using cloudpebble you should go to the settings page of your app and make sure the configurable box is checked.
var initialized = false;
Pebble.addEventListener("ready", function() {
console.log("ready called!");
initialized = true;
});
Pebble.addEventListener("showConfiguration", function() {
console.log("showing configuration");
//change this url to yours
Pebble.openURL('http://assets.getpebble.com.s3-website-us-east-1.amazonaws.com/pebble-js/configurable.html');
});
Pebble.addEventListener("webviewclosed", function(e) {
console.log("configuration closed");
// webview closed
var options = JSON.parse(decodeURIComponent(e.response));
console.log("Options = " + JSON.stringify(options));
});
(https:// github.com/pebble-hacks/js-configure-demo/blob/master/src/js/pebble-js-app.js - remove space after https://)
To then push the settings back to the pebble i think you need to add
Pebble.sendAppMessage(options);
just before
console.log("configuration closed");
// webview closed
I found this out at the last post on this pebble forum thread http://forums.getpebble.com/discussion/12854/appmessage-inbox-handlers-not-getting-triggered-by-javascript-configuration-data
You can aslo find a configuration website example named configurable.html in the same git as the code example at https:// github.com/pebble-hacks/js-configure-demo remove space after https://
Hope this helps a bit on the way to achieving your goal
So the configuration page is a web page, and you can host it and provide your URL as mentioned by Ankan above.
Like this:
Pebble.openURL('http://assets.getpebble.com.s3-website-us-east-1.amazonaws.com/pebble-js/configurable.html');
Lets say you decide to take the name and age of the user in the configuration page, you would have two text fields for them to enter their information, then you would have a submit button. For the submit button write a javascript function which uses jQuery to take the values of the text fields onclick, then save those values to a variable, and use JSON to send them to the phone. Here is an example of a fully created configuration web page: https://github.com/pebble-hacks/js-configure-demo
Enjoy.