Last active
December 14, 2018 05:20
-
-
Save pulyaevskiy/800a87ccc8db6c57145f53e8ec01b0b6 to your computer and use it in GitHub Desktop.
Actions on Google
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// 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