jeangnc / us-visa-bot

US Visa Bot
MIT License
140 stars 30 forks source link

Cookies null #24

Open xamoko opened 4 months ago

xamoko commented 4 months ago

function parseCookies(cookies) not received datas, return null

jenzkupinc commented 4 months ago

lo mismo aqui, doesnt bring it back !Even when extracted from the official page, it doesn't work. It throws a forbidden error and 401,403 got that.

xamoko commented 4 months ago

lo mismo aqui, doesnt bring it back !Even when extracted from the official page, it doesn't work. It throws a forbidden error and 401,403 got that.

pudiste hacerlo funcionar en la parte de las cookies???

jenzkupinc commented 4 months ago

No funciona. . .

xamoko commented 4 months ago

No funciona. . .

ok, manos a la obra XD

jenzkupinc commented 4 months ago

Que tiene en mente?

///////////////////////////////////////////////////////

async function extractHeaders(res, htmlContent) { try {

const csrfTokenMatch1 = htmlContent.match(/<meta\s+name=["']csrf-token["']\s+content=["']([^"']+)["']/);
const csrfTokenMatch2 = htmlContent.match(/<meta\s+nombre=["']csrf-token["']\s+contenido=["']([^"']+)["']/);

const csrfTokenMatch = csrfTokenMatch1 || csrfTokenMatch2;
if (!csrfTokenMatch || csrfTokenMatch.length < 2) {
  throw new Error("No se encontró el CSRF-Token en el contenido HTML.");
}
const csrfToken = csrfTokenMatch[1];
const cookiesHeader = res.headers.get('set-cookie');

if (!cookiesHeader) {
  throw new Error("No se encontraron las cookies en los encabezados de la respuesta.");
}

const parsedCookies = parseCookies(cookiesHeader);
const cookieHeaderValue = `_yatri_session=${parsedCookies['_yatri_session']}`;

return {
  "Cookie": cookieHeaderValue,
  "X-CSRF-Token": csrfToken,
  "Referer": BASE_URI,
  "Referrer-Policy": "strict-origin-when-cross-origin",
  'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
  'Cache-Control': 'no-store',
  'Connection': 'keep-alive'
};

} catch (error) { throw new Error("No se pueden extraer los encabezados necesarios: " + error.message); } }

function parseCookies(cookies) { const parsedCookies = {};

if (!cookies) { return parsedCookies; } cookies.split(';').map(c => c.trim()).forEach(c => { const [name, value] = c.split('=', 2); parsedCookies[name] = value; });

return parsedCookies; }

xamoko commented 4 months ago

intentare reescribirlo, hay unos que están en python y al menos a mi me falla al obtener las cookies, entonces ire revisando cada error a ver si llego a la solución

jenzkupinc commented 4 months ago

suerte bro! tengamos fe que funcionará

jenzkupinc commented 4 months ago

como te fue? no hay solucion . . me canse de buscar solucion

xamoko commented 4 months ago

como te fue? no hay solucion . . me canse de buscar solucion

Sigo reescribiendo

kaganatalay commented 4 months ago

Was facing the same issue, I resolved it by adding the following headers to line 53, where the script attempts to fetch anonymous headers.

const anonymousHeaders = await fetch(`${BASE_URI}/users/sign_in`, {
    headers: {
      "User-Agent": "",
      "Accept": "*/*",
      "Accept-Encoding": "gzip, deflate, br",
      "Connection": "keep-alive",
    },
  })

Submitted this as a PR, hopefully gets merged soon.

jenzkupinc commented 4 months ago

Was facing the same issue, I resolved it by adding the following headers to line 53, where the script attempts to fetch anonymous headers.

const anonymousHeaders = await fetch(`${BASE_URI}/users/sign_in`, {
    headers: {
      "User-Agent": "",
      "Accept": "*/*",
      "Accept-Encoding": "gzip, deflate, br",
      "Connection": "keep-alive",
    },
  })

Submitted this as a PR, hopefully gets merged soon.

same thing i guess, or should we have to rewrite into useragentr and accept?

xamoko commented 4 months ago

Was facing the same issue, I resolved it by adding the following headers to line 53, where the script attempts to fetch anonymous headers.

const anonymousHeaders = await fetch(`${BASE_URI}/users/sign_in`, {
    headers: {
      "User-Agent": "",
      "Accept": "*/*",
      "Accept-Encoding": "gzip, deflate, br",
      "Connection": "keep-alive",
    },
  })

Submitted this as a PR, hopefully gets merged soon.

I've resolved this issue and modify login function, now this function looked like this

"async function login() { const anonymousHeaders = await fetch(${BASE_URI}/users/sign_in,{ method: 'GET', credentials: 'same-origin', redirect: 'follow', agent: null, headers: { "Content-Type": "text/plain", "Referrer-Policy": "strict-origin-when-cross-origin", 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36', 'Cache-Control': 'no-store', 'Connection': 'keep-alive' },}) .then(response => extractHeaders(response))

return fetch(${BASE_URI}/users/sign_in, { "headers": Object.assign({}, anonymousHeaders, { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", }), "method": "POST", "body": new URLSearchParams({ 'utf8': '✓', 'user[email]': USERNAME, 'user[password]': PASSWORD, 'policy_confirmed': '1', 'commit': 'Accessar' }), }) .then(res => ( Object.assign({}, anonymousHeaders, { 'Cookie': extractRelevantCookies(res) }) )) }"

xamoko commented 4 months ago

Was facing the same issue, I resolved it by adding the following headers to line 53, where the script attempts to fetch anonymous headers.

const anonymousHeaders = await fetch(`${BASE_URI}/users/sign_in`, {
    headers: {
      "User-Agent": "",
      "Accept": "*/*",
      "Accept-Encoding": "gzip, deflate, br",
      "Connection": "keep-alive",
    },
  })

Submitted this as a PR, hopefully gets merged soon.

same thing i guess, or should we have to rewrite into useragentr and accept?

after fix that, you had problem whit function checkAvailableDate(head)????

jenzkupinc commented 4 months ago

correcto esta solucionado juntos con su ayuda.

!/usr/bin/env node

import fetch from "node-fetch"; import cheerio from 'cheerio';

const USERNAME = process.env.USERNAME const PASSWORD = process.env.PASSWORD const SCHEDULE_ID = process.env.SCHEDULE_ID const FACILITY_ID = process.env.FACILITY_ID

const BASE_URI = 'https://ais.usvisa-info.com/es-es/niv'

async function main(currentBookedDate) { if (!currentBookedDate) { log(Invalid current booked date: ${currentBookedDate}) process.exit(1) }

log(Initializing with current date ${currentBookedDate})

try { const sessionHeaders = await login()

while(true) {
  const date = await checkAvailableDate(sessionHeaders)

  if (!date) {
    log("no dates available")
  } else if (date > currentBookedDate) {
    log(`nearest date is further than already booked (${currentBookedDate} vs ${date})`)
  } else {
    currentBookedDate = date
    const time = await checkAvailableTime(sessionHeaders, date)

    book(sessionHeaders, date, time)
      .then(d => log(`booked time at ${date} ${time}`))
  }

  await sleep(3)
}

} catch(err) { console.error(err) log("Trying again")

main(currentBookedDate)

} }

async function login() { const anonymousHeaders = await fetch(${BASE_URI}/users/sign_in, { method: 'GET', credentials: 'same-origin', redirect: 'follow', agent: null, headers: { "Content-Type": "text/plain", "Referrer-Policy": "strict-origin-when-cross-origin", 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36', 'Cache-Control': 'no-store', 'Connection': 'keep-alive' } }).then(response => extractHeaders(response));

return fetch(${BASE_URI}/users/sign_in, { "headers": Object.assign({}, anonymousHeaders, { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", }), "method": "POST", "body": new URLSearchParams({ 'utf8': '✓', 'user[email]': USERNAME, 'user[password]': PASSWORD, 'policy_confirmed': '1', 'commit': 'Accessar' }), }) .then(res => ( Object.assign({}, anonymousHeaders, { 'Cookie': extractRelevantCookies(res) }) )); }

function checkAvailableDate(headers) { return fetch(${BASE_URI}/schedule/${SCHEDULE_ID}/appointment/days/${FACILITY_ID}.json?appointments[expedite]=false, { "headers": Object.assign({}, headers, { "Accept": "application/json", "X-Requested-With": "XMLHttpRequest", }), "cache": "no-store" }) .then(r => r.json()) .then(r => handleErrors(r)) .then(d => d.length > 0 ? d[0]['date'] : null)

}

function checkAvailableTime(headers, date) { return fetch(${BASE_URI}/schedule/${SCHEDULE_ID}/appointment/times/${FACILITY_ID}.json?date=${date}&appointments[expedite]=false, { "headers": Object.assign({}, headers, { "Accept": "application/json", "X-Requested-With": "XMLHttpRequest", }), "cache": "no-store", }) .then(r => r.json()) .then(r => handleErrors(r)) .then(d => d['business_times'][0] || d['available_times'][0]) }

function handleErrors(response) { const errorMessage = response['error']

if (errorMessage) { throw new Error(errorMessage); }

return response }

async function book(headers, date, time) { const url = ${BASE_URI}/schedule/${SCHEDULE_ID}/appointment

const newHeaders = await fetch(url, { "headers": headers }) .then(response => extractHeaders(response))

return fetch(url, { "method": "POST", "redirect": "follow", "headers": Object.assign({}, newHeaders, { 'Content-Type': 'application/x-www-form-urlencoded', }), "body": new URLSearchParams({ 'utf8': '✓', 'authenticity_token': newHeaders['X-CSRF-Token'], 'confirmed_limit_message': '1', 'use_consulate_appointment_capacity': 'true', 'appointments[consulate_appointment][facility_id]': FACILITY_ID, 'appointments[consulate_appointment][date]': date, 'appointments[consulate_appointment][time]': time, 'appointments[asc_appointment][facility_id]': '', 'appointments[asc_appointment][date]': '', 'appointments[asc_appointment][time]': '' }), }) }

async function extractHeaders(res) { const cookies = extractRelevantCookies(res)

const html = await res.text() const $ = cheerio.load(html); const csrfToken = $('meta[name="csrf-token"]').attr('content')

return { "Cookie": cookies, "X-CSRF-Token": csrfToken, "Referer": BASE_URI, "Referrer-Policy": "strict-origin-when-cross-origin", 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36', 'Cache-Control': 'no-store', 'Connection': 'keep-alive' } }

function extractRelevantCookies(res) { const parsedCookies = parseCookies(res.headers.get('set-cookie')) return _yatri_session=${parsedCookies['_yatri_session']} }

function parseCookies(cookies) { const parsedCookies = {}

cookies.split(';').map(c => c.trim()).forEach(c => { const [name, value] = c.split('=', 2) parsedCookies[name] = value })

return parsedCookies }

function sleep(s) { return new Promise((resolve) => { setTimeout(resolve, s * 1000); }); }

function log(message) { console.log([${new Date().toISOString()}], message) }

const args = process.argv.slice(2); const currentBookedDate = args[0] main(currentBookedDate)

xamoko commented 4 months ago

correcto esta solucionado juntos con su ayuda.

!/usr/bin/env node

import fetch from "node-fetch"; import cheerio from 'cheerio';

const USERNAME = process.env.USERNAME const PASSWORD = process.env.PASSWORD const SCHEDULE_ID = process.env.SCHEDULE_ID const FACILITY_ID = process.env.FACILITY_ID

const BASE_URI = 'https://ais.usvisa-info.com/es-es/niv'

async function main(currentBookedDate) { if (!currentBookedDate) { log(Invalid current booked date: ${currentBookedDate}) process.exit(1) }

log(Initializing with current date ${currentBookedDate})

try { const sessionHeaders = await login()

while(true) {
  const date = await checkAvailableDate(sessionHeaders)

  if (!date) {
    log("no dates available")
  } else if (date > currentBookedDate) {
    log(`nearest date is further than already booked (${currentBookedDate} vs ${date})`)
  } else {
    currentBookedDate = date
    const time = await checkAvailableTime(sessionHeaders, date)

    book(sessionHeaders, date, time)
      .then(d => log(`booked time at ${date} ${time}`))
  }

  await sleep(3)
}

} catch(err) { console.error(err) log("Trying again")

main(currentBookedDate)

} }

async function login() { const anonymousHeaders = await fetch(${BASE_URI}/users/sign_in, { method: 'GET', credentials: 'same-origin', redirect: 'follow', agent: null, headers: { "Content-Type": "text/plain", "Referrer-Policy": "strict-origin-when-cross-origin", 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36', 'Cache-Control': 'no-store', 'Connection': 'keep-alive' } }).then(response => extractHeaders(response));

return fetch(${BASE_URI}/users/sign_in, { "headers": Object.assign({}, anonymousHeaders, { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", }), "method": "POST", "body": new URLSearchParams({ 'utf8': '✓', 'user[email]': USERNAME, 'user[password]': PASSWORD, 'policy_confirmed': '1', 'commit': 'Accessar' }), }) .then(res => ( Object.assign({}, anonymousHeaders, { 'Cookie': extractRelevantCookies(res) }) )); }

function checkAvailableDate(headers) { return fetch(${BASE_URI}/schedule/${SCHEDULE_ID}/appointment/days/${FACILITY_ID}.json?appointments[expedite]=false, { "headers": Object.assign({}, headers, { "Accept": "application/json", "X-Requested-With": "XMLHttpRequest", }), "cache": "no-store" }) .then(r => r.json()) .then(r => handleErrors(r)) .then(d => d.length > 0 ? d[0]['date'] : null)

}

function checkAvailableTime(headers, date) { return fetch(${BASE_URI}/schedule/${SCHEDULE_ID}/appointment/times/${FACILITY_ID}.json?date=${date}&appointments[expedite]=false, { "headers": Object.assign({}, headers, { "Accept": "application/json", "X-Requested-With": "XMLHttpRequest", }), "cache": "no-store", }) .then(r => r.json()) .then(r => handleErrors(r)) .then(d => d['business_times'][0] || d['available_times'][0]) }

function handleErrors(response) { const errorMessage = response['error']

if (errorMessage) { throw new Error(errorMessage); }

return response }

async function book(headers, date, time) { const url = ${BASE_URI}/schedule/${SCHEDULE_ID}/appointment

const newHeaders = await fetch(url, { "headers": headers }) .then(response => extractHeaders(response))

return fetch(url, { "method": "POST", "redirect": "follow", "headers": Object.assign({}, newHeaders, { 'Content-Type': 'application/x-www-form-urlencoded', }), "body": new URLSearchParams({ 'utf8': '✓', 'authenticity_token': newHeaders['X-CSRF-Token'], 'confirmed_limit_message': '1', 'use_consulate_appointment_capacity': 'true', 'appointments[consulate_appointment][facility_id]': FACILITY_ID, 'appointments[consulate_appointment][date]': date, 'appointments[consulate_appointment][time]': time, 'appointments[asc_appointment][facility_id]': '', 'appointments[asc_appointment][date]': '', 'appointments[asc_appointment][time]': '' }), }) }

async function extractHeaders(res) { const cookies = extractRelevantCookies(res)

const html = await res.text() const $ = cheerio.load(html); const csrfToken = $('meta[name="csrf-token"]').attr('content')

return { "Cookie": cookies, "X-CSRF-Token": csrfToken, "Referer": BASE_URI, "Referrer-Policy": "strict-origin-when-cross-origin", 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36', 'Cache-Control': 'no-store', 'Connection': 'keep-alive' } }

function extractRelevantCookies(res) { const parsedCookies = parseCookies(res.headers.get('set-cookie')) return _yatri_session=${parsedCookies['_yatri_session']} }

function parseCookies(cookies) { const parsedCookies = {}

cookies.split(';').map(c => c.trim()).forEach(c => { const [name, value] = c.split('=', 2) parsedCookies[name] = value })

return parsedCookies }

function sleep(s) { return new Promise((resolve) => { setTimeout(resolve, s * 1000); }); }

function log(message) { console.log([${new Date().toISOString()}], message) }

const args = process.argv.slice(2); const currentBookedDate = args[0] main(currentBookedDate)

así te funciona sin problema???

jenzkupinc commented 4 months ago

Si, funciona a la perfeciones, si deseas puedo compartir como yo lo tengo modificado con estilos, y con sus carpeta de módulos.

xamoko commented 4 months ago

Si, funciona a la perfeciones, si deseas puedo compartir como yo lo tengo modificado con estilos, y con sus carpeta de módulos.

Mejor un repo y ahi lo subes aprovechando que funciona bien XD