Skip to content

Instantly share code, notes, and snippets.

@pulyaevskiy
Last active December 14, 2018 05:20
Show Gist options
  • Save pulyaevskiy/800a87ccc8db6c57145f53e8ec01b0b6 to your computer and use it in GitHub Desktop.
Save pulyaevskiy/800a87ccc8db6c57145f53e8ec01b0b6 to your computer and use it in GitHub Desktop.
Actions on Google
/// This is pseudo-code which drafts possible way of using Google's `actions-on-google` Node.js package.
/// This code has not been tested, compiled or ran anywhere.
@JS()
library actionssdk;
import 'package:firebase_functions_interop/firebase_functions_interop.dart';
import 'package:js/js.dart';
import 'package:js/js_util.dart';
import 'package:node_interop/node_interop.dart';
void main() {
final app = actionssdk(ActionsSDKAppOptions(debug: true));
// Note that Dart functions cannot be passed to JS as-is and must be
// wrapped with allowInterop or allowInteropCaptureThis
app.intent('actions.intent.MAIN', allowInterop((ActionsSDKConversation conv,
[String input, Argument argument, GoogleRpcStatus status]) {
conv.ask('Your ssml goes here');
// If above call fails when deployed we might need to use callMethod:
callMethod(conv, 'ask', ['Your ssml goes here']);
// As you can see in firebase_admin_interop and functions interop
// I abstract away all these details from the user so that they only
// need to deal with pure Dart.
}));
app.intent('actions.intent.MAIN', allowInterop((ActionsSDKConversation conv,
[String input, Argument argument, GoogleRpcStatus status]) {
if (input == 'bye') {
// The `close` method is similar to `ask` method so might need the `callMethod`
// approach
conv.close('Goodbye!');
}
conv.ask('Your ssml goes here...');
}));
// This won't actually work currently as firebase_functions_interop expects a Dart function
// in onRequest. This can be easily fixed by updating the package to support actionssdk
// or expose native JS object to interact with directly.
functions['sayNumber'] = functions.https.onRequest(app);
}
// This loads Node.js package
// Note that you need to have it in your package.json
final ActionsSDKExports _actionsOnGoogleExports = require('actions-on-google');
// This provides access to the actionssdk only
final ActionsSDKAppFactory actionssdk = _actionsOnGoogleExports.actionssdk;
/// Here we define interface of exports provided by Node.js package.
@JS()
@anonymous
abstract class ActionsSDKExports {
// For this example we only declare the actionssdk binding, but can add more if needed.
external ActionsSDKApp actionssdk(ActionsSDKAppOptions options);
}
typedef ActionsSDKAppFactory = ActionsSDKApp Function(
ActionsSDKAppOptions options);
/// Here we define interface that's expected for the actionssdk.
@JS()
@anonymous
abstract class ActionsSDKApp {
// Rough approximation of method signature from here:
// https://actions-on-google.github.io/actions-on-google-nodejs/interfaces/actionssdk.actionssdkapp.html#intent
// [intent] here can be either single value or an array, so had to declare
// as dynamic
external ActionsSDKApp intent(
dynamic intent, ActionsSdkIntentHandler handler);
}
// This is how to declare basic JSON-like objects so that it's easy to use
// On the Dart side. Mostly useful for things like options (this case)
@JS()
@anonymous
abstract class ActionsSDKAppOptions {
external bool get debug;
// Must have external factory
external factory ActionsSDKAppOptions({bool debug});
}
/// All the bindings continued...
/// You have to declare everything you're going to use.
/// This is rough approximation of signature from here:
/// https://actions-on-google.github.io/actions-on-google-nodejs/interfaces/actionssdk.actionssdkintenthandler.html
typedef ActionsSdkIntentHandler = dynamic Function(ActionsSDKConversation conv,
[String input, Argument argument, GoogleRpcStatus status]);
@JS()
@anonymous
abstract class ActionsSDKConversation {
// Type definition for ask seems like it could be a variadic function
// in which case we won't be able to just call `conv.ask('something')` and
// will have to invoke it using [callMethod].
external ActionsSDKConversation ask(dynamic responses);
// The same applies to this method.
external ActionsSDKConversation close(dynamic responses);
// ...
}
@JS()
@anonymous
abstract class Argument {
// ...
}
@JS()
@anonymous
abstract class GoogleRpcStatus {
// ...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment