Code Monkey home page Code Monkey logo

yandex-dialogs-sdk's Introduction

yandex-dialogs-sdk

npm version

Note: this is an open-source project. It is not affiliated with Yandex LLC.

Tiny zen library to create skills for Yandex.Alice

yandex-dialogs-sdk — Telegram chat, if you need help

Install SDK

npm i yandex-dialogs-sdk --save

To enable debug mode run DEBUG=yandex-dialogs-sdk node YOUR_APP.js

Videotutorials

🔨 Built with SDK

Getting Started

const { Alice, Reply, Markup } = require('yandex-dialogs-sdk')
const alice = new Alice();

const M = Markup;
alice.command('', async ctx => Reply.text('Look, what i can!'));
alice.command('Give a piece of advice', async ctx =>
  Reply.text('Make const not var'),
);
alice.command(
  ['What is trending now?', 'Watch films', 'Whats in the theatre?'],
  ctx => {
    return {
      text: `What about 50 Angry Men?`,
      buttons: [M.button('Buy ticket'), M.button('What else?')],
    };
  },
);
alice.command(/(https?:\/\/[^\s]+)/g, ctx => Reply.text('Matched a link!'));
alice.any(async ctx => Reply.text(`I don't understand`));
const server = alice.listen(3001, '/');

Hot middlewares from maintainer

Handle non-trivial scenarios

const { Alice, Scene, Stage } = require('yandex-dialogs-sdk')
const stage = new Stage();
const alice = new Alice();
const SCENE_AT_BAR = 'SCENE_AT_BAR';
const atBar = new Scene(SCENE_AT_BAR);

atBar.command('show menu', ctx =>
  Reply.text('only vodka here', {
    buttons: ['buy vodka', 'go away'],
  }),
);
atBar.command('buy vodka', ctx => Reply.text(`you're dead`));
atBar.command('go away', ctx => {
  ctx.leave();
  return Reply.text('as you want');
});
atBar.any(ctx => Reply.text(`no money no honey`));

stage.addScene(atBar);
alice.use(stage.getMiddleware());
alice.command('i want some drinks', ctx => {
  ctx.enter(SCENE_AT_BAR);
  return Reply.text('lets go into pub', {
    buttons: ['show menu', 'go away'],
  });
});

A lot of examples in folder ./examples

API

Alice
const { Alice } = require('yandex-dialogs-sdk')
  • alice.command - Set handler for command
  • alice.any - Set handler if no command has been matched
alice.command('text', ctx => null)
alice.command(/regex/ig, ctx => null)
alice.command(['array', 'of', 'strings'], ctx => null)
// pass function which returns boolean. True means perfect match.
alice.command(ctx => true || false, ctx => null)

alice.any('text', ctx => null)

// create event listener
// triggers when request processing is finished
alice.on('response', ctx => {
  console.log(ctx.response)
})
Images Api

To use this API you have to provide your auth data. More info

const alice = new Alice({
  oAuthToken: OAUTH_TOKEN,
  skillId: SKILL_ID
});
  • alice.imagesApi.uploadImageByUrl - Upload image by URL
  • alice.imagesApi.uploadImageFile - Upload image by File Buffer (Not implemented yet).
  • alice.imagesApi.getImages - Get all uploaded images
  • alice.imagesApi.getImagesQuota - Get images quota
  • alice.imagesApi.deleteImage - Delete image
const image = await alice.imagesApi.uploadImageByUrl(IMAGE_URL);
const images = await alice.imagesApi.getImages();
// @example { total: 104857600, used: 25715766 }
const quota = await alice.imagesApi.getImagesQuota();
// @example { result: 'ok' } | { message: 'Image not found' }
await alice.imagesApi.deleteImage('IMAGE_ID')
Context
  • [ctx.data] - object with request
  • [ctx.message] — shortcut for ctx.data.request.command
  • [ctx.originalUtterance] - shortcut for ctx.data.request.original_utterance
  • [ctx.sessionId] — shortcut for ctx.data.session.session_id
  • [ctx.messageId] — shortcut for ctx.data.session.message_id
  • [ctx.userId] — shortcut for ctx.data.session.user_id
  • [ctx.payload] — shortcut for ctx.data.request.payload
  • [ctx.nlu] - shortcut for ctx.data.request.nlu (see more)
  • [ctx.response] - available only in listeners. appears just before sending a response
  • [ctx.enter()] - enters session
  • [ctx.leave()] - goes to main dialog
  • ctx.session.set - set session value. Session is attached to user_id
  • ctx.session.get - get session value.
