marusia

package
v2.14.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 13, 2022 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package marusia для создания скилла Маруси.

Для голосового помощника Маруси теперь можно создавать скиллы, которые пополнят её базу навыков. Пользователям будет удобнее общаться с Марусей, а разработчики и владельцы бизнеса смогут сделать голосовой интерфейс для своих продуктов.

Документация: https://vk.com/dev/marusia_skill_docs

Регистрация приложения ВКонтакте

Скилл можно создать в разделе для разработчиков: https://vk.com/editapp?act=create. В день можно создать не более 3-х скиллов, и не более 10-и за 5 дней.

Для этого:

1. Выберите «Скилл Маруси» в типах приложения;

2. Добавьте название, которое будет совпадать с командой для активации скилла;

3. Введите в поле Webhook URL адрес сервера, по которому будет размещен навык, например https://example.com/test-webhook;

4. Подтвердите действие.

Вы попадёте в интерфейс администрирования Вашего скилла.

Обратите внимание: имя является первой фразой-триггером для вызова скилла.

Фразы

Фразы для вызова скилла должны быть специфичны и уникальны, чтобы мы могли использовать их для внешних скиллов. Например, фразу «Расскажи анекдот» добавить не сможем, т.к. она уже используется во внутренних скиллах Маруси. А вот фразу «Давай сделаем кодревью» — пока можно использовать для внешнего скилла.

Длина фразы активации не может превышать 64 символа.

Фраза вызова скилла строится по следующей схеме:

Слово «Маруся» + любая из дефолтных фраз вызова скилла + фраза активации.

Дефолтные фразы вызова скилла:

хочу скилл/навык

запусти скилл/навык

включи скилл/навык

открой скилл/навык

Примеры: «Маруся, запусти навык шутка дня», «Маруся, включи скилл шутка дня».

Схема взаимодействия со скиллом

1. Пользователь произносит фразу для вызова скилла.

2. Получив и распознав выражение, сервер Маруси отправляет POST-запрос на Webhook URL, который вы указали в настройках.

3. Обработчик скилла должен ответить на полученный от сервера Маруси запрос. Таймаут ожидания ответа — 5 секунд, после чего сервер Маруси завершит сессию.

При создании скилла по умолчанию доступ к нему имеют только его администраторы. Для того, чтобы проверить скилл, авторизуйтесь в приложении Маруси для Android или iOS через VK Connect, используя номер, привязанный к учётной записи ВКонтакте.

Запустить скилл можно как голосовой командой, так и при помощи чата в приложении.

Также протестировать и отладить скилл можно в отладчике скиллов https://skill-debugger.marusia.mail.ru/

Если тестируется навык, развернутый локально, отладчик скорее всего столкнется с ограничениями, накладываемыми браузером на выполнение CORS.

В этом случае необходимо добавить в webhook поддержку предварительного запроса (метод OPTIONS) и проброс CORS-заголовков:

wh.EnableDebuging()

Пример

Пример скилла.

type myPayload struct {
	Text string
	marusia.DefaultPayload
}

wh := marusia.NewWebhook()
// wh.EnableDebuging()

