בניית מחלקת תקשורת עם ימות המשיח API ב nodejs
-
ב"ה לאחר שהתקדמתי קצת בNODEJS.
ניסיתי לבנות את המחלקה ונתקלתי בקשיים, וחזרתי לחפש את הנושא שכבר העליתי כאן, ועדיין צריך עזרה.
הקוד שהתחלתי לבנותconst fetch = require('node-fetch'); const { URLSearchParams } = require('url'); module.exports = class YmApiV1 { constructor(username, password) { this.username = username; this.password = password; this.token = ''; this.URL = 'https://www.call2all.co.il/ym/api/'; } Login(action, body){ let url = this.URL + 'Login?' + 'username=' + this.username + '&password=' + encodeURIComponent(this.password); this.l = fetch(url, { method: 'get' }).then(res => res.json()).then(json => { console.log(json); if (json.token){ this.token = json.token; return this.connecting(action, body); }else{ throw 'שם משתמש או סיסמא שגויים.'; } }).catch(error => console.error(error)); return this.l; } connecting( action, body = []) { if (this.token === ''){ return this.Login(action, body); }else{ let params = new URLSearchParams(); params.append('token', this.token); if (body){ for (let i in body){ params.append(i, body[i]); } } let url = this.URL + action; return fetch(url, { method: 'POST', body: params }).then(res => res.json()).then(json => {return json;}).catch(error => console.error(error)); } } Logout(){ return this.connecting('Logout'); } RunCampaign(templateId, phones, callerId = false){ let body = { templateId : templateId, phones : phones, }; if (callerId){ body['callerId'] = callerId; } return this.connecting('RunCampaign', body); } GetTemplates(){ return this.connecting('GetTemplates'); } };
והשימוש באמצעות:
const YmApiV1 = require('../my_models/YmApiV1.js'); let YmApi1 = new YmApiV1('0773137770', '1234'); YmApi1.connecting('GetSession').then(res => { console.log(res); // סתם בדיקה שהניתוק בוצע ואין יותר הרשאות YmApi1.Logout().then(() => { YmApi1.connecting('GetSession').then(res => { console.log(res); }); }); }); YmApi1.GetTemplates().then(function (t) { console.log('GetTemplates'); console.log(t); });
המורכבות במחלקה היא כך:
למי שלא מכיר את הAPI של ימות המשיח אכתוב בפשטות: מתחברים עם מספר המערכת והסיסמא לקבלת טוקן, ובאמצעות הטוקן ניתן לקרוא לשאר הפונקציות, ובסיום מומלץ לסיים את הטוקן ע"י פונקציית Logout.
לבנות סתם את קבלת הטוקן בתוך הבנאי, יש בעיה כי הרי JS לא מחכה וממשיך להמשך הקוד, ואז הוא ניגש לפונקציה לפני שהטוקן זמין, וזה ייכשל.
לעשות שהקריאה לפונקציות תיהיה מתוך פרומיז של קבלת הטוקן זה בעיה במידה ואני רוצה לבצע מספר פעולות על אותו מערכת באותו חיבור והפעולות לא קשורות אחת לשניה, יותר קל ליצור אובייקט של המחלקה ולגשת מכל מקום בקוד.
לעשות שבכל התחברות זה יוצר טוקן, זה בזבוז משאבים וקריאה נוספת, ומה גם שהמתכנת של ימות אמר לי שלמעט ביצירת טוקנים עדיף.
אז מה שעשיתי שלפני הפעלת פונקציה זה בודק האם קיים טוקן, ואחרת זה יוצר את הטוקן.
על פניו, מאוד נחמד..
הבעיה היא שבמידה ואני קורא לפונקציה נוספת בשורה אחרת בקוד ולא מתוך הפרומיז של הקריאה הקודמת, כיון ועדיין השרת בתהליך קבלת הטוקן ועדיין לא נוצר הטוקן, אז קורא שוב ליצירת טוקן, ואז נוצרים לי שני טוקנים.
אשמח למי שיכול לעzור לסיים את בניית המחלקה לטובת הכלל.
תודה
@magicode @dovid @יוסף-בן-שמעון -
@חוקר, אל תסתכל אפילו במה שאני כותב. אבל מכיון שאני הדיוט קופץ בראש אני כותב מה שעולה על דעתי. נראה אח"כ איך זה שונה ממה שהמומחים יגידו.
לכאורה הפתרון מונח בתוך מילותיו הקצרים של @magicode למעלה:אתה עושה מחלקה שיש בה פונקציה פנימית connect שהיא פרומיס והיא רצה פעם אחת בפעם השניה היא מחזירה את אותו פרומיס
ובתרגום למחלקה שלך, במקום ש-
this.token
יהיה מחרוזת, תעשה אותו פרומיס.const fetch = require('node-fetch'); const { URLSearchParams } = require('url'); module.exports = class YmApiV1 { constructor(username, password) { this.username = username; this.password = password; this.URL = 'https://www.call2all.co.il/ym/api/'; } get token() { if (!this.tokenPromise) { this.tokenPromise = new Promise((resolve, reject) => { let url = this.URL + 'Login?' + 'username=' + this.username + '&password=' + encodeURIComponent(this.password); fetch(url, { method: 'get' }).then(res => res.json()).then(json => { console.log(json); if (json.token) { resolve(json.token); } else { reject('שם משתמש או סיסמא שגויים.'); } }); }) } return this.tokenPromise; } connecting(action, body) { return this.token.then( token => { let params = new URLSearchParams(); params.append('token', token); if (body) { for (let i in body) { params.append(i, body[i]); } } let url = this.URL + action; return fetch(url, { method: 'POST', body: params }).then(res => res.json()).catch(console.error); }); } };
-
@חוקר אמר בבניית מחלקת תקשורת עם ימות המשיח API ב nodejs:
רק אשמח לקצת הסבר אודות המילה get ששמת לפני הפונקציה token.
זה היה סתם "סוכר תחבירי", זה דרך לייצר פונקציה שניגשים אליו כאילו הוא מאפיין.
כתוצאה מכך כתבתיthis.token.then
במקוםthis.token().then
.
לפי מה שאני מבין, זה נועד למצבים שיש לך משהו שבעקרון הוא מאפיין אלא שאתה רוצה לעשות קצת חישובים לפני שאתה מחזיר אותו. -
@zvizvi אמר בבניית מחלקת תקשורת עם ימות המשיח API ב nodejs:
מציע לשים את הקוד בGithub כדי שיהיה אפשר לתרום ולשפר אותו.
אשאל את ימות המשיח אם יש להם בעיה בזה.
אם אין בעיה, בהחלט שזה יכול להיות לעניין, כי ימות המשיח הוסיפו כל מיני פונקציות מעניינות בAPI, שעדיין אינן מופיעות בתיעוד הרשמי, והן יכולות מאוד לעזור. -
@חוקר אמר בבניית מחלקת תקשורת עם ימות המשיח API ב nodejs:
@zvizvi אמר בבניית מחלקת תקשורת עם ימות המשיח API ב nodejs:
מציע לשים את הקוד בGithub כדי שיהיה אפשר לתרום ולשפר אותו.
אשאל את ימות המשיח אם יש להם בעיה בזה.
אם אין בעיה, בהחלט שזה יכול להיות לעניין, כי ימות המשיח הוסיפו כל מיני פונקציות מעניינות בAPI, שעדיין אינן מופיעות בתיעוד הרשמי, והן יכולות מאוד לעזור.ספר לנו על זה,
ומאיפה אתה יודע. -
@MusiCode אמר בבניית מחלקת תקשורת עם ימות המשיח API ב nodejs:
@חוקר אמר בבניית מחלקת תקשורת עם ימות המשיח API ב nodejs:
@zvizvi אמר בבניית מחלקת תקשורת עם ימות המשיח API ב nodejs:
מציע לשים את הקוד בGithub כדי שיהיה אפשר לתרום ולשפר אותו.
אשאל את ימות המשיח אם יש להם בעיה בזה.
אם אין בעיה, בהחלט שזה יכול להיות לעניין, כי ימות המשיח הוסיפו כל מיני פונקציות מעניינות בAPI, שעדיין אינן מופיעות בתיעוד הרשמי, והן יכולות מאוד לעזור.ספר לנו על זה,
ומאיפה אתה יודע.המתכנת הראשי בימות המשיח שהוא גם המפתח של הAPI אישר את זה מבחינתם.
לגבי הפונקציות החדשות, פשוט מאוד ראיתי שיש לימות אתר חדש בפיתוח https://www.call2all.co.il/yemot-admin-g1/#/login ובדקתי ברכיב הדף איך זה עובד, ופשוט מאוד כל האתר החדש מבוסס על הAPI, ולכן הם הוסיפו את כל האפשרויות הנדרשות.
ביניהם:
קבלת פירוט דקות נכנסות
קבלת רשימת קבצים בתיקיה
שכפול/מחיקה/העברה של קובץ/ים
בקבצי טקסט ניתן העלאת טקסט כטקסט במקום כקובץ.
הורדת טקסט של קובץ טקסט/ini
וכנראה עוד כמה שעדיין לא שמתי לב.המתכנת של ימות אישר שזה בסדר לשימוש, והוא יוסיף את זה בתיעוד בימים הבאים.
מי שמצא פונקציות נוספות, שיכתוב כאן.
בינתיים זה המחלקה לפי מה שכבר הוספתי (אני מקוה בסופו של דבר להכניס את כל הפונקציות בימות כפונקציות במחלקה, זה מאוד יעיל לפי שמשתמש ב IDE.)const fetch = require('node-fetch'); const { URLSearchParams } = require('url'); module.exports = class YmApi { constructor(username, password, ymLink = 'ym') { this.username = username; this.password = password; this.URL = 'https://www.call2all.co.il/' + ymLink + '/api/'; } get token() { if (!this.tokenPromise) { this.tokenPromise = new Promise((resolve, reject) => { let url = this.URL + 'Login?' + 'username=' + this.username + '&password=' + encodeURIComponent(this.password); fetch(url, { method: 'get' }).then(res => res.json()).then(json => { console.log(json); if (json.token) { resolve(json.token); } else { reject('שם משתמש או סיסמא שגויים.'); } }); }) } return this.tokenPromise; } connecting(action, body) { console.log('action ' + action); return this.token.then( token => { let params = new URLSearchParams(); params.append('token', token); if (body) { for (let i in body) { params.append(i, body[i]); } } let url = this.URL + action; return fetch(url, { method: 'POST', body: params }).then(res => res.json()).catch(console.error); }); } Logout(){ return this.connecting('Logout'); } RunCampaign(templateId, phones, callerId = false){ let body = { templateId : templateId, phones : phones, }; if (callerId){ body['callerId'] = callerId; } return this.connecting('RunCampaign', body); } GetTemplates(){ return this.connecting('GetTemplates'); } GetTemplates2(){ return this.connecting2('GetTemplates'); } GetIvrTree(path){ return this.connecting('GetIvrTree', {path : 'ivr2:' + path}); } GetIncomingCalls(){ return this.connecting('GetIncomingCalls'); } GetTextFile(what){ return this.connecting('GetTextFile', {'what' : 'ivr2:' + what}); } UploadTextFile(what, contents){ return this.connecting('UploadTextFile', {'what' : 'ivr2:' + what, contents : contents}); } FileAction(action, what, target){ //action = [move, copy, delete] let body = {action : action, 'target' : 'ivr2:' + target}; if (typeof what === 'object'){ for (let i = 0; i < what.length;i++) { body['what' + i] = 'ivr2:' + what[i]; } }else{ body['what'] = 'ivr2:' + what; } return this.connecting('FileAction', body); } };
דוגמת שימוש בהמשך להנ"ל
YmApi.FileAction('copy', '/025.wav', '/7').then(function (t) { console.log('FileAction'); console.log(t); });
-
@חוקר הנה המחלקה שלי (מעט יותר קצר, מבוסס פרומיס):
דוגמא:
const yemot_api = require("yemot-api"); (async () => { const y = new yemot_api(); await y.connect("0773137770", "1234"); let r; /** קבלת מספר יחידות */ r = await y.exec("GetSession"); console.log(r); /** העלאת קובץ */ let o = { file: { value: "12345", options: { filename: "123.txt", contentType: "text/txt" } }, path: "ivr/123.txt" }; r = await y.exec("UploadFile", o); console.log(r); /** הורדת קובץ */ o = { path: "ivr/123.txt" }; r = await y.exec("DownloadFile", o); console.log(r); })();
צריך פונקציה אנונימית, כי רק פונקציות מאפשרות תחביר של א-סינכרוניות.
-
שימו לב:
חדש! מהיום ישנה דרך נוספת להתחבר. אין צורך ליצור טוקן ולבצע פעולות באמצעות הטוקן, אלא ניתן בקריאה עצמה לשדר במקום טוקן את פרטי הכניסה.
לדוגמאtoken=091234567:1234
ניתן לראות כאן דוגמת שימוש
http://www.call2all.co.il/f2/viewtopic.php?f=8&t=5022
מבדיקה מול המכנת הראשי בימות המשיח, האפשרות הזו עובדת בכל המקומות במקום טוקן!
שימו לב שזה יכול להיות פחות מאובטח שבכל בקשה שולחים את הפרטים המלאים, אבל מצד שני במקום שצריך לעשות רק קריאה אחת, אז זה ודאי לא אחרת מהקריאה ליצירת הטוקן..