// enter/leave scene
const { Scene } = require('yandex-dialogs-sdk');
ctx.enter('scene-name');
ctx.leave();

ctx.session.set('price', 200);
const price = ctx.session.get('price'); // 200

enter/leave example

Stage
const { Stage } = require('yandex-dialogs-sdk')
const stage = new Stage()
  • stage.addScene - adds scene to stage
  • stage.removeScene - removes scene from stage
  • stage.getMiddleware - returns stage middleware

full scene example

Middlewares
const createMessagesCounterMiddleware = () => {
  let count = 0
  return async (ctx, next) => {
    // You can do anything with context here
    count += 1;
    return next(ctx)
  }
}
alice.use(createMessagesCounterMiddleware())
Reply
const { Reply } = require('yandex-dialogs-sdk')
IMAGE_ID = '213044/d13b0d86a41daf9de232'
EXTRA_PARAMS = { // Extra params are optional
  tts: 'Hi the+re',
  buttons: ['one', Markup.button('two')],
  end_session: true
}
  • Reply.text
// Second argument is optional
alice.any(ctx => Reply.text('text'), EXTRA_PARAMS)
  • Reply.bigImageCard - One big image
Reply.bigImageCard('text', {
  image_id: IMAGE_ID,
  title: string, // optional
  description: string, // optional
  button: M.button('click'), // optional
}, EXTRA_PARAMS)
  • Reply.itemsListCard - Gallery
Reply.itemsListCard('text', [IMAGE_ID, IMAGE_ID], EXTRA_PARAMS);
Reply.itemsListCard('test', {
    header: 'header',
    footer: {
      text: 'test',
      button: Markup.button('button'),
    },
    items: [
      IMAGE_ID, 
      { image_id: IMAGE_ID, title: 'title', description: 'description' },
    ],
  });
Events
// create event listener
// triggers when request processing is finished
alice.on('response', ctx => {
  console.log(ctx.response)
})
Markup
const { Markup } = require('yandex-dialogs-sdk')
  • Markup.button
const M = Markup
M.button('string')
M.button({
  title: string;
  url: string;
  payload: object;
  hide: boolean;
})

CONTRIBUTING

git clone

npm install && npm run test && npm run dev

Typescript will be compiled into ./dist

Contributors

Thanks all these awesome people for this product.


Stanislav Popov

📖

Nikita Rogozhin

📖

Roman Paradeev

📖

Vanya Klimenko

📖

Dmitry Guketlev

📖

Alexander Karpov

📖

Phil Romanov © MIT 2018

yandex-dialogs-sdk's People

Contributors

alexander-karpov avatar fletcherist avatar patriarh12 avatar popstas avatar rogodec avatar sameoldmadness avatar vitalets avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

yandex-dialogs-sdk's Issues

CORS headers

Привет, я использую приложение на vue как тестовое, которое притворяется Алисой и отправляет запросы на навык.

Проблема в том, что post запросы из браузера не проходят, из-за отсутствия CORS заголовков в ответе yandex-dialogs-sdk.

Возможно ли сделать возможность указать заголовки, не меняя код sdk?

Я пока что прямо в alice.js listen вписал:

      app.use(function(req, res, next) {
        res.header("Access-Control-Allow-Origin", "*")
        res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
        next();
      })

Это помогло, но хочется по-нормальному сделать. Я вижу, что в alice.js есть middlewares, но они не используются, они предполагались как раз для таких случаев? Если да, могу отправить PR с доделкой этого функционала.

Об обязательности возвращения результата из команды scene

Второй раз натыкаюсь на проблему: если из команды сцены не вернуть результат, навык сломается.

В 1.4.7 ctx.reply() перестал возвращать результат, из-за этого все мои сцены сломались (вся одна сцена), т.к. они заканчивались на return ctx.reply(), этот пример из README.md тоже должен перестать работать:

const inBar = new Scene('in-the-bar')
inBar.enter('Алиса, пойдём в бар!', ctx => ctx.reply('Пойдём.'))
inBar.command('ты сейчас в баре?', ctx => ctx.reply('Да!'))
inBar.leave('Пошли отсюда', ctx => ctx.reply('Уже ухожу.'))

Если команда сцены не вернет положительный (ненулевой) результат, выполнение продолжится, commands.search() найдет и исполнит следующую команду, из-за этого.

В то же время, если не вернуть результат из обычной команды, ничего страшного не произойдет, в тех же examples и реальных использованиях это есть.

Мои предложения:

  • Не проверять результат после ответа сцены и всегда прерывать выполнение. Я сейчас не вижу причин не делать этого, может быть в этом есть смысл?
  • Вернуть return для ctx.reply(), если он был убран не специально (что не имеет смысла, если выполнить первый пункт)
  • Программно проверять корректность команды, как ты это делаешь в мидлварях, это предупреждение меня спасало от ошибок (опять же не нужно, если убрать первое)

Добавить событие response

Хочется добавить событие response, которое бы тригерилось, когда ответ уже сформирован. Это пригодится например для отправки аналитики.

Примерно так:

const alice = new Alice();

alice.command('Привет', ctx => { ... });

alice.on('response', ctx => {
  console.log(ctx.response);
});

Version 2.0 READ PLEASE

Hello, mates! 🏷

I'm very sorry to say, but if u're now working on PR, 99% chance, that it wouldn't be merged in our current release. To tell you the truth, we are going to migrate to 2.0 with lots of breaking changes and new design

Can't tell you more yet, but you can look at the draft version here: https://github.com/Yavanosta/yandex-dialogs-sdk/tree/v2-preview

We haven't come to consideration with @Yavanosta in some points yet. Maybe we'll even freeze this repository and continue in another one (thanks to copyright©©© problems)

Stay tuned.

@TODO: Welcome method