wh.OnEvent(func(r marusia.Request) (resp marusia.Response) {
	switch r.Request.Type {
	case marusia.SimpleUtterance:
		switch r.Request.Command {
		case marusia.OnStart:
			resp.Text = "Скилл запущен"
			resp.TTS = "Скилл запущен, жду команд"
		case "картинка":
			resp.Card = marusia.NewBigImage(
				"Заголовок",
				"Описание",
				457239017,
			)
		case "картинки":
			resp.Card = marusia.NewImageList(
				457239017,
				457239018,
			)
		case "кнопки":
			resp.Text = "Держи кнопки"
			resp.TTS = "Жми на кнопки"
			resp.AddURL("ссылка", "https://vk.com")
			resp.AddButton("подсказка без нагрузки", nil)
			resp.AddButton("подсказка с нагрузкой", myPayload{
				Text: "test",
			})
		case "ссылка":
			resp.Text = marusia.CreateDeepLink(
				"e7a7d540-3928-4f11-87bf-a0de1244c096",
				map[string]string{"Text": "нагрузка из ссылки"},
			)
			resp.TTS = "Держи диплинк"
		case "пуш":
			resp.Text = `Держи пуш`
			resp.TTS = `Отправила пуш на устройство`
			resp.Push.PushText = "Hello, i am push"
		case marusia.OnInterrupt:
			resp.Text = "Скилл закрыт"
			resp.TTS = "Пока"
			resp.EndSession = true
		default:
			resp.Text = "Неизвестная команда"
			resp.TTS = "Я вас не поняла"
		}
	case marusia.ButtonPressed:
		var p myPayload

		err := json.Unmarshal(r.Request.Payload, &p)
		if err != nil {
			resp.Text = "Что-то пошло не так"
			return
		}

		resp.Text = "Кнопка нажата. Полезная нагрузка: " + p.Text
		resp.TTS = "Вы нажали на кнопку"
	case marusia.DeepLink:
		var p myPayload

		err := json.Unmarshal(r.Request.Payload, &p)
		if err != nil {
			resp.Text = "Что-то пошло не так"
			return
		}

		resp.Text = "Специальная ссылка. Полезная нагрузка: " + p.Text
		resp.TTS = "Вы перешли по ссылке"
	}

	return
})

http.HandleFunc("/", wh.HandleFunc)

http.ListenAndServe(":8080", nil)

Index

Examples

Constants

View Source
const (
	// OnStart команда запуска скилла. В скилл будет передана пустая строка
	// Command = "".
	OnStart = ""

	// OnInterrupt команда завершении скилла по команде "стоп", "выход" и т.д. в
	// скилл будет передано Command = "on_interrupt", чтобы у скилла была
	// возможность попрощаться с пользователем.
	OnInterrupt = "on_interrupt"
)

Типичные команды голосового ввода.

View Source
const Version = "1.0"

Version версия протокола.

Variables

This section is empty.

Functions

func CreateDeepLink(marusiaID string, params map[string]string) string

CreateDeepLink returns a link to go to the skill, as well as transfer data to your skill.

See https://vk.com/dev/marusia_skill_docs15

func SpeakerAudio added in v2.10.0

func SpeakerAudio(name string) string

SpeakerAudio произносимый Марусей текст можно разнообразить звуковыми эффектами, которые входят в её библиотеку звуков.

Список звуков можно найти на странице https://vk.com/dev/marusia_skill_docs4

Example
package main

import (
	"fmt"

	"github.com/SevereCloud/vksdk/v2/marusia"
)

func main() {
	tts := fmt.Sprintf(
		"Поздравляю! %s Вы правильно ответили на все мои вопросы!",
		marusia.SpeakerAudio("marusia-sounds/game-win-1"),
	)
	fmt.Println(tts)

}
Output:

Поздравляю! <speaker audio="marusia-sounds/game-win-1"> Вы правильно ответили на все мои вопросы!

func SpeakerAudioVKID added in v2.10.0

func SpeakerAudioVKID(id string) string

SpeakerAudioVKID существует возможность вставлять в произносимую речь собственные звуки. Для этого необходимо на странице редактирования скилла воспользоваться формой загрузки медиафайлов. Загруженный аудиофайл будет доступен только для использования в вашем навыке.

Example
package main

import (
	"fmt"

	"github.com/SevereCloud/vksdk/v2/marusia"
)

func main() {
	tts := fmt.Sprintf(
		"Угадайте, чей это голос? %s",
		marusia.SpeakerAudioVKID("-2000000002_123456789"),
	)
	fmt.Println(tts)

}
Output:

Угадайте, чей это голос? <speaker audio_vk_id="-2000000002_123456789">

Types

type Application added in v2.10.0

