Json Type Provider -> using Load and credentials - f#

I am making the following request which is returning Json.
let baseUrl = "http://wex-qa.mybluemix.net/resources/question"
let userName = "yourName#aol.com"
let password = "yourCreds"
let authKey = userName + ":" + password
let client = new HttpClient()
client.DefaultRequestHeaders.Authorization <- new AuthenticationHeaderValue("Basic",authKey)
let input = new Dictionary<string,string>()
input.Add("question","what time is it")
let content = new FormUrlEncodedContent(input)
let result = client.PostAsync(baseUrl,content).Result
let resultContent = result.Content.ReadAsStringAsync().Result
I immediately thought of using the Json Type Provider so I made a local file of the response to be the type def. I then went to load the type where I need the credentials and the content. However, I did not see where the .Load() function have an overload to pass in the credentials and the content. Should I continue to make the request via the HttpClient class and use the .Parse() function?
Thanks in advance.

Expanding on the answer in the comments (which is correct).
I had this problem in 2022 with FSharp.Data 4.2.9. There still seems to be no way to put authorisation credentials into the requests for either defining the JsonProvider type, or the runtime collection of data. With a bit of working around, it can be made to work like a type provider, as described in the question and comment.
Get your credentials for web requests from the site. This often involves a single 'key' rather than a username/password pair.
Instantiate the type provider with sample data from the site (extracted with the required credentials).
At runtime, use HttpClient with Authorization, to read JSON from the URL, and then use the Parse method of the type provide to return typed data. This allows you to use intellisense on the returned data
This example is for the MailChimp API, which supports mailing lists and requires a company API Key on web requests.
First, follow instructions on the site to get 'Credentials' for API calls.
Second, use any method to extract sample JSON to a file. I used the PHP samples provided by MailChimp.
Then define the JsonProvider with that data.
type mcListsTypeProvider = JsonProvider< "./lists_sample_data.json">
Here lists is a fundamental component of the API. In this example, I will be working with the "Sales Subscribers" list.
The next function will read from a URL, and return typed Json data, as if directly from the Load function.
The core of this is the jsonProviderParse argument, which is the Parse method from the JsonProvider.
let loadTypedJson url jsonProviderParse =
use httpClient = new HttpClient()
// Set up authorisation
let mailChimpApiKey = "3ef8dXXXXXXXXXXXXXXXXf61e-us18" // Could be a "userName:passowrd" key
httpClient.DefaultRequestHeaders.Authorization <- AuthenticationHeaderValue("Basic",mailChimpApiKey)
// Get content
let result = httpClient.GetAsync(url : string).Result
let content = result.Content.ReadAsStringAsync().Result
// Parse content, with the Parse method from the JsonProvider
jsonProviderParse content
Then use loadTypedJson as you would myTypeProvider.Load("https:..")
// Find the MailChimp list Id for the "Sales Subscribers" list
let listsUrl = "https://us18.api.mailchimp.com/3.0/lists"
let data = loadTypedJson listsUrl mcListsTypeProvider.Parse
let list_id =
data.Lists
|> Seq.find (fun list -> list.Name = "Sale Subscribers")
|> (fun x -> x.Id)
printfn "Sale Subscribers list_id = %s" list_id
Output: list_id = f21XXXXX85
Intellisense working for the JsonProvider

Related

How to get oauth AccessToken in classic asp

I want to send email by connecting google via oauth
Below is the code present for C#
MailSender objMail = new MailSender();
objMail.TLS = true;
objMail.Username = "myaccount#gmail.com";
objMail.Password = "[oauth]ya29.Il-8B-88nf.......GhoNhUXKtBS-ZEQOAZ9tTWg";
...
objMail.Send();
For whole code please navigate to
https://www.aspemail.com/net_manual_03.html#3_5
To generate access token which is appended with "[oauth]" above, we are using
MailSender objMail = new MailSender();
MailSender objMail2 = objMail.GetAccessToken("GMAIL", "4/wQGBh....LtcM", false);
string AccessToken = objMail2.Username;
string RefreshToken = objMail2.Password;
int ExpiresIn = objMail2.Timeout;
I want to implement the same functionality in classic asp, but when i am creating object of "MailSender" in classic asp, it is throwing error that:
Object doesn't support this property or method:
'objMail.GetAccessToken'
Please suggest me how can i generate access token of oauth from classic asp
That error is telling you that the object you are using doesn’t recognise the method you are trying to call. In this situation the official documentation is the best resource.
Quote from GetAccessToken()
This method was introduced in version 5.5.0.1.
The likelihood here is you are using an older version of the ASPEmail COM component.
You can use the below code to output the version information;
<%
Dim Mail
Set Mail = Server.CreateObject("Persits.MailSender")
Call Response.Write("Version: " & Mail.Version)
%>

Is there a way to parse xml in docusign?

Is there a way to parse xml in docusign? And if so, how does this work? I do not find any user guide or something like this.
Thank you for your support
I would recommend that you use the REST API. the SOAP API is very old and not actively being worked on.
To retrieve values from a DocuSign "form" (we call it an envelope) you can use the following code example:
Here is a C# snippet, you get back at the end JSON with all the form data.
// Step 1: Obtain your OAuth token
var accessToken = RequestItemsService.User.AccessToken; // Represents your {ACCESS_TOKEN}
var accountId = RequestItemsService.Session.AccountId; // Represents your {ACCOUNT_ID}
var envelopeId = RequestItemsService.EnvelopeId;
// Step 2: Construct your API headers
var config = new Configuration(new ApiClient(basePath));
config.AddDefaultHeader("Authorization", "Bearer " + accessToken);
// Step 3: Call the eSignature REST API
EnvelopesApi envelopesApi = new EnvelopesApi(config);
EnvelopeFormData results = envelopesApi.GetFormData(accountId, envelopeId);

The type provider 'ProviderImplementation.HtmlProvider' reported an error: The 'Value'='XXXX' part of the cookie is invalid

I'm using HtmlProvider to web scrape stock company news e.g. https://www.nasdaq.com/symbol/{STOCK_SYMBOL_HERE}/news-headlines but I'm getting an error in this line of code
let [<Literal>] stockNewsUrl = "https://www.nasdaq.com/symbol/AAPL/news-headlines"
let news = new HtmlProvider<stockNewsUrl>()
There is squiggle on the second line and the error was Error FS3033 The type provider 'ProviderImplementation.HtmlProvider' reported an error: Cannot read sample HTML from 'https://www.nasdaq.com/symbol/AAPL/news-headlines': The 'Value'='AAPL,technology' part of the cookie is invalid.
To make an HTTP request to https://www.nasdaq.com/symbol/AAPL/news-headlines, we are required to provide a CookieContainer. Since you are using the FSharp.Data library, I suggest to use its HTTP Utilities:
type Nasdaq = HtmlProvider<"/tmp.html">
let cc = CookieContainer ()
let data =
Http.RequestString ("https://www.nasdaq.com/symbol/AAPL/news-headlines", cookieContainer = cc)
|> Nasdaq.Parse
data.Tables.``Today's Market Activity``.Html
|> printfn "%A"
Of course you have to pre-download the page and save to /tmp.html first.
Small note: if we already have the HTML string (as in our case), we use Nasdaq.Parse; if we have a url, we use Nasdaq.Load.
It looks like this fails because F# Data sends cookies in a format that the Nasdaq service does not like. An easy workaround is to download the page once to have a sample available at compile-time and then download the page at runtime using some other means.
type Nasdaq = HtmlProvider<"c:/temp/nasdaq.html">
let wc = new WebClient()
let downloaded = wc.DownloadString("https://www.nasdaq.com/symbol/AAPL/news-headlines")
let ns = Nasdaq.Load(downloaded)
This works, but there are two issues:
The page dos not contain any tables/lists, so the ns value is not giving you nice static access to anything useful
I get timeout exception when I try to download the data using WebClient, so perhaps that also does not work (but it might just be that I'm behind a proxy or something..)

How to send a speech to text request using google_speech1 in Rust?

I am trying to use google_speech1 for Rust, but the documentation provides incomplete examples, which makes it very hard for me, being both new at Rust and at using Google Speech Api, to figure out how to do send a speech to text request.
More specifically, I would like to be able to send a local audio file, indicate the source language and retrieve the transcription.
Here is the closest I could find in the official documentation(https://docs.rs/google-speech1/1.0.8+20181005/google_speech1/struct.SpeechRecognizeCall.html):
use speech1::RecognizeRequest;
// As the method needs a request, you would usually fill it with the desired information
// into the respective structure. Some of the parts shown here might not be applicable !
// Values shown here are possibly random and not representative !
let mut req = RecognizeRequest::default();
// You can configure optional parameters by calling the respective setters at will, and
// execute the final call using `doit()`.
// Values shown here are possibly random and not representative !
let result = hub.speech().recognize(req)
.doit();
UPDATE
Taking a step back, even simple examples provided on the website don't seem to run properly. Here is some sample very basic code:
pub mod speech_api_demo {
extern crate google_speech1 as speech1;
extern crate hyper;
extern crate hyper_rustls;
extern crate yup_oauth2 as oauth2;
use oauth2::{ApplicationSecret, Authenticator, DefaultAuthenticatorDelegate, MemoryStorage};
use speech1::Speech;
use speech1::{Error, Result};
use std::fs::File;
use std::io::Read;
#[derive(Deserialize, Serialize, Default)]
pub struct ConsoleApplicationSecret {
pub web: Option<ApplicationSecret>,
pub installed: Option<ApplicationSecret>,
}
pub fn speech_sample_demo() {
/*
Custom code to generate application secret
*/
let mut file =
File::open("C:\\Users\\YOURNAME\\.google-service-cli\\speech1-secret.json").unwrap();
let mut data = String::new();
file.read_to_string(&mut data).unwrap();
use serde_json as json;
let my_console_secret = json::from_str::<ConsoleApplicationSecret>(&data);
assert!(my_console_secret.is_ok());
let unwrappedConsoleSecret = my_console_secret.unwrap();
assert!(unwrappedConsoleSecret.installed.is_some() && unwrappedConsoleSecret.web.is_none());
let secret: ApplicationSecret = unwrappedConsoleSecret.installed.unwrap();
/*
Custom code to generate application secret - END
*/
// Instantiate the authenticator. It will choose a suitable authentication flow for you,
// unless you replace `None` with the desired Flow.
// Provide your own `AuthenticatorDelegate` to adjust the way it operates and get feedback about
// what's going on. You probably want to bring in your own `TokenStorage` to persist tokens and
// retrieve them from storage.
let auth = Authenticator::new(
&secret,
DefaultAuthenticatorDelegate,
hyper::Client::with_connector(hyper::net::HttpsConnector::new(
hyper_rustls::TlsClient::new(),
)),
<MemoryStorage as Default>::default(),
None,
);
let mut hub = Speech::new(
hyper::Client::with_connector(hyper::net::HttpsConnector::new(
hyper_rustls::TlsClient::new(),
)),
auth,
);
let result = hub.operations().get("name").doit();
match result {
Err(e) => match e {
// The Error enum provides details about what exactly happened.
// You can also just use its `Debug`, `Display` or `Error` traits
Error::HttpError(_)
| Error::MissingAPIKey
| Error::MissingToken(_)
| Error::Cancelled
| Error::UploadSizeLimitExceeded(_, _)
| Error::Failure(_)
| Error::BadRequest(_)
| Error::FieldClash(_)
| Error::JsonDecodeError(_, _) => (println!("{}", e)),
},
Ok(res) => println!("Success: {:?}", res),
}
}
}
Running this code (calling speech_sample_demo) gives the following error:
Token retrieval failed with error: Invalid Scope: 'no description
provided'
I also tried some very ugly code to force the scope into the request, but it did not make any difference. I am having a hard time understanding what this error means. Am I missing something in my request or is it something else getting in the way at the other end? Or maybe that api code library is just broken?
Please also note that client id and client secret provided by default don't work anymore, when I was using those it would say that account is deleted.
I then set up an OAuth 2.0 client and generated the json file which I copied over to default location and then started getting the error above. Maybe it is just me not setting Google Api account properly, but in any case would be great if someone else could try it out to see if I am the only one having those issues.
Once I get over running such a simple request, I have some more code ready to be tested that sends over an audio file, but for now it fails very early on in the process.
The error you get originates from here and means that the OAuth scope you used when generating your credentials file doesn't allow you to access the Google speech API. So the problem is not in your Rust code, but instead in the script you used to generate your OAuth access tokens.
Basically, this means that when you generated your OAuth json file, you requested access to the Google API in a general way, but you didn't say which specific APIs you meant to use. According to this document, you need to request access to the https://www.googleapis.com/auth/cloud-platform scope.
You are missing the flow param to Authenticator. This is how you get the access token. You create an Enum using FlowType.
example:
use oauth2::{ApplicationSecret, Authenticator, DefaultAuthenticatorDelegate, MemoryStorage,FlowType};
let Flo = FlowType::InstalledInteractive;
let auth = Authenticator::new(
&secret,
DefaultAuthenticatorDelegate,
hyper::Client::with_connector(hyper::net::HttpsConnector::new(
hyper_rustls::TlsClient::new(),
)),
<MemoryStorage as Default>::default(),
None,)
See here: https://docs.rs/yup-oauth2/1.0.3/yup_oauth2/enum.FlowType.html
Not exactly easy to figure out.
I made this work via service accounts by doing this
let https = hyper_rustls::HttpsConnectorBuilder::new()
.with_native_roots()
.https_only()
.enable_http1()
.build();
let service_account_key: oauth2::ServiceAccountKey = oauth2::read_service_account_key(
&"PATH_TO_SERVICE_ACCOUNT.json".to_string(),
)
.await
.unwrap();
let auth = oauth2::ServiceAccountAuthenticator::builder(service_account_key)
.build()
.await
.unwrap();
let hub = Speech::new(hyper::Client::builder().build(https), auth);

Google OAuth2 Redirect URL Issues

I cannot figure out how to pass a redirect url to accomplish OAuth2 authorization. Google REST API indicates that redirect_url parameters can be passed but this .Net API does not seem to have a feature to pass redirect url
Dim Coll As New List(Of String)
Coll.Add(CalendarService.Scope.Calendar)
Coll.Add(Google.Apis.Tasks.v1.TasksService.Scope.Tasks)
Dim credential As UserCredential = GoogleWebAuthorizationBroker.AuthorizeAsync(New ClientSecrets() With { _
.ClientId = ClientCredentials.ClientID, _
.ClientSecret = ClientCredentials.ClientSecret _
}, Coll, "user", CancellationToken.None, New SavedDataStore(myStoredResponse)).Result
Dim CalService = New CalendarService(New BaseClientService.Initializer() With { _
.HttpClientInitializer = credential, _
.ApplicationName = "myApp"})
A browser instance is launched when this code is executed but the return_url parameter in that request is always to to some random url (e.g., http://localhost:<random port number>/Authorize. Don't know where is this value coming from. In the API console, I have set http://localhost:4444/Home/Index. Since there is no match, authentication throws Error: redirect_uri_mismatch
The above code results into this request url
https://accounts.google.com/o/oauth2/auth?access_type=offline&response_type=code&client_id=589627125301.apps.googleusercontent.com&redirect_uri=http://localhost:44933/authorize/&scope=https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/tasks
In summary the question is, where is this http://localhost:44933/authorize/ coming from?
Any pointers as to how to set this redirect_uri parameter in the code?
Try adding a .CallbackURL property. Google API usually looks for one.

Resources