Lua request from Tado thermostat api - post

I'm building a so called 'Quickapp' in Home Center 3 (From Fibaro) in the 'Lua' programming language. I want to fetch some data from the Tado api, but it's poorly documented. I keep getting the following message from the console:
Full authentication is required to access this resourceunauthorized
I think that's because I need do assign the Bearer token from the request, but i'm a little lost how...
This is what i have so far:
function QuickApp:fetchTadoData(username,password,client_secret)
local url = "https://auth.tado.com/oauth/token"
local postdata = {
["client_id"] = "tado-web-app",
["grant_type"] = "password",
["scope"] = "home.user",
["username"] = username,
["password"] = password,
["client_secret"] = client_secret
}
local extraheaders = {
["content-type"] = "application/json"
}
self.http:request(url, {
options={
headers = extraheaders,
data = json.encode(postdata),
method = "POST"
},
success = function(status)
self:debug(status.data)
end,
error = function(error)
errorlog("Error getting data: "..error)
self:debug("hallo")
end
})
end
I know the Curl code to get the 'Bearer token' response:
curl -s "https://auth.tado.com/oauth/token" -d client_id=tado-web-app -d grant_type=password -d scope=home.user -d username="you#example.com" -d password="Password123" -d client_secret=wZa
But I don't know how to translate this to the above Lua code. Any help is appreciated!

https://manuals.fibaro.com/home-center-3-quick-apps
Looks OK, the main thing I'm noticing is this:
"self.http must have previously been created by net.HTTPClient"
function QuickApp :fetchTadoData( username, password, client_secret )
self .http = net .HTTPClient( { timeout = 5000 } ) -- 5 seconds
local url = "https://auth.tado.com/oauth/token"
local requestBody = {
action = 'create',
params = {
["client_id"] = "tado-web-app",
["grant_type"] = "password",
["scope"] = "home.user",
["username"] = username,
["password"] = password,
["client_secret"] = client_secret
}
}
local extraheaders = {
["content-type"] = "application/json",
["accept"] = "application/json"
}
self .http :request( url, {
options = {
headers = extraheaders,
data = json .encode( requestBody ),
method = "POST"
},
success = function( response )
self :debug( response .status )
self :debug( response .data )
end, -- success
error = function( msg )
self :debug( 'Error: ' ..msg )
end -- error
})
end -- :fetchTadoData()

Related

F# making a API request to a graphql endpoint

I try to get some data from a grqphql endpoint with F#.
I use Fsharp.Data
let apiQuery = """query findData {
apiData(Model:{
PageNumber: 1,
PageSize: 100
})
{
ErrorMessage Success ValidationResult TotalCount
Data{
ItemId
}
}
}"""
let queryGraphQl () =
Http.RequestString
( apiUrl,
headers = [ ContentType HttpContentTypes.Json;
Authorization ("bearer " + token)
],
body =
TextRequest apiQuery
)
But I get (500) Internal Server Error
The same in Python works fine:
query_headers = {
"Authorization": 'bearer %s' % token,
'Content-Type': 'application/json'
}
response = requests.post(url, json={'query': apiQuery}, headers=query_headers)
Any suggestions what I am missing?
In Postman I have to add
Content-Length and Host like to be calculated when request is sent.
It appears that the F# and Python code is not equivalent. The Python code contains additional query keyword in the payload.
I don't know the specifics of your particular endpoint, but I wrote similar code using one of the public interfaces.
open System.Net
open FSharp.Data
open FSharp.Data.HttpRequestHeaders
let key = "********-****-****-****-*************"
let uri k = $"https://api.everbase.co/graphql?apikey={k}"
let gurl = uri key
let apiQuery = """{ "query" :
"{ client { ipAddress { country { name } city { name } } } }"
}"""
let connectToGraph apiUrl apiQuery =
try
let res = Http.RequestString( url = apiUrl, httpMethod="POST", body = TextRequest apiQuery, headers = [ ContentType HttpContentTypes.Json; UserAgent "mozilla" ])
res
with
| _ as ex -> ex.Message
[<EntryPoint>]
let main argv =
let res = connectToGraph gurl apiQuery
printf "Response: %A" res
0
I suppose you should separate the query in your F# code from the rest of the definition with a ':'. Also the actual payload should be wrapped in quotes/double quotes to form a valid Json value.

C# WebClient.UploadData in Rails

I have a c# method that I'm trying to convert to ruby on rails . I'm using unirest but I think something is not working correctly. This is my C# method :
private static string HTTPPoster(string url, string prmSendData)
{
try
{
WebClient wUpload = new WebClient();
wUpload.Proxy = null;
Byte[] bPostArray = Encoding.UTF8.GetBytes(prmSendData);
Byte[] bResponse = wUpload.UploadData(url, "POST", bPostArray);
Char[] sReturnChars = Encoding.UTF8.GetChars(bResponse);
string sWebPage = new string(sReturnChars);
return sWebPage;
}
catch
{
return "-1";
}
}
And This is what I tried so far in rails with unirest :
def HTTPPoster(url)
xml = "My XML Goes Here"
byte_array = xml.bytes
headers = {}
headers['Content-Type'] = "application/json"
headers['Accept'] = "application/json"
response = Unirest.post(url,
headers: headers,
parameters: {
body: byte_array
})
puts "response #{response.body}"
if ![200,201].include?(response.code)
raise "Mblox Error: #{response.code}, #{response.body}"
end
end
If you also know other libraries that can achieve what I need please let me know.
I used Faraday gem and sent the data as xml and not as byte array. And now I am achieving want I wanted.
response = Faraday.post(url) do |req|
req.headers['Content-Type'] = "application/xml"
req.headers['Accept'] = "*/*"
req.headers['Accept-Encoding'] = "gzip, deflate, br"
req.body = xml
end

The view function did not return a valid response. The return type must be a string, dict

using Spotify API and Flask I am trying to extend refresh_token validity. As a result, when I send a request to the server, I get this error:
*The view function did not return a valid response. The return type must be a string, dict, tuple, Response instance, or WSGI callable, but it was a Response.*
My code:
#app.route("/index")
def index():
if time.time() > session['expires_in']:
payload = session['refresh_token']
ref_payload = {
'grant_type': 'refresh_token',
'refresh_token':session["refresh_token"]
}
header={'Authorization': 'Basic ' + '<CLIENT_ID>:<CLIENT_SECRET'}
r = requests.post(AUTH_URL, data=ref_payload, headers=header)
return r
#app.route("/q")
def api_callback():
session.clear()
code = request.args.get('code')
res = requests.post(AUTH_URL, data={
"grant_type":"authorization_code",
"code":code,
"redirect_uri":REDIRECT_URI,
"client_id":CLIENT_ID,
"client_secret":CLIENT_SECRET
})
res_body = res.json()
session["token"] = res_body.get("access_token")#token
session["expires_in"] = res_body.get("expires_in")#time
session["refresh_token"] = res_body.get("refresh_token")#reflesh token
return redirect("index")
https://accounts.spotify.com/api/token is accepted as AUTH_URL
Most likely the problem is very commonplace, but I can't think of a solution now. Thanks in advance
I solved this problem. In my configurashion file i was create a veriable in which i encode my client_id and client_secret to base64 format:
ID_SEC = CLIENT_ID +':'+ CLIENT_SECRET
base64_encode = base64.b64encode(ID_SEC.encode()).decode()
After in the header i edit authorisation :
header={
'Content-Type':'application/x-www-form-urlencoded',
'Accept': 'application/json',
'Authorization': 'Basic {}'.format(base64_encode)
}
And send post requests:
r = requests.post(AUTH_URL, data=ref_payload, headers=header)

Sending a message to discord webhook with lua

So I am trying to send a message to a discord webhook in Lua.
Currently I have this code:
local http = require("socket.http")
ltn12 = require("ltn12")
local payload = [[ {"username":"NAME","avatar_url":"","content":"MESSAGE"} ]]
http.request
{
url = "https://discordapp.com/api/webhooks/<redacted>",
method = "POST",
headers =
{
["Content-Type"] = "application/json",
["Content-Length"] = payload:len()
},
source = ltn12.source.string(payload),
}
That I found here: http://forum.micasaverde.com/index.php?topic=32035.0
But the message never arrives. What am I doing wrong?
Edit: I tested a bit and it seems like I get a 301 error code when I send this to the discord webhook.

How to perform basic Auth in Lua

I have the following partial lua script.
local config_string = [===[
]===]
local config = LuaConfig:new(config_string)
local request = LuaHttpRequest:new(config, "HTTP")
local username = "sss"
local password = "xxx"
request:set_header("Content-Type", "multipart/form-data")
request:set_header("Accept","application/json")
request:set_body("{\"RecordTitle\": { \"Value\": \"test vinay 344\" }, \"RecordRecordType\": \"2\", \"Fields\": { \"RoadSurface\" { \"Value\": \"smooth\" } } }")
request:set_url("http://ddddddd/CMServiceAPI/Record")
How do i perform basic Auth?
I don’t know which library you use, but something like this:
local username = "sss"
local password = "xxx"
local mime = require("mime")
request:set_header("authentication", "Basic " .. (mime.b64(username ..":" .. password)) )
request:set_header("content-type", "application/json" )
and at the end use a POST request

Resources