type Application struct {
	// Идентификатор экземпляра приложения, в котором пользователь общается
	// с Марусей (максимум 64 символа). Уникален в разрезе: скилл + приложение
	// (устройство).
	ApplicationID string `json:"application_id"`

	// Тип приложения (устройства). Возможные варинты: mobile, speaker, other.
	ApplicationType string `json:"application_type"`
}

Application данные об экземпляре приложения.

type AudioMeta added in v2.11.0

type AudioMeta struct {
	// Заголовок аудиозаписи.
	Title string `json:"title"`

	// Подзаголовок аудиозаписи.
	SubTitle string `json:"sub_title"`

	// ссылка на обложку композиции
	Art struct {
		URL string `json:"url"`
	} `json:"art"`
}

AudioMeta описание дополнительной информации об аудиозаписи (название аудио, обложка и тд.).

type AudioPlayer added in v2.11.0

type AudioPlayer struct {
	// Номер начального аудио (нумерация с 0).
	SeekTrack int `json:"seek_track,omitempty"`

	// С какой секунды аудио под номером seek_track начинать
	SeekSecond int             `json:"seek_second,omitempty"`
	Playlist   []AudioPlaylist `json:"playlist"`
}

AudioPlayer структура аудиоплеера состоит из плейлиста, в котором содержатся объекты для описания каждого трека внутри плейлиста, а также двух опциональных полей, в которых указывается с какого трека и с какой секунды начинать.

Важно: в плейлисте могут содержаться объекты только с одинаковым source_type, т.е не может быть плейлиста, состоящего из аудио из вк и получаемых по url.

https://vk.com/dev/marusia_skill_docs11

type AudioPlaylist added in v2.11.0

type AudioPlaylist struct {
	Stream AudioStream `json:"stream"`
	Meta   AudioMeta   `json:"meta,omitempty"`
}

AudioPlaylist структура, отвечающая за описание того откуда брать информацию о треке.

type AudioStream added in v2.11.0

type AudioStream struct {
	// ID аудио внутри плейлиста, должен быть уникальным для каждого аудио.
	TrackID string `json:"track_id"`

	// Тип источника аудиозаписи. Может иметь 2 значения url и vk.
	// source_type url доступен только после одобрения со стороны
	// разработчиков Маруси. source_type vk доступен для любых скиллов
	//
	// В случае передачи аудио через source_type vk, meta информация будет
	// взята из VK, если поле meta не передано и непосредственно из поля meta,
	// если оно передано.
	SourceType string `json:"source_type"`

	// Источник аудиозаписи.  В случае source_type url представляет ссылку на
	// аудиозапись, в случае source_type vk представляет собой audio_vk_id
	// аудиозаписи VK.
	Source string `json:"source"`
}

AudioStream описание информации об аудиозаписи.

type BindingType

type BindingType string

BindingType тип для DefaultPayload.

const (
	BindingTypeSuggest BindingType = "suggest"
)

Возможные значения.

type Button

type Button struct {
	// Текст кнопки, максимум 64 символа.
	Title string `json:"title"`

	// URL, который откроется при нажатии на кнопку, максимум 1024 байта.
	// Если свойство url не указано, по нажатию на кнопку навыку будет
	// отправлен текст кнопки. Пока кнопки с url поддерживаются только
	// на Android, на iOS появятся совсем скоро.
	URL string `json:"url,omitempty"`

	// Любой JSON, который нужно отправить скиллу, если данная кнопка будет
	// нажата, максимум 4096 байт.
	Payload interface{} `json:"payload,omitempty"`
}

Button кнопка.

type Card