Добавить welcome метод на пустое сообщение (когда впервые вызывается навык, этот метод должен быть вызван, если он был указан.

Имя для сцены и не только?

Создавая новую сцену, можно указать её название (имя). А можно ли задать дополнительно что то своё?

например:

const game = new Scene( 'song', songs.getRandom() );

и потом как то обрабатывать:

game.command('подскажи', ctx => {

    let hint = game[ someProperty ].hint;

    return ctx.reply( hint );
});

SDK не умеет завершать сессию

Предлагаю сделать метод для ctx, аналогичный методу reply

Что-то вроде ctx.endSession(), ctx.closeSession(), ctx.finishSession()

Который будет патчить

"response": {
    "end_session": true,

Предлагайте свои названия! Сделаю в рамках отдельного PR

Более плавный переход от reply('текст') к reply с указанием tts.

Больной сценарий

  1. Пишешь в коде: reply('неверный перевод слова').
  2. Получаешь неправильное ударение "слова́".
  3. Приходится стирать все и переписывать на использование replyBuilder, да ещё и дублировать всю фразу. А всего-то нужно ударение исправить. В итоге ленишься и оставляешь как есть. Качество навыка страдает.

Предложение

Ввести спец-синтаксис в reply, в котором можно указать инструкцию для tts. Что-нибудь в духе такого:

ctx.reply('неверный перевод {{слова|сл+ова}} {{C#|си шарп}}') 

Это может быть эквивалентно

ctx.reply(ctx.replyBuilder
  .text('неверный перевод слова C#') 
  .tts('неверный перевод сл+ова си шарп')
  .get());

Incorrect check of initial command

Main app:

'use strict';

const { reply } = require('alice-renderer');
const { Alice } = require('yandex-dialogs-sdk');

const alice = new Alice();

alice.command('команда', () => reply`команда `);
alice.command('длинная команда', () => reply`длинная команда`);
alice.command('', () => reply`команда приветствие`);

alice.listen(8000, '/');

$ node testapp.js

Test app:

$ cat testtest.js 
'use strict';

const User = require('alice-tester');
const user = new User('http://localhost:8000/');
user.enter().then(() => {
  console.log(user.response);
});


$ node testtest.js
{ text: 'длинная команда',
  tts: 'длинная команда',
  end_session: false }

Matchers

@popstas предложил реализовать функциональность матчеров первым аргументом к команде

const matcher = ctx => ['спасибо', 'благодарю', 'спс'].indexOf(ctx.message) !== -1)
alice.command(matcher, ctx => ctx.reply('всегда пожалуйста')

Идея очень крутая, это позволит разработчикам описывать свои матч-паттерны. В будущем, можно будет прикрутить в этот матчер функцию-модель-NLP-whatever — вот тогда заживём

Программный выход из сцены

Здравствуйте! Я немного запутался в сценах. Хочу сразу предупредить я с "nodejs" на вы, а с "typeScript" на "что это О_о".

Постараюсь вкратце объяснить, что мне нужно:

Я хочу создать сцену, но "матчи" для успешного выхода определить программно или в "any" парсить и выходить? как то можно так?

TypeError: Cannot read property 'session' of undefined

code:

const { Alice, Reply } = require('yandex-dialogs-sdk');

const alice = new Alice();

alice.use((ctx, next) => {
  return next();
});

alice.any(ctx => {
  return Reply.text('Hello');
});

alice.listen(3000, '/');

output:

(node:80625) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'session' of undefined
    at .../node_modules/yandex-dialogs-sdk/dist/stage/stage.js:32:26
    at next (.../node_modules/yandex-dialogs-sdk/dist/alice.js:48:20)
    at alice.use (.../src/index.js:6:10)
    at next (.../node_modules/yandex-dialogs-sdk/dist/alice.js:48:20)
    at .../node_modules/yandex-dialogs-sdk/dist/session/userSessionMiddleware.js:15:23

не разворачивается в тестовой среде

привет, приложение интересное. хотел посмотреть и развернуть его на тестовой среде Now.sh

но нашел ошибку в lowerCamelCase нотации файла, поправь пожалуйста.

Error: Cannot find module './ButtonBuilder'
at Object. (/home/nowuser/src/node_modules/yandex-dialogs-sdk/src/ctx.js:2:23)

Scene.any (no such command)

Description:

Scene.any does not catch phrases.

Version: 2.0.6

Full code:

const { Alice, Reply, Scene, Markup } = require('yandex-dialogs-sdk');
const alice = new Alice();

const TEST_ROOM = 'TEST_ROOM';

const TestRoom = new Scene(TEST_ROOM);
const M = Markup;


alice.command('', ctx => {
    ctx.enter(TEST_ROOM);
    return Reply.text('Начать тест');
});

TestRoom.any( ctx => {
    console.log(ctx.message);
    return Reply.text('Произвести действие!');
});


const port = 3001
alice.listen(port, '/', callback => console.log(port))

Console log:

PS Q:\Apps\Adventure\Adventure Engine\Adventure-Engine---YandexAlice-MongoDB-JS> node testany.js
(node:10540) UnhandledPromiseRejectionWarning: Error: No response for request "123". Try add command for it or add default command.
at Alice.handleRequest (Q:\Apps\Adventure\Adventure Engine\Adventure-Engine---YandexAlice-MongoDB-JS\node_modules\yandex-dialogs-sdk\dist\alice.js:63:19)
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:10540) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:10540) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

CONTRIBUTING.md

Мы решили ввести гугловый кодстайл, чтобы весь проект был консистентным
http://google.github.io/styleguide/jsguide.html

Нужен гайд для контрибьюторов CONTRIBUING.md и ссылка на него в README.md.

