Watson API access from adobe action script 3 - api

I'm trying to access the Watson Text to Speech API thru an action script 3 flash application. As you known Adobe implement a new security features to restrict the access across domains using a mechanism that use a rules based xml configuration file (crossdomain.xml). In my case the below error is raised when the script is executed:
Source code:
package
{
import flash.net.URLRequest;
import flash.net.URLRequestHeader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLLoader;
import flash.net.URLVariables;
import flash.net.URLRequestMethod;
import flash.events.Event;
import flash.events.HTTPStatusEvent;
import flash.events.SecurityErrorEvent;
import flash.events.IOErrorEvent;
public class Greeter
{
public function sayHello():String
{
var params:Object = {user:"John",password:"secret"};
var request:URLRequest = new URLRequest();
request.url = "https://watson-api-explorer.mybluemix.net/text-to-speech/api/v1/voices";
request.contentType = "application/json";
request.method = URLRequestMethod.POST;
request.data = JSON.stringify(params);
var contentTypeHeader:URLRequestHeader = new URLRequestHeader("Content-Type","application/json");
var acceptHeader:URLRequestHeader = new URLRequestHeader("Accept","application/json");
var formDataHeader:URLRequestHeader = new URLRequestHeader("Content-Type","application/json");
var authorizationHeader:URLRequestHeader = new URLRequestHeader("Authorization","Basic YjcxYWUwNTMtZTJmYi00ZmQzLWFiMTctOTRjYTc2MzYzYWE3OlZ5dU9VZ0w3ak1zVw==");
request.requestHeaders = [acceptHeader,formDataHeader,authorizationHeader,contentTypeHeader];
var postLoader:URLLoader = new URLLoader();
postLoader.dataFormat = URLLoaderDataFormat.BINARY;
postLoader.addEventListener(Event.COMPLETE, loaderCompleteHandler);
postLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
postLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
postLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
try
{
postLoader.load(request);
}
catch (error:Error)
{
trace("Unable to load post URL");
}
var greeting:String;
greeting = "Prueba de conexión a Watson!";
return JSON.stringify(request.data);
}
private function loaderCompleteHandler(event:Event):void
{
trace("loaderCompleteHandler: ");
}
private function httpStatusHandler(event:HTTPStatusEvent):void
{
trace("httpStatusHandler: ");
}
private function securityErrorHandler(event:SecurityErrorEvent):void
{
trace("securityErrorHandler: " + event);
}
private function ioErrorHandler(event:IOErrorEvent):void
{
trace("ioErrorHandler: " + event);
}
}
}
Console output:
[trace] Advertencia: Error al cargar el archivo de política desde https://watson-api-explorer.mybluemix.net/crossdomain.xml
[trace] *** Violación de la seguridad Sandbox ***
[trace] Se ha detenido la conexión con https://watson-api-explorer.mybluemix.net/text-to-speech/api/v1/voices - no se permite desde http://garragames.com/garra-x/Tick.swf
[trace] 05:45:44 PM | err | [SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2170: Security sandbox violation: http://garragames.com/garra-x/Tick.swf cannot send HTTP headers to https://watson-api-explorer.mybluemix.net/text-to-speech/api/v1/voices."]
[trace] Error #2044: Unhandled securityError:. text=Error #2170: Security sandbox violation: http://garragames.com/garra-x/Tick.swf cannot send HTTP headers to https://watson-api-explorer.mybluemix.net/text-to-speech/api/v1/voices.
¿Exist another option to access the API from Action Script Flash App?

Your real question should be "how to authenticate?" with Watson API from Flash rather than how to beat that security sandbox issue of loading/decoding via URLLoader (which has automatic cross-domain check).
You have to authenticate (log in) somehow. This seems an unlikely thing to achieve via Actionscript only. You can see a Flash Player error like :
"Authorization header cannot be sent using Actionscript"
by using URLStream instead URLLoader. Also URLStream does not care about security issues. It just gets the bytes if they exist. According to this document it says Flash "Authorization" requests are allowed. Did not work for me though. Maybe it's not allowed in debugger?
Once authenticated from your URL/Domain, then also your Flash app can make any requests as normal POST url since it's asking via same (now allowed) domain. Use URLStream instead of URLLoader if you want bytes since it has no cross-domain restrictions.
PS: for example, you can use a Sound object to playback text converted into speech.
(if authenticated, ie: you are logged in) Try :
Make an input text box on stage, with instance name txtbox.
Save below code in document class called : Main.as (compile as Main.swf)
Test the code below : (SWF result = type into textbox and press enter to hear it spoken).
package
{
import flash.display.MovieClip;
import flash.utils.*;
import flash.media.*;
import flash.net.*;
import flash.events.*;
public class Main extends MovieClip
{
public var snd_Obj: Sound = new Sound;
public var snd_Chann: SoundChannel = new SoundChannel;
public var snd_req: URLRequest = new URLRequest();
public var str_Token: String = "";
public var url_sendto_Watson: String = "";
public var str: String = "";
public var str_Voice: String = "";
public var str_mySpeech: String = "";
public var load_Token: URLLoader;
public function Main()
{
load_Token = new URLLoader();
load_Token.addEventListener(Event.COMPLETE, onTokenLoaded);
load_Token.load(new URLRequest("https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/text-to-speech/api"));
//# Your token as requested from :: https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/text-to-speech/api
//trace("Token : " + str_Token); //# To confirm it has token code
//txtbox.type = "INPUT";
txtbox.background = true;
txtbox.text = ""; //starting text
txtbox.addEventListener(TextEvent.TEXT_INPUT, text_inputCapture);
txtbox.addEventListener(KeyboardEvent.KEY_DOWN, key_handler);
addChild(txtbox);
}
function key_handler(evt:KeyboardEvent)
{
if(evt.charCode == 13) //# if ENTER key is pressed (will send text to convert to speech)
{
str_mySpeech = txtbox.text;
str_mySpeech = str_mySpeech.replace(" ", "%20");
str_Voice = "en-US_AllisonVoice"; //or your preferred voice (see:
//# Update requested URL to include your typed text
url_sendto_Watson = ""; //# reset
url_sendto_Watson = "https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize?";
url_sendto_Watson += "accept=audio/mp3"; //# get as MP3 result
url_sendto_Watson += "&text=" + str_mySpeech;
url_sendto_Watson += "&voice=" + str_Voice; //# ie: "en-US_AllisonVoice"
url_sendto_Watson += "&token=" + str_Token;
//# Attempt loading
snd_req.url = url_sendto_Watson;
snd_Obj = new Sound();
snd_Obj.addEventListener(Event.COMPLETE, onSoundLoaded);
snd_Obj.load( snd_req );
txtbox.removeEventListener(KeyboardEvent.KEY_DOWN, key_handler);
}
}
public function text_inputCapture(event:TextEvent):void
{
str = txtbox.text; //# Update text to send
txtbox.addEventListener(KeyboardEvent.KEY_DOWN, key_handler);
}
function onSoundLoaded(event:Event):void
{
snd_Chann = snd_Obj.play(); //# Play returned Speech convert result
snd_Obj.removeEventListener(Event.COMPLETE, onSoundLoaded);
}
function onTokenLoaded(evt:Event):void
{ str_Token = evt.target.data; /*# get Token result */ }
} //end Class
} //end Package
This will only work when the SWF file is embedded inside an HTML page. Something like below :
<!DOCTYPE html>
<html>
<body>
<audio id="audio_watson">
<source src="http://stream.watsonplatform.net/text-to-speech/api/v1/synthesize?accept=audio/mp3&text=welcome&voice=en-US_AllisonVoice" type="audio/mpeg">
</audio>
<embed src="Main.swf" width="800" height="600">
<script>
var a = document.getElementById("audio_watson");
a.play(); //playback to trigger authentication
</script>
</body>
</html>

Related

non-invocable member 'File' cannot be used like a method error message- what am I missing?

I have a Blazor Application which had files uploaded to a upload folder on the web server. I am in the process of trying to figure out the code to download an uploaded file in the browser for retrieval and viewing. Right now the code is as below (the download part from code examples on the internet)
public void FileDetailsToolbarClickHandler(Syncfusion.Blazor.Navigations.ClickEventArgs args)
{
string path = null;
string uploads = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "wwwroot\\uploads");
path = uploads + "\\" + SelectedFileName;
if (args.Item.Text == "Delete")
{
//Code for Deleting goes here
//UploadRef.Remove();
if (System.IO.File.Exists(path))
{
System.IO.File.Delete(path);
}
FileDetailsService.FileDetailsDelete(SelectedFileId); //NavigationManager.NavigateTo($"/ServiceRequestNotes/servicerequestnoteadd");
NavigationManager.NavigateTo($"/ServiceRequests/serviceRequestsaddedit2/{Id}", forceLoad: true);
}
else
{
// its a download
IFileProvider provider = new PhysicalFileProvider(uploads);
IFileInfo fileinfo = provider.GetFileInfo(path + SelectedFileName);
var readStream = fileinfo.CreateReadStream();
var mimeType = "application/pdf";
return File(readStream, mimeType, SelectedFileName);
}
}
On the last statement I am a getting the following error message
non-invocable member 'File' cannot be used like a method error message
What am I missing or do I need to change or add to have the output from the readstream render to the browser?
The blazor application is a blazor server app not WASM. It does not make use of API controllers.
Any advice?
This is a void method. You can't return anything at all. Also, if you're trying to instantiate a File object, you'd have to use the new keyword.