type Card struct {
	// Тип карточки.
	Type CardType `json:"type"`

	// Заголовок изображения или ссылки.
	Title string `json:"title,omitempty"`

	// Описание ссылки.
	Text string `json:"text,omitempty"`

	// Описание изображения.
	//
	// Deprecated: исчезло из документации.
	Description string `json:"description,omitempty"`

	// ID изображения из раздела "Медиа-файлы" в настройках скилла
	// (игнорируется для типа ItemsList).
	ImageID int `json:"image_id,omitempty"`

	// Список изображений, каждый элемент является объектом формата BigImage.
	Items []CardItem `json:"items,omitempty"`

	// Ссылка для карточки типа Link. Для карточки типа MiniApp адрес мини-приложения.
	URL string `json:"url,omitempty"`
}

Card описание карточки — сообщения с поддержкой изображений.

func NewBigImage

func NewBigImage(title, description string, imageID int) *Card

NewBigImage возвращает карточку с картинкой.

func NewImageList added in v2.1.0

func NewImageList(imageIDs ...int) *Card

NewImageList возвращает карточку с набором картинок.

func NewItemsList added in v2.1.0

func NewItemsList(items ...CardItem) *Card

NewItemsList возвращает карточку с набором картинок.

func NewLink(url, title, text string, imageID int) *Card

NewLink возвращает карточку с стилизованной ссылкой.

func NewMiniApp added in v2.10.0

func NewMiniApp(url string) *Card

NewMiniApp возвращает карточку vk miniapp'а.

type CardItem added in v2.1.0

type CardItem struct {

	// ID изображения из раздела "Медиа-файлы" в настройках скилла.
	ImageID int `json:"image_id"`
}

CardItem элемент карточки.

type CardType

type CardType string

CardType тип карточки.

const (
	// Одно изображение.
	BigImage CardType = "BigImage"

	// Набор изображений.
	ItemsList CardType = "ItemsList"

	// Карточка vk miniapp'а.
	MiniApp CardType = "MiniApp"

	// Стилизованная ссылка.
	Link CardType = "Link"
)

Возможные значения.

type ClientPlayerStatus added in v2.11.0

type ClientPlayerStatus struct {
	TrackNumber int     `json:"track_number"`
	Elapsed     float64 `json:"elapsed"`
	Duration    float64 `json:"duration"`
	TrackID     int     `json:"track_id"`
}

ClientPlayerStatus плеер статус.

type DefaultPayload

type DefaultPayload struct {
	BindingType    BindingType `json:"binding_type"`
	Index          int         `json:"index"`
	TargetPhraseID string      `json:"target_phrase_id"`
}

DefaultPayload дефолтная нагрузка.

type Interfaces

type Interfaces struct {
	// Пользователь может видеть ответ скилла на экране и открывать ссылки
	// в браузере.
	Screen *Screen `json:"screen,omitempty"`
}

Interfaces интерфейсы, доступные на устройстве пользователя.

func (*Interfaces) IsScreen

func (i *Interfaces) IsScreen() bool

IsScreen пользователь может видеть ответ скилла на экране и открывать ссылки в браузере.

type Meta

type Meta struct {
	// Идентификатор клиентского приложения
	ClientID string `json:"client_id"`

	// Язык в POSIX-формате, максимум 64 символа.
	Locale string `json:"locale"`

	// Название часового пояса, включая алиасы, максимум 64 символа
	Timezone string `json:"timezone"`

	// Интерфейсы, доступные на устройстве пользователя.
	Interfaces Interfaces `json:"interfaces"`

	// Город пользователя на русском языке.
	CityRu string `json:"_city_ru,omitempty"`

	// Плеер статус.
	ClientPlayerStatus ClientPlayerStatus `json:"client_player_status,omitempty"`

	// Если true, то запрос к скиллу технический (не от реального пользователя)
	Test bool `json:"test,omitempty"`
}

Meta информация об устройстве, с помощью которого пользователь общается с Марусей.

type NLU

type NLU struct {
	Tokens   []string `json:"tokens"`
	Entities []string `json:"entities"`
}

NLU - Natural Language Understanding.

type Push added in v2.12.0

type Push struct {
	// Текст пуша, максимум 64 символа.
	PushText string `json:"push_text"`

	// Любой JSON, который нужно отправить скиллу, если данный пуш будет
	// нажат, максимум 4096 байт.
	Payload interface{} `json:"payload,omitempty"`
}

Push уведомления это удобный механизм для передачи сообщений пользователю, к примеру, если пользователь использует умную колонку с Марусей, вы можете послать ему push, при нажатии на который, откроется любой ответ от вашего навыка (к примеру картинка).

При клике на push, в навык придет запрос с указанным payload по протоколу диплинка.

type Request

type Request struct {
	// Информация об устройстве, с помощью которого пользователь общается с Марусей.
	Meta Meta `json:"meta"`

	// Данные, полученные от пользователя.
	Request RequestIn `json:"request"`

	// Данные о сессии.
	Session Session `json:"session"`

	// Хранение состояния.
	State State `json:"state"`

	// Версия протокола.
	Version string `json:"version"`
}

Request структура запроса.

type RequestIn

type RequestIn struct {
	// Служебное поле: запрос пользователя, преобразованный для внутренней
	// обработки Марусей. В ходе преобразования текст, в частности, очищается
	// от знаков препинания, а числительные преобразуются в числа. При
	// завершении скилла по команде "стоп", "выход" и т.д. в скилл будет
	// передано "on_interrupt", чтобы у скилла была возможность попрощаться с
	// пользователем.
	Command string `json:"command"`

	// Полный текст пользовательского запроса, максимум 1024 символа.
	OriginalUtterance string `json:"original_utterance"`

	// Тип ввода.
	Type RequestType `json:"type"`

	// JSON, полученный с нажатой кнопкой от обработчика скилла (в ответе на
	// предыдущий запрос), максимум 4096 байт. Передаётся, только если была
	// нажата кнопка с payload.
	Payload json.RawMessage `json:"payload,omitempty"`

	// Объект, содержащий слова и именованные сущности, которые Маруся
	// извлекла из запроса пользователя.
	NLU *NLU `json:"nlu"`
}

RequestIn данные, полученные от пользователя.

type RequestType

type RequestType string

RequestType тип ввода.

const (
	SimpleUtterance RequestType = "SimpleUtterance" // голосовой ввод
	ButtonPressed   RequestType = "ButtonPressed"   //  нажатие кнопки
	DeepLink        RequestType = "DeepLink"
)

Возможные значения.

type Response

type Response struct {
	// Текст, который следует показать и сказать пользователю. Максимум 1024
	// символа. Не должен быть пустым. В тексте ответа можно указать переводы
	// строк последовательностью «\n».
	//
	// TODO: поддержка массива строк.
	Text string `json:"text"`

	// Для того, чтобы передать SSML в ответе из внешнего скилла,
	// необходимо передать "ssml".
	TTSType string `json:"tts_type,omitempty"`

	// Speech Synthesis Markup Language представляет собой основанный
	// на XML язык разметки для приложений синтеза речи.
	SSML string `json:"ssml,omitempty"`

	// Ответ в формате TTS (text-to-speech), максимум 1024 символа.
	// Поддерживается расстановка ударений с помощью '+'.
	TTS string `json:"tts,omitempty"`

	// Кнопки (suggest'ы), которые следует показать пользователю. Кнопки можно
	// использовать как релевантные ответу ссылки или подсказки для
	// продолжения разговора.
	Buttons []Button `json:"buttons,omitempty"`

	// Push уведомление.
	Push Push `json:"push,omitempty"`

	// Признак конца разговора:
	//
	// true — сессию следует завершить,
	//
	// false — сессию следует продолжить.
	EndSession bool `json:"end_session"`

	// Описание карточки — сообщения с поддержкой изображений.
	// Важно! Если указано данное поле, то поле text игнорируется.
	Card *Card `json:"card,omitempty"`

	// Плеер.
	AudioPlayer *AudioPlayer `json:"audio_player,omitempty"`

	// Для сохранения состояния внутри сессии.
	// При этом, если в очередном ответе не записать данные, даже если они не
	// изменились, то они затрутся, и в следующем запросе поле будет пустым.
	// Помимо этого, состояние потеряется если:
	//
	// Пользователь выходит из скилла;
	//
	// Скилл сам явно завершает работу, передав EndSession: true;
	//
	// Выход происходит по таймауту, когда пользователь не отвечает некоторое
	// время (1 минуту).
	//
	// Лимит размера json-объекта - 5 КБ.
	SessionState json.RawMessage `json:"session_state,omitempty"`

	// Для персистентного хранения данных о юзере.
	// Чтобы удалить конкретное поле из сохранённого json-объекта, нужно
	// положить null в это поле.
	// Лимит размера json-объекта - 5 КБ.
	UserStateUpdate json.RawMessage `json:"user_state_update,omitempty"`
}