Туда можно добавить ссылку на кодстайл.
Там можно написать, что мы решили использовать IButton вместо ButtonInterface для именования интерфейсов в коде.

ctx.userId - inconsistent interaction issue

Full code:

const { Alice, Scene, Reply, Markup } = require('yandex-dialogs-sdk');

const alice = new Alice();


const M = Markup;
const welcomeMatcher = ctx => ctx.data.session.new === true;
alice.command(welcomeMatcher, ctx =>
  Reply.text('Привет! Я загадала число от 1 до 100. Сможешь отгадать его?', {
    buttons: [M.button('Давай попробуем!'), M.button('Не хочу')],
  }),
);


alice.command('Давай попробуем!', ctx => {
    console.log(ctx.message);
    console.log(ctx.userid);
    //const uid = String(ctx.userId);
    //console.log(uid);
    //const uidalt = ctx.get('userId');
    //console.log(uidalt);
	
});

const server = alice.listen(8080, '/');

Terminal log for normal interaction:

PS H:\Apps\Adventure\Adventure Engine\Adventure-Engine---YandexAlice-MongoDB-JS> node test3.js
Давай попробуем!
undefined

For: ctx.userid (lowercase)

PS H:\Apps\Adventure\Adventure Engine\Adventure-Engine---YandexAlice-MongoDB-JS> node test3.js
Давай попробуем!
undefined

For:

const uidalt = ctx.get('userId');
console.log(uidalt);

PS H:\Apps\Adventure\Adventure Engine\Adventure-Engine---YandexAlice-MongoDB-JS> node test3.js
Давай попробуем!
undefined

And Finaly For:

const uid = String(ctx.userId);
console.log(uid);

PS H:\Apps\Adventure\Adventure Engine\Adventure-Engine---YandexAlice-MongoDB-JS> node test3.js
11dff563-fa0c-5017-99d7-cdd70c90119b

Tadam...

Поддержка вариантивности в ответах на уровне SDK

Раз уж вы даже в презентации рассказываете, что классно делать вариативность часто повторяющихся фраз, то сделайте поддержку этого в sdk.

Например, так:

ctx.reply(`${ctx.oneOf('Привет', 'Здорово')}, ${ctx.oneOf('чувак', 'парниша')}!`);

или спец-синтаксисом

ctx.reply(`{{Привет|Здорово}}, {{чувак|парниша}}!`);

можно даже с вероятностями:

ctx.reply(`{{Привет:0.9|Здорово}}, {{чувак:0.5|парниша:0.4|малыш:0.1}}!`);

Unhandled promise rejection, on short commands.

Version: SDK v2.0.6
Tested thrue: https://github.com/popstas/yandex-dialogs-client/
Node: v10.11.0; NPM: v6.4.1;

Not working:

alice.command('Нуп', ctx => { //this place
	
	return Reply.text(
		`Ты победил! Я загадала число. Сыграешь ещё раз?`,
		{
			buttons: [M.button('Сыграть ещё раз!'), M.button('Не хочу')],
		},
	);
});

No issue:

alice.command('Ну попробуй!', ctx => {
	
	return Reply.text(
		`Ты победил! Я загадала число. Сыграешь ещё раз?`,
		{
			buttons: [M.button('Сыграть ещё раз!'), M.button('Не хочу')],
		},
	);
});

Log: img

Fullcode:

const { Alice, Scene, Reply, Markup } = require('yandex-dialogs-sdk');

const alice = new Alice();


const M = Markup;

const welcomeMatcher = ctx => ctx.data.session.new === true;
alice.command(welcomeMatcher, ctx =>
  Reply.text('Привет! Я загадала число от 1 до 100. Сможешь отгадать его?', {
    buttons: [M.button('Давай попробуем!'), M.button('Не хочу')],
  }),
);

alice.command('Нуп', ctx => {
	
	return Reply.text(
		`Ты победил! Я загадала число. Сыграешь ещё раз?`,
		{
			buttons: [M.button('Сыграть ещё раз!'), M.button('Не хочу')],
		},
	);
});

const server = alice.listen(8080, '/');