How to use Google translate for free? Maybe you have some analogs [duplicate]

If I pass a string (either in English or Arabic) as an input to the Google Translate API, it should translate it into the corresponding other language and give the translated string to me.
I read the same case in a forum but it was very hard to implement for me.
I need the translator without any buttons and if I give the input string it should automatically translate the value and give the output.
Can you help out?
You can use google script which has FREE translate API. All you need is a common google account and do these THREE EASY STEPS.
1) Create new script with such code on google script:
var mock = {
parameter:{
q:'hello',
source:'en',
target:'fr'
}
};
function doGet(e) {
e = e || mock;
var sourceText = ''
if (e.parameter.q){
sourceText = e.parameter.q;
}
var sourceLang = '';
if (e.parameter.source){
sourceLang = e.parameter.source;
}
var targetLang = 'en';
if (e.parameter.target){
targetLang = e.parameter.target;
}
var translatedText = LanguageApp.translate(sourceText, sourceLang, targetLang, {contentType: 'html'});
return ContentService.createTextOutput(translatedText).setMimeType(ContentService.MimeType.JSON);
}
2) Click Publish -> Deploy as webapp -> Who has access to the app: Anyone even anonymous -> Deploy. And then copy your web app url, you will need it for calling translate API.
3) Use this java code for testing your API:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
public class Translator {
public static void main(String[] args) throws IOException {
String text = "Hello world!";
//Translated text: Hallo Welt!
System.out.println("Translated text: " + translate("en", "de", text));
}
private static String translate(String langFrom, String langTo, String text) throws IOException {
// INSERT YOU URL HERE
String urlStr = "https://your.google.script.url" +
"?q=" + URLEncoder.encode(text, "UTF-8") +
"&target=" + langTo +
"&source=" + langFrom;
URL url = new URL(urlStr);
StringBuilder response = new StringBuilder();
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("User-Agent", "Mozilla/5.0");
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
}
}
As it is free, there are QUATA LIMITS: https://docs.google.com/macros/dashboard
Use java-google-translate-text-to-speech instead of Google Translate API v2 Java.
About java-google-translate-text-to-speech
Api unofficial with the main features of Google Translate in Java.
Easy to use!
It also provide text to speech api. If you want to translate the text "Hello!" in Romanian just write:
Translator translate = Translator.getInstance();
String text = translate.translate("Hello!", Language.ENGLISH, Language.ROMANIAN);
System.out.println(text); // "Bună ziua!"
It's free!
As #r0ast3d correctly said:
Important: Google Translate API v2 is now available as a paid service. The courtesy limit for existing Translate API v2 projects created prior to August 24, 2011 will be reduced to zero on December 1, 2011. In addition, the number of requests your application can make per day will be limited.
This is correct: just see the official page:
Google Translate API is available as a paid service. See the Pricing and FAQ pages for details.
BUT, java-google-translate-text-to-speech is FREE!
Example!
I've created a sample application that demonstrates that this works. Try it here: https://github.com/IonicaBizau/text-to-speech
Generate your own API key here. Check out the documentation here.
You may need to set up a billing account when you try to enable the Google Cloud Translation API in your account.
Below is a quick start example which translates two English strings to Spanish:
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.translate.Translate;
import com.google.api.services.translate.model.TranslationsListResponse;
import com.google.api.services.translate.model.TranslationsResource;
public class QuickstartSample
{
public static void main(String[] arguments) throws IOException, GeneralSecurityException
{
Translate t = new Translate.Builder(
GoogleNetHttpTransport.newTrustedTransport()
, GsonFactory.getDefaultInstance(), null)
// Set your application name
.setApplicationName("Stackoverflow-Example")
.build();
Translate.Translations.List list = t.new Translations().list(
Arrays.asList(
// Pass in list of strings to be translated
"Hello World",
"How to use Google Translate from Java"),
// Target language
"ES");
// TODO: Set your API-Key from https://console.developers.google.com/
list.setKey("your-api-key");
TranslationsListResponse response = list.execute();
for (TranslationsResource translationsResource : response.getTranslations())
{
System.out.println(translationsResource.getTranslatedText());
}
}
}
Required maven dependencies for the code snippet:
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-translate</artifactId>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-gson</artifactId>
<version>LATEST</version>
</dependency>
I’m tired of looking for free translators and the best option for me was Selenium (more precisely selenide and webdrivermanager) and https://translate.google.com
import io.github.bonigarcia.wdm.ChromeDriverManager;
import com.codeborne.selenide.Configuration;
import io.github.bonigarcia.wdm.DriverManagerType;
import static com.codeborne.selenide.Selenide.*;
public class Main {
public static void main(String[] args) throws IOException, ParseException {
ChromeDriverManager.getInstance(DriverManagerType.CHROME).version("76.0.3809.126").setup();
Configuration.startMaximized = true;
open("https://translate.google.com/?hl=ru#view=home&op=translate&sl=en&tl=ru");
String[] strings = /some strings to translate
for (String data: strings) {
$x("//textarea[#id='source']").clear();
$x("//textarea[#id='source']").sendKeys(data);
String translation = $x("//span[#class='tlid-translation translation']").getText();
}
}
}
You can use Google Translate API v2 Java. It has a core module that you can call from your Java code and also a command line interface module.

Reading email via thunderbird extension in html format

I am using the
function MsgHdrToMimeMessage(aMsgHdr, aCallbackThis, aCallback,
aAllowDownload, aOptions) {
method from http://mxr.mozilla.org/comm-central/source/mailnews/db/gloda/modules/mimemsg.js#171 to read the selected email via thunderbird extension. This method works fine and the only trouble is that it gives the plain text message by stripping all the html from the message.
How to get a html version of the message instead?
As I know you cannot access to the whole body (with mail and html tags). You have the functions and attributes of the XPCOM scriptable interface nsIMsgDbHdr.
I have an add-on which sends mail. I read the whole mail body with the help of the following code snippet. As you can see I read the whole mail from the disk and loaded its content into a variable. You can also use it to read the full mail body.
function SendMailNow(aMsgDBHdr) {
var aMsgURI = aMsgDBHdr.folder.getUriForMsg(aMsgDBHdr);
var msgWindow = Components.classes["#mozilla.org/messenger/msgwindow;1"]
.createInstance();
msgWindow = msgWindow.QueryInterface(Components.interfaces.nsIMsgWindow);
var msgStream = Components.classes["#mozilla.org/network/sync-stream-listener;1"]
.createInstance();
msgStream = msgStream.QueryInterface(Components.interfaces.nsIInputStream);
var aMsgService = messenger.messageServiceFromURI(aMsgURI);
var scriptInputStream = Components.classes["#mozilla.org/scriptableinputstream;1"]
.createInstance();
scriptInputStream = scriptInputStream
.QueryInterface(Components.interfaces.nsIScriptableInputStream);
scriptInputStream.init(msgStream);
try {
aMsgService.streamMessage(aMsgURI, // uri of message to stream
msgStream, // a stream listener listening to the message
msgWindow, // a nsIMsgWindow for progress and status feedback
null, // a nsIUrlListener that is notified when url starts and stops
false, // it will create a stream converter from message rfc2822 to
null // Header added to the URI. e.g., header=filter
);
} catch (ex) {
}
// Creating content
var content = "";
while (scriptInputStream.available()) {
content = content + scriptInputStream.read(512);
if (content.match(/\r\n\r\n/) || content.match(/\n\n/)) {
if (sendMail(content, aMsgDBHdr.messageId)) {
log("SEND_DONE\t" + aMsgDBHdr.messageId + "\t"
+ aMsgDBHdr.subject);
} else {
log("SEND_FAILED\t" + aMsgDBHdr.messageId + "\t"
+ aMsgDBHdr.subject);
}
}
}
}
I hope this will help you!

Authenticating with Facebook for Mobile Services in Azure

I am having trouble with facebook authentication for Mobile Services in Azure.
To be more specific, I already have an application that is using Facebook C# SDK and it works fine. I can log on, fetch list of my friends and so. I want to keep using this SDK, but I also want to authenticate for Azure Mobile Service.
So, my plan was, log on with Facebook C# SDK (as I already do today), get the authentication token, and pass it to the MobileServiceClient.LoginAsync() - function. That way, I can still have all the nice features in Facebook C# SDK, and also use the built in authentication system in Mobile Services for Azure.
var client = new FacebookClient();
dynamic parameters = new ExpandoObject();
parameters.client_id = App.FacebookAppId;
parameters.redirect_uri = "https://www.facebook.com/connect/login_success.html";
parameters.response_type = "token";
parameters.display = "popup";
var loginUrl = client.GetLoginUrl(parameters);
WebView.Navigate(loginUrl);
When load is complete, followin is executed:
FacebookOAuthResult oauthResult;
if (client.TryParseOAuthCallbackUrl(e.Uri, out oauthResult) && oauthResult.IsSuccess)
{
var accessToken = oauthResult.AccessToken;
var json = JsonObject.Parse("{\"authenticationToken\" : \"" + accessToken + "\"}");
var user = await App.MobileService.LoginAsync(MobileServiceAuthenticationProvider.Facebook, json);
}
However, I get this exception when I call the last line of code above:
MobileServiceInvalidOperationException, "Error: The POST Facebook login request must specify the access token in the body of the request."
I cannot find any information on how to format the accesstoken, I have tried a lot of different keys (instead of "authenticationToken" as you see in my sample). I also have tried just to pass the accesstoken string, but nothing seem to work.
Also, if I use the MobileServiceClient.LoginAsync() for making a brand new login, it works just fine, but it seem silly to force users to log on twice.
Any help is greatly appreciated!
The format expected for the object is {"access_token", "the-actual-access-token"}. Once the login is completed using the Facebook SDK, the token is returned in the fragment with that name, so that's what the Azure Mobile Service expects.
BTW, this is a code which I wrote, based on your snippet, which works. It should handle failed cases better, though, but for the token format, this should be enough
private void btnLoginFacebookToken_Click_1(object sender, RoutedEventArgs e)
{
var client = new Facebook.FacebookClient();
dynamic parameters = new ExpandoObject();
parameters.client_id = "MY_APPLICATION_CLIENT_ID";
parameters.redirect_uri = "https://www.facebook.com/connect/login_success.html";
parameters.response_type = "token";
parameters.display = "popup";
var uri = client.GetLoginUrl(parameters);
this.webView.LoadCompleted += webView_LoadCompleted;
this.webView.Visibility = Windows.UI.Xaml.Visibility.Visible;
this.webView.Navigate(uri);
}
async void webView_LoadCompleted(object sender, NavigationEventArgs e)
{
AddToDebug("NavigationMode: {0}", e.NavigationMode);
AddToDebug("Uri: {0}", e.Uri);
string redirect_uri = "https://www.facebook.com/connect/login_success.html";
bool close = (e.Uri.ToString().StartsWith(redirect_uri));
if (close)
{
this.webView.LoadCompleted -= webView_LoadCompleted;
this.webView.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
string fragment = e.Uri.Fragment;
string accessToken = fragment.Substring("#access_token=".Length);
accessToken = accessToken.Substring(0, accessToken.IndexOf('&'));
JsonObject token = new JsonObject();
token.Add("access_token", JsonValue.CreateStringValue(accessToken));
try
{
var user = await MobileService.LoginAsync(MobileServiceAuthenticationProvider.Facebook, token);
AddToDebug("Logged in: {0}", user.UserId);
}
catch (Exception ex)
{
AddToDebug("Error: {0}", ex);
}
}
}

File Upload Control in Domino

I need to post a file to Domino Server from a PhoneGap Application.
Here is the PhoneGap File Transfer example
// !! Assumes variable fileURI contains a valid URI to a text file on the device
var win = function(r) {
console.log("Code = " + r.responseCode);
console.log("Response = " + r.response);
console.log("Sent = " + r.bytesSent);
}
var fail = function(error) {
alert("An error has occurred: Code = " = error.code);
}
var options = new FileUploadOptions();
options.fileKey="file";
options.fileName=fileURI.substr(fileURI.lastIndexOf('/')+1);
options.mimeType="text/plain";
var params = new Object();
params.value1 = "test";
params.value2 = "param";
options.params = params;
var ft = new FileTransfer();
ft.upload(fileURI, "http://some.server.com/upload.php", win, fail, options);
//This is a PHP example - Domino would be like
// ft.upload(fileURI, "http://some.server.com/database.nsf/attachmentForm? createDocument", win, fail, options);
Does anyone know what needs to be done in Domino to get the file attachment that is being posted?
The easiest thing to do would be to create a form in Domino containing a File Upload control. You should be able to open the Domino form with a browser and see the generated html form that would normally be used. In there you will find all the info you need. This is of course dependent on the ft.upload method acting like an http multipart/form-data POST.