Response данные для ответа пользователю.

func (*Response) AddButton

func (r *Response) AddButton(title string, payload interface{})

AddButton добавляет к ответу кнопку с полезной нагрузкой.

Если полезная нагрузка не нужна, можно передать nil.

func (*Response) AddURL

func (r *Response) AddURL(title string, url string)

AddURL добавляет к ответу кнопку с ссылкой.

type Screen

type Screen struct{}

Screen структура для Interfaces.

type Session

type Session struct {
	// Уникальный идентификатор сессии, максимум 64 символа.
	SessionID string `json:"session_id"`

	// Идентификатор экземпляра приложения, в котором пользователь общается с
	// Марусей, максимум 64 символа.
	//
	// Deprecated: Важно! Это поле устарело, вместо него стоит использовать
	// Session.Application.ApplicationID.
	UserID string `json:"user_id"`

	// Идентификатор вызываемого скилла, присвоенный при создании.
	// Соответствует полю "Маруся ID" в настройках скилла.
	SkillID string `json:"skill_id"`

	// Признак новой сессии:
	//
	// true — пользователь начинает новый разговор с навыком,
	//
	// false — запрос отправлен в рамках уже начатого разговора.
	New bool `json:"new"`

	// Идентификатор сообщения в рамках сессии, максимум 8 символов.
	// Инкрементируется с каждым следующим запросом.
	MessageID int `json:"message_id"`

	// Данные о пользователе. Передаётся, только если пользователь
	// авторизован.
	User User `json:"user"`

	// Данные об экземляре приложения.
	Application Application `json:"application"`
}

Session данные о сессии.

type State added in v2.10.0

type State struct {
	// Хранение данных в сессии.
	Session json.RawMessage `json:"session"`

	// Персистентное хранение данных.
	User json.RawMessage `json:"user"`
}

State данные состояния.

type User added in v2.10.0

type User struct {
	// Идентификатор аккаунта пользователя (максимум 64 символа).
	// Уникален в разрезе: скилл + аккаунт.
	UserID string `json:"user_id"`
}

User данные о пользователе.

type Webhook

type Webhook struct {
	// contains filtered or unexported fields
}

Webhook структура.

func NewWebhook

func NewWebhook() *Webhook

NewWebhook возвращает новый Webhook.

func (*Webhook) EnableDebuging added in v2.11.0

func (wh *Webhook) EnableDebuging()

EnableDebuging включает CORS для https://skill-debugger.marusia.mail.ru

func (*Webhook) HandleFunc

func (wh *Webhook) HandleFunc(w http.ResponseWriter, r *http.Request)

HandleFunc обработчик http запросов.

func (*Webhook) OnEvent

func (wh *Webhook) OnEvent(f func(r Request) Response)

OnEvent обработчик скилла.

Таймаут ожидания ответа — 5 секунд, после чего сервер Маруси завершит сессию.

Directories

Path Synopsis
Package ssml implements Speech Synthesis Markup Language.
Package ssml implements Speech Synthesis Markup Language.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL