1
0
This repository has been archived on 2022-11-26. You can view files and clone it, but cannot push or open issues or pull requests.
YandexLavkaNotifer/curier_api.js

461 lines
13 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const DEF_DELAY = 1200;
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms || DEF_DELAY));
}
var config = require('./config');
const request = require('request');
function isJson(str) {
return str.constructor === ({}).constructor;
}
function canBeJson(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
function convertDate(inputFormat) {
function pad(s) { return (s < 10) ? '0' + s : s; }
var d = new Date(inputFormat)
return [pad(d.getDate()), pad(d.getMonth()+1), d.getFullYear()].join('.')
}
const weekdays = ['Воскресенье','Понедельник','Вторник','Среда','Четверг','Пятница','Суббота']
class Courier{
free_slots = {};
old_free_slots = [];
is_waiting = false;
constructor(user) {
this.id = user.id;
this.username = user.username||'no_username';
this.password = user.password||'no_password';
this.token = user.token||'unauthorized';
this.mode = user.mode||0;
this.zones = user.zones||[];
}
updateUser(user) {
this.id = user.id||this.id;
this.username = user.username||this.username;
this.password = user.password||this.password;
this.token = user.token||this.token||'unauthorized';
this.mode = user.mode||this.mode||0;
this.zones = user.zones||this.zones||[];
}
async auth(){
var status = 'waiting';
var token = this.token;
await request.post(`https://courier.eda.yandex/api/v2/authenticate`,{
headers: {
"x-app-version": " 5.2.5"
},
body: JSON.stringify({
"username": this.username,
"password": this.password
})
}, await function(err, response, body) {
if(err) {
console.log(err)
return status = false;
}
if(canBeJson(body))body=JSON.parse(body);
if(body.isSuccess){
token = body.payload.apiKey||'unauthorized';
status = true;
}
else {
console.log(body)
return status = false;
}
});
while(status == 'waiting') {
await sleep(100);
}
this.token = token;
return status;
}
async getInfo(){
var returned_info = {
isSuccess: 'waiting'
}
await request.get(`https://courier.eda.yandex/api/v2/courier/info`,{
headers: {
"x-api-token": this.token
}
},await function(err, response, body) {
if(err) return returned_info.isSuccess = 'false';
if(canBeJson(body))body=JSON.parse(body);
if(body.isSuccess){
returned_info.isSuccess = 'true';
returned_info.user = {
id: body.payload.id,
name: body.payload.fullName.surname + ' ' + body.payload.fullName.firstName + ' ' + body.payload.fullName.patronymic,
status: body.payload.status
};
}
else return returned_info.isSuccess = 'false';
});
while(returned_info.isSuccess == 'waiting') {
await sleep(100);
}
this.info = returned_info.user;
return returned_info.isSuccess == 'true';
}
async getPlannedFromServer(){
var returned_info = {
isSuccess: 'waiting'
}
await request.get(`https://ctt.eda.yandex/courier-shifts/actual`,{
headers: {
"Authorization": 'Bearer ' + this.token
}
},await function(err, response, body) {
if(err) {
console.log(err)
return returned_info.isSuccess = 'false';
}
//console.log(body)
if(canBeJson(body))body=JSON.parse(body);
if(body.errors) {
returned_info.errors = body.errors;
return returned_info.isSuccess = 'false';
}
if(body.data)
returned_info = body.data;
});
while(returned_info.isSuccess == 'waiting') {
await sleep(100);
}
return returned_info;
}
async getPlanned(){
var info = await this.getPlannedFromServer();
var slots_info = {}
for(var slot of info){
if(slot.attributes.status == 'Planned'){
var time_start = (new Date(Date.parse(slot.attributes.startsAt)));
var time_end = (new Date(Date.parse(slot.attributes.endsAt)));
if(!slots_info[time_start.toLocaleDateString({ timeZone: 'Europe/Moscow' })]) slots_info[time_start.toLocaleDateString({ timeZone: 'Europe/Moscow' })] = [];
var myslot = {
startsAt: time_start.toLocaleTimeString('ru-RU',{ timeZone: 'Europe/Moscow', hour12: false }),
endsAt: time_end.toLocaleTimeString('ru-RU',{ timeZone: 'Europe/Moscow', hour12: false }),
startPoint: slot.attributes.startPoint.attributes.name
}
if(slot.attributes.startLocation)myslot.startLocation = slot.attributes.startLocation.name;
slots_info[time_start.toLocaleDateString({ timeZone: 'Europe/Moscow' })].push(myslot)//.push('Работаю ' + (new Date(Date.parse(slot.attributes.startsAt))).toLocaleDateString())
}
}
this.planned = slots_info;
return await this.getPlannedText();
}
async getPlannedText(){
var answer = '<b>Запланированные слоты:</b>\n\n';
for(var date in this.planned){
answer += `<i>(${convertDate(date)}, ${weekdays[new Date(date).getDay()]})</i>\n`
for(var slot of this.planned[date]){
if(slot.startLocation)
answer += '>' + slot.startLocation + '\n';
answer += `Слот с ${slot.startsAt.substring(0,5)} до ${slot.endsAt.substring(0,5)}
`
}
answer += '\n';
}
if(answer == '<b>Запланированные слоты:</b>\n\n') answer = 'Нет запланнированных слотов'
return answer;
}
async getMyZones(){
var info = await this.getPlannedFromServer();
var zones = {}
for(var slot of info){
if(!zones[slot.attributes.startPoint.attributes.name])zones[slot.attributes.startPoint.attributes.name]=0;
zones[slot.attributes.startPoint.attributes.name]++;
}
// console.log(zones)
/* var main_zone = '';
var num = 0;*/
this.clearZones();
for(var zone in zones){
/* if(zones[zone]>num){
num = zones[zone];
main_zone = zone;
}*/
this.addZone(config.points[zone]);
}
/* if(main_zone!='')
this.addZone(config.points[main_zone]);*/
return zones;
}
async getFreeSlotsFromServer(date){
var returned_info = {
isSuccess: 'waiting'
}
var zones_filter = ``;
for(var zone of this.zones)
zones_filter += `&filters%5Bzones%5D%5B%5D=${zone}`;
await request.get(`https://ctt.eda.yandex/courier-shifts?filters%5Bdate%5D=${date}${zones_filter}`,{
headers: {
"Authorization": 'Bearer ' + this.token,
"x-app-version": '5.3.2'
}
},await function(err, response, body) {
if(err) {
console.log(err)
return returned_info.isSuccess = 'false';
}
if(canBeJson(body))body=JSON.parse(body);
if(body.errors) {
returned_info.errors = body.errors;
return returned_info.isSuccess = 'false';
}
if(body.data)
returned_info = body.data;
});
while(returned_info.isSuccess == 'waiting') {
await sleep(100);
}
return returned_info;
}
async getFreeSlots(date){
var day_info = await this.getFreeSlotsFromServer(convertDate(date));
if(day_info.isSuccess != 'false'){
var returned_info = {
date: date,
// cols: day_info.opened.length,
slots: []
}
for(var slot of day_info.opened){
var time_start = (new Date(Date.parse(slot.attributes.startsAt)));
var time_end = (new Date(Date.parse(slot.attributes.endsAt)));
var myslot = {
id: slot.id,
startsAt: time_start.toLocaleTimeString('ru-RU',{ timeZone: 'Europe/Moscow', hour12: false }),
endsAt: time_end.toLocaleTimeString('ru-RU',{ timeZone: 'Europe/Moscow', hour12: false }),
startPoint: slot.attributes.startPoint.attributes.name,
}
if(slot.attributes.startLocation)myslot.startLocation = slot.attributes.startLocation.name;
this.free_slots[date+'_'+myslot.startsAt+'_'+myslot.endsAt]=myslot;
returned_info.slots.push(myslot)
}
return this.getFreeSlotsText(returned_info);
}
else return 'Возникла ошибка ( используйте /relogin )\n';
}
async getFreeSlotsText(day_info){
var answer = '';
if(day_info.slots.length>0){
answer = `(${convertDate(day_info.date)}, ${weekdays[(new Date(day_info.date)).getDay()]})\n`
/* for(var slot of day_info.slots){
answer += `Слот с ${slot.startsAt.substring(0,5)} до ${slot.endsAt.substring(0,5)}`;
if(this.zones.length>1)
answer+=`(${slot.startPoint})`;
answer+=`\n`;
}*/
if(this.zones.length == 1)
for(var slot of day_info.slots){
if(slot.startLocation)
answer += '>' + slot.startLocation + '\n';
answer += `Слот с ${slot.startsAt.substring(0,5)} до ${slot.endsAt.substring(0,5)}
`;
}
else{
var zones = {}
for(var slot of day_info.slots){
if(slot.startLocation){
if(!zones[slot.startLocation])zones[slot.startLocation] = [];
zones[slot.startLocation].push(slot);
}
else {
if(!zones[slot.startPoint])zones[slot.startPoint] = [];
zones[slot.startPoint].push(slot);
}
}
for(var zone in zones){
answer += '>' + zones[zone][0].startLocation||zones[zone][0].startPoint + '\n';
for (var slot of zones[zone]){
answer += `Слот с ${slot.startsAt.substring(0,5)} до ${slot.endsAt.substring(0,5)}`;
answer += `\n`;
}
}
}
answer += '\n'
}
return answer;
}
async getFreeSlotsWeek(){
var answer = '<b>Свободные слоты:</b>\n\n';
var date = new Date(Date.now())
for(var i = 0; i<=10; i++){
answer += await this.getFreeSlots(date.toLocaleDateString({ timeZone: 'Europe/Moscow'}));
date.setDate(date.getDate() + 1);
}
if(answer == '<b>Свободные слоты:</b>\n\n') answer = 'Свободных слотов нет'
return answer;
}
async getNewFreeSlotsWeek(){
this.free_slots = {};
var date = new Date(Date.now())
for(var i = 0; i<=10; i++){
await this.getFreeSlots(date.toLocaleDateString({ timeZone: 'Europe/Moscow'}));
date.setDate(date.getDate() + 1);
}
var newslots = {};
for(var slot in this.free_slots){
if(this.old_free_slots.indexOf(slot)==-1){
let date = slot.split('_')[0];
if(!newslots[date])newslots[date]=[];
newslots[date].push(this.free_slots[slot]);
}
}
this.old_free_slots = Object.keys(this.free_slots);
return await this.getNewFreeSlotsWeekText(newslots);
}
async getNewFreeSlotsWeekText(newslots){
var answer = '<b>Доступны новые слоты:</b>\n\n';
for(var date in newslots){
answer += `<i>(${convertDate(date)}, ${weekdays[new Date(date).getDay()]})</i>\n`
for(var slot of newslots[date]){
answer += `Слот с ${slot.startsAt.substring(0,5)} до ${slot.endsAt.substring(0,5)}
`
}
answer += '\n';
}
if(answer == '<b>Доступны новые слоты:</b>\n\n') answer = 'no_answer'
return answer;
}
async getOrders(){
var returned_info = {
isSuccess: 'waiting'
}
await request.get(`https://courier.eda.yandex/api/v2/orders`,{
headers: {
"x-api-token": this.token
}
},await function(err, response, body) {
if(err) {
returned_info.err = err;
return returned_info.isSuccess = 'false';
}
if(canBeJson(body))body=JSON.parse(body);
if(body.errors)
returned_info.errors = body.errors;
if(!body.isSuccess){
returned_info.body = body;
return returned_info.isSuccess = 'false';
}
if(body.isSuccess)
returned_info = body;
});
while(returned_info.isSuccess == 'waiting') {
await sleep(100);
}
return returned_info;
}
async getOrdersText(orders_){
var orders = orders_||await this.getOrders();
var answer = '';
if(orders.isSuccess){
if(!orders.meta) return config.defaulttext.need_reauth;
if(orders.meta.count == 0)
return 'Нет заказов'
for await(var order of orders.payload.orders){
console.log(order)
answer += `<b>Заказ N:</b> <i>${order.orderNr}</i>
<b>Адрес:</b> ${order.customer.address.title}, подъезд ${order.customer.address.entrance||'-'}, этаж ${order.customer.address.floor||'-'}, квартира ${order.customer.address.office||order.customer.address.doorcode||'-'}
`
if(order.comment!=null)
answer += `<b>Комментарий:</b> ${order.comment}\n`;
answer += `<b>Вес:</b> ${order.weight/1000} кг.\n`;
answer += `<b>Цена:</b> ${order.subtotal} ${order.currency.sign}\n`;
if(order.deliveryFee!='0')
answer += `<b>Платная доставка:</b> ${order.deliveryFee} ${order.currency.sign}\n`;
answer += `\n<b>Блюда:</b>\n`
for(var item of order.cartItems)
answer += `${item.quantity} ${item.name}\n`
answer += `\n`
answer += `<b>Клиент:</b> <i>${order.customer.firstName||''} ${order.customer.lastName||''}</i>
<b>Телефон:</b> <i>${order.customer.phoneNumber}</i>
`
}
}
else return 'Возникла ошибка';
return answer;
}
clearZones(){
this.zones = [];
}
addZone(zone){
this.zones.push(zone);
}
data(){
return {
id: this.id,
username: this.username,
password: this.password,
token: this.token,
mode: this.mode,
zones: this.zones
}
}
reset(){
this.token = 'unauthorized';
}
checkAuth(){
return !(this.token == 'unauthorized');
}
}
module.exports = Courier