fuse.js всегда совпадёт со строкой длиннее 32 символов

Оригинальный баг - krisk/Fuse#136
Ответа там нет, посмотрел PR, последние коммиты в форках, там тоже нет исправления, но в issue есть указание место на проблемную строку.

При длине строки длиннее 32 в совпадениях будут рандомные строки, все со score 0.5, ни больше ни меньше.

Варианты решения (по убыванию моих предпочтений):

  • обрезать строки до 32
  • не использовать fuse.js при строках длиннее 32
  • выкинуть fuse.js (но чем его заменить?)

Рефакторинг Session/Sessions

Кажется, это очень слабое место у нас сейчас.
Я плохо понимаю, чем оно идеологически отличается от ctx.state.
Хочется переписать его на мидлвари точно так же, как это было сделано с ctx.state

Can't compile project from sources

Trying to compile project from sources cause a lot of errors:

  1. alice.ts reference node-fetch package but it's not listed in package json
  2. a lot of typescript compiler errors
src/alice.ts:217:13 - error TS2322: Type '{}' is not assignable to type 'CommandInterface'.
  Property 'callback' is missing in type '{}'.

217       const requestedCommand: CommandInterface = requestedCommands[0]
                ~~~~~~~~~~~~~~~~


src/buttonBuilder.ts:32:5 - error TS2322: Type '{ title?: string; url?: string; hide?: boolean; payload?: {}; }' is not assignable to type 'ButtonBuilder'.
  Property 'button' is missing in type '{ title?: string; url?: string; hide?: boolean; payload?: {}; }'.

32     return this.button
       ~~~~~~~~~~~~~~~~~~


src/buttonBuilder.ts:32:5 - error TS2409: Return type of constructor signature must be assignable to the instance type of the class.

32     return this.button
       ~~~~~~~~~~~~~~~~~~


src/commands.ts:69:27 - error TS2339: Property 'toLowerCase' does not exist on type 'CommandNameType'.

69       return command.name.toLowerCase() === name.toLowerCase()
                             ~~~~~~~~~~~


src/ctx.ts:78:5 - error TS2322: Type 'void | WebhookResponse' is not assignable to type 'WebhookResponse'.
  Type 'void' is not assignable to type 'WebhookResponse'.

78     return this._sendReply(message)
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


src/ctx.ts:83:47 - error TS2345: Argument of type 'BigImageCard' is not assignable to parameter of type 'ParamsType'.
  Property 'text' is missing in type 'BigImageCard'.

83       const message = this._createReply(reply(bigImageCard(image(params))))
                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~


src/scene.ts:35:10 - error TS2416: Property 'on' in type 'Scene' is not assignable to the same property in base type 'Alice'.
  Type '(event: any) => void' is not assignable to type '() => void'.

