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 = 'Запланированные слоты:\n\n';
for(var date in this.planned){
answer += `(${convertDate(date)}, ${weekdays[new Date(date).getDay()]})\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 == 'Запланированные слоты:\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 = 'Свободные слоты:\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 == 'Свободные слоты:\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 = 'Доступны новые слоты:\n\n';
for(var date in newslots){
answer += `(${convertDate(date)}, ${weekdays[new Date(date).getDay()]})\n`
for(var slot of newslots[date]){
answer += `Слот с ${slot.startsAt.substring(0,5)} до ${slot.endsAt.substring(0,5)}
`
}
answer += '\n';
}
if(answer == 'Доступны новые слоты:\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 += `Заказ N: ${order.orderNr}
Адрес: ${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 += `Комментарий: ${order.comment}\n`;
answer += `Вес: ${order.weight/1000} кг.\n`;
answer += `Цена: ${order.subtotal} ${order.currency.sign}\n`;
if(order.deliveryFee!='0')
answer += `Платная доставка: ${order.deliveryFee} ${order.currency.sign}\n`;
answer += `\nБлюда:\n`
for(var item of order.cartItems)
answer += `${item.quantity} ${item.name}\n`
answer += `\n`
answer += `Клиент: ${order.customer.firstName||''} ${order.customer.lastName||''}
Телефон: ${order.customer.phoneNumber}
`
}
}
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