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