35   public on(event) {
            ~~


src/scene.ts:77:16 - error TS2416: Property 'handleRequest' in type 'Scene' is not assignable to the same property in base type 'Alice'.
  Type '(req: WebhookRequest, sendResponse: (res: WebhookResponse) => void, ctx: CtxInterface, type?: str...' is not assignable to type '(req: WebhookRequest, sendResponse?: (res: WebhookResponse) => void) => Promise<any>'.

77   public async handleRequest(
                  ~~~~~~~~~~~~~


src/scene.ts:104:37 - error TS2345: Argument of type 'CtxInterface' is not assignable to parameter of type 'Ctx'.
  Property 'body' is missing in type 'CtxInterface'.

104       return await this.anyCallback(ctx)
                                        ~~~


src/tests/reply.spec.ts:19:21 - error TS2345: Argument of type 'string' is not assignable to parameter of type 'ParamsType'.

19   const msg = reply(expectedData.response.text)
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~


src/tests/reply.spec.ts:35:21 - error TS2345: Argument of type '{ text: string; tts: string; buttons: any[]; endSession: boolean; }' is not assignable to parameter of type 'ParamsType'.
  Property 'session' is missing in type '{ text: string; tts: string; buttons: any[]; endSession: boolean; }'.

 35   const msg = reply({
                        ~
 36     text: expectedData.response.text,
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
 39     endSession: expectedData.response.end_session,
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 40   })
    ~~~


src/tests/scene.spec.ts:18:16 - error TS2341: Property 'scenes' is private and only accessible within class 'Alice'.

18   expect(alice.scenes.length).toBe(2)
                  ~~~~~~

Не совсем понятно, как работают команды

const Alice = require('yandex-dialogs-sdk')
const alice = new Alice()

alice.welcome(async ctx => ctx.reply('welcome'));
alice.command(['Показать мои устройства', 
               'Показать ваши устройства',
               'Что у меня есть ?'], async ctx => ctx.reply('сморти'));
alice.command('Включи свет в ${where}', async ctx => {
  ctx.reply(`Включил свет в ${ctx.body.where}`);
});
      
alice.any((ctx) => {
  ctx.reply('Увы, я пока не знакома с этой командой')
});

alice.listen('/', 8000);

screen

Проблема leave и enter команд сцены

Сейчас enter и leave срабатывает только при полном совпадении, мне кажется надо бы переделать на поиск, который используется в командах.
Еще из-за того, что входная команда сейчас в общем списке команд сцены она может выбраться при команд поиске уже внутри сцены

Matchers+

Дополнение к issue #30
Очень нужный функционал, но предлагаю не использовать функцию как аргумент, а использовать объект. При использовании объекта можно будет делать проверки сразу по нескольким параметрам (команде от пользователя, данным в сессии и своей функции, куда придет ctx) и будет возможность безболезненно масштабировать функционал.
Как пример возможной реализации:

alice.command({
  speech: 'Привет!', /* Проверка по фразе, как сейчас */ 
  data: [{ key: 'step', value: 'welcome' }], /* Массив объектов для проверки по данным в сессии */ 
  additional: (ctx) => { return ctx.session.getData('step') === 'welcome' } // Своя функция обработчик, в которую приходит ctx 
}, ctx => ctx.reply('Добрый день!')

Scene не наследует fuseOptions от alice

Мне кажется, правильно будет пробрасывать fuseOptions, переданные при создании alice.
Сейчас, после #39, если fuseOptions нужно задавать для каждой сцены:

new Scene('in-answer', { fuseOptions })

Неиспользуемые файлы в репозитории

В репозитории лежит несколько неиспользуемых файлов, которые стоит убрать.

  • .babelrc
  • .flowconfig
  • package-lock.json и yarn.lockне нужны в библиотеке.

One key detail about package-lock.json is that it cannot be published, and it will be ignored if found in any place other than the toplevel package.

Заодно можно прибраться в зависимостях.

  • micro не нужен
  • eslint нужен в dev

Из .eslintrc можно убрать упоминание flowtype.

Figure doesnt work

private _searchFigures(requestedCommandName: string) {
const figuresCommands = this._figures
return figuresCommands.filter(figure => {
const reg = utils.getFiguresRegexp(figure.name)
return requestedCommandName.match(reg)
})
}

ItemsList Cards

Давайте поддержим апи диалогов с галереей карточек
Предлагаю следующее

  • Метод ctx.replyWithGallery аналогично методу ctx.replyWithImage
  • Сокращённый вариант — для просто картинок (через массив)
  • Полный вариант — для всего остального (через объект)
ctx.replyWithGallery([
  '1027858/46r960da47f60207e924',
  '1027858/46r960da47f60207e924',
  '1027858/46r960da47f60207e924',
])

Условный вход в сцену

Было бы удобно иметь возможность перейти в сцену из другой команды:

const inBar = new Scene('in-the-bar');

alice.command('Алиса, пойдём в бар!', ctx => {
    if (ctx.profile.age < 18) {
        ctx.reply('Давайте лучше в кино.');
    } else {
        ctx.reply('Пойдёмте.');
        inBar.enter();
    }
});

Выводить original_utterance в ctx

У меня в навыке смысл зависит от того, с какой фразой вызвали навык. "Спроси у ..." - чтение "Скажи ..." - запись. Поэтому понадобилось читать original_utterance, а к ней нет доступа из SDK.

Непонятки с матчами команд

Некорректно обрабатываются совпадения с массивами строк... или я чего то не понимаю

let game = new Scene( songs.get() ); // перегрузочка :)

game.enter(['готов', 'играть', 'начинаем', 'поехали', 'могу', 'давай'], ctx => {

    // совпадает с: "г", "и", "н", "п", "м", "д"
});

game.command(['повтори', 'подскажи', 'давай'], ctx => {

    // тоже совпадает с: "п", "д"
});

game.leave(['надоело', 'устал', 'скучно', 'стоп', 'хватит'], ctx => {

    // совпадает с: "н", "у", "с", "х"
});

Проще говоря с первыми буквами или неполными словами... Подскажите?

Alice is not a constructor

I'm a newbie in JS :) I tried to run:

nodemon index.js

and has an error:

const alice = new Alice()
              ^

TypeError: Alice is not a constructor
    at Object.<anonymous> (/Users/artemnovichkov/Documents/Projects/guess-numbers/index.js:2:15)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Function.Module.runMain (module.js:694:10)
    at startup (bootstrap_node.js:204:16)
    at bootstrap_node.js:625:3

Here is my index.js:

const Alice = require('yandex-dialogs-sdk')
const alice = new Alice()

const random = (min, max) => Math.floor(Math.random * (max - min + 1)) + min

const { button } = Alice
alice.welcome(ctx => {
    ctx.reply({
        text: 'Привет! Я загадала число от 1 до 100. Сможешь отгадать его?',
        buttons: [button('Давай попробуем!', button('Нет'))]
    })
})

alice.command('Давай попробуем', ctx => {
    ctx.state.guessedNumber = random(1, 100)
    ctx.reply('Ну попробуй!')
})

alice.command('Нет', ctx => {
    ctx.reply('Спасибо за игру!')
})

alice.command(/^\d+$/, ctx => {
    const number = Number(ctx.message)
    if (number > ctx.state.guessedNumber) {
        ctx.reply('Мое число меньше чем ${number}')
    } else if (number < ctx.state.guessedNumber) {
        ctx.reply('Мое число больше чем ${number}')
    } else {
        ctx.reply({
            text: 'Ты победил! Я загадала число ${ctx.state.guessedNumber}',
            buttons: [button('Сыграть еще раз', button('Нет'))]
        })
    }
})

alice.any(ctx => {
    ctx.reply('Ты ввел не число. Поробуй еще раз')
})

const port = 3000
alice.listen('/', port, callback => console.log(port))

npm package cause TypeScript compiler errors

Looks like not all required types included into npm package.

For example if you look into alice.d.ts in dist folder in reference import { configInterface } from './types/alice'; but there is no './types/alice' file here.

So I can't use this package with typescript :-(

Нужна лучшая модель описания команд

Текущая модель работает, но нужен инструмент гибче этого, надо смотреть в сторону fuzzysearch + nlp-решений. Пока что на первое время, я реализую дополнительно fuzzysearch и массивы для описания команд. Например:

alice.command(
['сколько стоит bitcoin', 'стоимость bitcoin', 'цена биткоина'], ctx => {...})

Confirm Method

@popstas предложил реализовать что-то вроде такого метода

alice.welcome((ctx) => {
  ctx.confirm({
    reply: '18 есть?',
    onYes: (ctx) => ctx.confirm({
      reply: 'А вы уверены?',
      onYes: (ctx) => ctx.reply('добро пожаловать'),
    }),
    onNo: (ctx) => {ctx.reply('в другой раз'),
  })
})

Реализовать можно в качестве middleware. Давайте обсуждать!

Prettier Integration

Hi there. We've decided to integrate prettier TS code-style autoformatter.
Thanks @alexander-karpov for the following proposal.
Here's the config:

{
    "printWidth": 100,
    "singleQuote": true,
    "tabWidth": 2,
    "semi": false
}

Another additions/requests/proposals?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.