Comments (7)
Quick update:
So I've figured out that sending the following HTTP Request message will email the user for confirmation, i've marked where to put the email with the ###EMAIL###
token:
Verb: POST
Address: https://www.opentable.com/dapi/fe/gql?optype=mutation&opname=SendVerificationCodeEmail
Headers:
Origin: https://www.opentable.com
Referer: https://www.opentable.com/authenticate/start?isPopup=true&rp=https%3A%2F%2Fwww.opentable.com%2F&srs=1&isFromBookingFlow=false
x-csrf-token: 2e96d1b2-400c-4b31-9a35-1b978d67501a
x-query-timeout: 2000
Body:
{
"operationName":"SendVerificationCodeEmail",
"variables":{
"verifyEmail":false,
"email":"###EMAIL###",
"loginType":"popup-redirect",
"requestedAction":"https://www.opentable.com/",
"path":"https://www.opentable.com/"
},
"extensions":{
"persistedQuery":{
"sha256Hash":"b2d378ab902bfbc650cc50fe6e20415c9ce3803c9a82fe830f7834ef31c403fe"
}
}
}
It appears the header x-csrf-token: 2e96d1b2-400c-4b31-9a35-1b978d67501a
and the value "sha256Hash":"b2d378ab902bfbc650cc50fe6e20415c9ce3803c9a82fe830f7834ef31c403fe"
must be used to authenticate the request, and I've tested that these particular values can be re-used for different emails. x-query-timeout
can be set to arbitrary values and can still work, but must be set to some value for the request to work.
The server will respond with a message with the following body:
{
"data": {
"sendVerificationCodeEmail": {
"correlationId": "e4cbea19-cdcd-4502-b965-78b1d14a33cd",
"tooManyRequests": false,
"__typename": "SendVerificationCodeResult"
}
},
"loading": false,
"networkStatus": 7
}
The "correlationId": "e4cbea19-cdcd-4502-b965-78b1d14a33cd"
field is a unique identifier that must be used in later requests to link the verification code with this login session, and it changes value on each send of the above request. The "tooManyRequests": false
field indicates when the server will block the client due to excessive requesting. This block is short-term.
from resolved-bot.
After the request in the above is sent, two further requests must be made. First, a request must be made of content type x-protobuffer
that I'm still looking into, although I believe this request sends a long byte string to a google service in order to compute some sort of CAPTCHA token. I haven't found a way to send this in postman, but in firefox this packet can be sent with a few authentication values that I've recorded in order to obtain a new CAPTCHA token. For the next request, we need the CAPTCHA Token. After that is retrieved, we may send the following request, with the token ###CAPTCHA###
where the previously obtained CAPTCHA token should go, the token ###COID###
where the correlationId
field value should go from the previous server response, the token ###EMAIL###
where the user email should go, and the token ###CODE###
where the confirmation code from the email should go.
Verb: POST
Address: https://www.opentable.com/dapi/fe/proxy/authentication-consumer-backend/authentication/start-passwordless-login
Headers:
Origin: https://www.opentable.com
Referer: https://www.opentable.com/authenticate/verify-medium?isPopup=true&rp=https%3A%2F%2Fwww.opentable.com%2F&srs=1&isFromBookingFlow=false
x-csrf-token: c6f3e69c-23af-4e96-8cf5-372b7d66a0e1
Body:
{
"email":"###EMAIL###",
"correlationId":"###COID###",
"verificationCode":"###CODE###",
"loginContextToken":"{\"loginType\":\"popup-redirect\",\"requestedAction\":\"https://www.opentable.com/\"}",
"recaptchaToken":"###CAPTCHA###",
"tld":"com",
"databaseRegion":"na",
"checkExistingEmailEnabled":true
}
from resolved-bot.
Just looked into the above, and it appears one does not even need to login to make a reservation on open table, so while the above info is useful, we do not need it.
from resolved-bot.
It appears the sha256Hash field values are analagous to API Keys, but they work depending on the requested function. So logging in has its own sha256Hash key, searching has its own key, and reserving has its own key
from resolved-bot.
Working on the search function right now, and managed to get through to the opentable servers on go. Please note, there's some funky behavior with how the opentable servers handle the user-agent
header. You must include it, but it doesn't actually have to have anything in it, so feel free to set it to the empty string
from resolved-bot.
Quick Note:
The following HTTP message can be used to find metadata in order to prepare a reservation. I use the token ###RID###
to denote where the venueID should go, ###RESD###
where the reservation day should go, ###REST###
where the reservation time should go , ###PS###
where the party size should go, and ###XTOK###
where the x-csrf-token should go:
Verb: POST
Address: https://www.opentable.com/dapi/fe/gql?optype=query&opname=RestaurantsAvailability
Headers(on top of normal headers):
x-csrf-token: ###XTOK###
Body:
{
"operationName": "RestaurantsAvailability",
"variables": {
"onlyPop": false,
"forwardDays": 0,
"requireTimes": false,
"requireTypes": [],
"restaurantIds": [
###RID###
],
"date": "###RESD###",
"time": "###REST###",
"partySize": ###PS###,
"databaseRegion": "NA"
},
"extensions": {
"persistedQuery": {
"version": 1,
"sha256Hash": "e6b87021ed6e865a7778aa39d35d09864c1be29c683c707602dd3de43c854d86"
}
}
}
This will trigger a response from the server with the following example body:
Body:
{
"data": {
"availability": [
{
"restaurantId": 1287013,
"restaurantAvailabilityToken": "eyJ2IjoyLCJtIjowLCJwIjowLCJzIjowLCJuIjowfQ",
"availabilityDays": [
{
"noTimesReasons": [],
"earlyCutoff": null,
"sameDayCutoff": null,
"dayOffset": 0,
"allowNextAvailable": true,
"topExperience": null,
"slots": [
{
"isAvailable": true,
"timeOffsetMinutes": -60,
"slotHash": "3120410745",
"pointsType": "Standard",
"pointsValue": 100,
"experienceIds": [],
"slotAvailabilityToken": "eyJ2IjoyLCJtIjowLCJwIjowLCJjIjo2LCJzIjowLCJuIjowfQ",
"attributes": [
"highTop"
],
"isMandatory": false,
"isMandatoryBySeating": [
{
"tableCategory": "highTop",
"isMandatory": false,
"__typename": "IsMandatoryBySeating"
}
],
"experiencesBySeating": [],
"redemptionTier": "GreatDeal",
"type": "Standard",
"__typename": "AvailableSlot"
},
{
"isAvailable": true,
"timeOffsetMinutes": -30,
"slotHash": "283703391",
"pointsType": "Standard",
"pointsValue": 100,
"experienceIds": [],
"slotAvailabilityToken": "eyJ2IjoyLCJtIjowLCJwIjowLCJjIjo2LCJzIjowLCJuIjowfQ",
"attributes": [
"highTop"
],
"isMandatory": false,
"isMandatoryBySeating": [
{
"tableCategory": "highTop",
"isMandatory": false,
"__typename": "IsMandatoryBySeating"
}
],
"experiencesBySeating": [],
"redemptionTier": "GreatDeal",
"type": "Standard",
"__typename": "AvailableSlot"
},
{
"isAvailable": true,
"timeOffsetMinutes": 0,
"slotHash": "1620779529",
"pointsType": "Standard",
"pointsValue": 100,
"experienceIds": [],
"slotAvailabilityToken": "eyJ2IjoyLCJtIjowLCJwIjowLCJjIjo2LCJzIjowLCJuIjowfQ",
"attributes": [
"highTop"
],
"isMandatory": false,
"isMandatoryBySeating": [
{
"tableCategory": "highTop",
"isMandatory": false,
"__typename": "IsMandatoryBySeating"
}
],
"experiencesBySeating": [],
"redemptionTier": "GreatDeal",
"type": "Standard",
"__typename": "AvailableSlot"
},
{
"isAvailable": true,
"timeOffsetMinutes": 15,
"slotHash": "335170686",
"pointsType": "Standard",
"pointsValue": 100,
"experienceIds": [],
"slotAvailabilityToken": "eyJ2IjoyLCJtIjowLCJwIjowLCJjIjo2LCJzIjowLCJuIjowfQ",
"attributes": [
"highTop"
],
"isMandatory": false,
"isMandatoryBySeating": [
{
"tableCategory": "highTop",
"isMandatory": false,
"__typename": "IsMandatoryBySeating"
}
],
"experiencesBySeating": [],
"redemptionTier": "GreatDeal",
"type": "Standard",
"__typename": "AvailableSlot"
},
{
"isAvailable": true,
"timeOffsetMinutes": 30,
"slotHash": "142556990",
"pointsType": "Standard",
"pointsValue": 100,
"experienceIds": [],
"slotAvailabilityToken": "eyJ2IjoyLCJtIjowLCJwIjowLCJjIjo2LCJzIjowLCJuIjowfQ",
"attributes": [
"highTop"
],
"isMandatory": false,
"isMandatoryBySeating": [
{
"tableCategory": "highTop",
"isMandatory": false,
"__typename": "IsMandatoryBySeating"
}
],
"experiencesBySeating": [],
"redemptionTier": "GreatDeal",
"type": "Standard",
"__typename": "AvailableSlot"
}
],
"__typename": "AvailabilityDay"
}
],
"__typename": "RestaurantAvailability"
}
]
},
"loading": false,
"networkStatus": 7
}
Each entry in the "availabilityDays"
data array represents metadata for a time slot, with the "timeOffsetMinutes"
field value representing the difference between the time for that slot and the requested time, the "isAvailable"
field value representing whether the slot is free, and the "slotHash"
and "slotAvailabilityToken"
being used to identify the slot in the next request for finalizing the reservation
from resolved-bot.
Closed with recent PR
from resolved-bot.
Related Issues (14)
- [FEATURE]: Change AppCtx to handle multiple API objects HOT 3
- [FEATURE]: Improve documentation HOT 4
- [INFO]: Architecture Overview
- [INFO]: Documentation Etiquette HOT 1
- [BUG]: Login Crash with no payment account
- [BUG]: Crash on no resvervations for a given day
- [FEATURE]: Early Authentication + api.Time replacement HOT 1
- [FEATURE]: Captcha Cracking for Resy API HOT 5
- [FEATURE]: An option to specify table type HOT 4
- [BUG]: "unknown network error" when attempting to get reservation HOT 4
- [BUG]: bot not firing? HOT 5
- [BUG]: Unknown Network Error HOT 1
- [INFO]: Bot will be down for at least three weeks HOT 10
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from resolved-bot.