React Native use Twitter search API with Application-only authentication - react-native

I am new to React Native and want to build an App that uses the Twitter search API to display Tweets. No need for User Authentication.
I've been struggling the last two nights to get this working and starting to get frustrated xD.
I've tried building the request using Fetch and XMLHttpRequest with no luck. Also I tried several packages enabling OAuth 2.0 which also didn't work. I have the feeling I'm over complicating things as all I want to do is use the Application-only authentication and use the Standard search API.
Does anyone out there please have a code snippet on how to do this in react native without any extra packages? Is it possible at all with "just" Fetch or XMLHttpRequest?
Thanks in advance
Edit: Here's my code so far
var base64 = require('base-64');
var credentials = encodeURIComponent(key) + ":" + encodeURIComponent(secret);
var encoded = new Buffer(credentials).toString('base64');
console.log(encoded);
fetch('https://api.twitter.com/oauth2/token', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'Authorization': 'Basic ' + encoded
},
body: {
'grant_type': 'client_credentials'
},
}).then((response) => console.log(response))
Here the response:
Response {
"_bodyBlob": Blob {
"_data": Object {
"blobId": "8dea4e53-7b39-4b78-b1a5-d7ef5a58de48",
"offset": 0,
"size": 114,
},
},
"_bodyInit": Blob {
"_data": Object {
"blobId": "8dea4e53-7b39-4b78-b1a5-d7ef5a58de48",
"offset": 0,
"size": 114,
},
},
"headers": Headers {
"map": Object {
"cache-control": Array [
"public, max-age=0",
],
"content-disposition": Array [
"attachment; filename=json.json",
],
"content-type": Array [
"application/json;charset=utf-8",
],
"date": Array [
"Wed, 16 May 2018 16:55:48 GMT",
],
"expires": Array [
"Tue, 31 Mar 1981 05:00:00 GMT",
],
"last-modified": Array [
"Wed, 16 May 2018 16:55:48 GMT",
],
"ml": Array [
"A",
],
"server": Array [
"tsa_o",
],
"status": Array [
"403 Forbidden",
],
"strict-transport-security": Array [
"max-age=631138519",
],
"x-connection-hash": Array [
"b6dde5b876b934c8dcdb059ef0c400fa",
],
"x-content-type-options": Array [
"nosniff",
],
"x-frame-options": Array [
"DENY",
],
"x-response-time": Array [
"105",
],
"x-transaction": Array [
"0084737c0054c4dc",
],
"x-tsa-request-body-time": Array [
"26",
],
"x-twitter-response-tags": Array [
"BouncerCompliant",
],
"x-ua-compatible": Array [
"IE=edge,chrome=1",
],
"x-xss-protection": Array [
"1; mode=block; report=https://twitter.com/i/xss_report",
],
},
},
"ok": false,
"status": 403,
"statusText": undefined,
"type": "default",
"url": "https://api.twitter.com/oauth2/token",
}

So, I'm happy to report I got this working.
Main problem was the encoding of the Request Body.
Here"s the working code to authenticate and get a bearer token. Then using this token to use the search API:
_getBearer = () => {
var details = {
'grant_type': 'client_credentials'
};
var formBody = [];
for (var property in details) {
var encodedKey = encodeURIComponent(property);
var encodedValue = encodeURIComponent(details[property]);
formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");
var key = "xxx";
var secret = "yyy";
var base64 = require('base-64');
var credentials = encodeURIComponent(key) + ":" + encodeURIComponent(secret);
var encoded = new Buffer(credentials).toString('base64');
console.log("Created encoded credentials: " + encoded);
fetch('https://api.twitter.com/oauth2/token', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'Authorization': 'Basic ' + encoded
},
body: formBody
}).then((response) => response.json())
.then((responseData) => {
bearerToken = responseData.access_token;
console.log("Got Bearer: " + responseData.access_token);
this._loadTweet();
})
.catch((error) => {
console.error(error);
Alert.alert('Alert Title failure' + JSON.stringify(error))
});
_loadTweet = () => {
console.log("start load tweet");
fetch('https://api.twitter.com/1.1/search/tweets.json?q=love', {
method: 'GET',
headers: {
'Authorization': "Bearer " + bearerToken
}
}).then((response) => response.json())
.then((responseData) => {
console.log(JSON.stringify(responseData));
})
.catch((error) => {
console.error(error);
Alert.alert('Alert Title failure' + JSON.stringify(error))
});
};
};

Related

to generate client code from httpsnippet(npm)

I am not able to get headers in the output while generating the client code
const snippet = new HTTPSnippet({
method: 'GET',
url: 'http://mockbin.com/request',
headers: {
'content-type': 'Application/json',
}
});
const options = { indent: '\t' };
const output = snippet.convert('shell', 'curl', options);
console.log(output);
output
[Error [HARError]: validation failed] {
errors: [
{
keyword: 'type',
dataPath: '.headers',
schemaPath: '#/properties/headers/type',
params: { type: 'array' },
message: 'should be array'
}
]
}
expected: - headers should be the part of the curl rather than this error
The validation message says that headers should be an array.
HAR Docs (found in httpsnippet);
<headers>
This object contains list of all headers (used in <request> and <response> objects).
"headers": [
{
"name": "Accept-Encoding",
"value": "gzip,deflate",
"comment": ""
},
{
"name": "Accept-Language",
"value": "en-us,en;q=0.5",
"comment": ""
}
]

why cant I save data to database?

Trying to insert form data by this function.
Here is my function:
saveTimeline() {
let formData = new FormData();
formData.append("title", this.title);
formData.append("from", this.from);
formData.append("to", this.to);
formData.append("events[0].year", this.year);
formData.append("events[0].image", this.softCopyUpload);
formData.append("events[0].content", this.content);
formData.append("events[0].audio", this.audioFile);
console.log(formData);
this.$axios
.post(this.$API + "api/v1/admin/timelines/", formData, {
headers: {
Authorization: "Bearer " + this.token,
},
})
.then((res) => {
if (res) {
console.log("success");
}
});
},
Error: "Timeline title must not be set to empty"
Always getting this error. Why ?
Why append is not working ?
My JSON
{
"title": "dvdvds",
"from": 1990,
"to": 2010,
"events": [
{
"year": 1990,
"image": "test.jpg",
"content": "test content",
"audio": "test.mp4"
}
]
}
I have no idea what kind of object "this" is, but are you sure that this.title has been set to something, and is not empty?
Seems like you don't set the form data correctly. The docs suggest something like this for the browser:
const params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params);

React native sending image to server using formdata

I have a problem sending a picture to a server, that's like the default approach, but it does not seem to work.
var source = '/Users/alexx/Library/Developer/CoreSimulator/Devices/44F0FA92-4898-4CFB-862E-4E5EC4C8AB28/data/Containers/Bundle/Application/34BCE695-4B4F-472F-AB5C-F2336AC45273/DoorLock.app/123.jpg';
const form = new FormData();
form.append('image', {
uri: source,
type: 'image/jpg',
name: '123.jpg',
});
const data = () => {
fetch(api ,{
method: 'POST',
body: form,
})
that's the response i get from the server:
{
"_bodyBlob": {
"_data": {
"__collector": [
Object
],
"blobId": "78B18938-15BF-4F18-B3C8-1EB30A24D9F8",
"name": "test.html",
"offset": 0,
"size": 192,
"type": "text/html"
}
},
"_bodyInit": {
"_data": {
"__collector": [
Object
],
"blobId": "78B18938-15BF-4F18-B3C8-1EB30A24D9F8",
"name": "test.html",
"offset": 0,
"size": 192,
"type": "text/html"
}
},
"bodyUsed": false,
"headers": {
"map": {
"connection": "keep-alive",
"content-length": "192",
"content-type": "text/html",
"date": "Mon, 02 Nov 2020 22:57:21 GMT",
"server": "PythonAnywhere"
}
},
"ok": false,
"status": 400,
"statusText": undefined,
"type": "default",
"url": api
}
Although this python code works perfectly and gets a correct response
img = {'file':('123.png', open('the path to the pic/123.png', 'rb'), 'image/png)}
post(api, files = img)
is there any way to get this working or its the server side problem that can't receive the correct arguments?
Adding "file://" to the beginning of the source string fixed the problem.
so the src looks like
var source = 'file:///Users/alexx/Library/Developer/CoreSimulator/Devices/44F0FA92-4898-4CFB-862E-4E5EC4C8AB28/data/Containers/Bundle/Application/34BCE695-4B4F-472F-AB5C-F2336AC45273/DoorLock.app/123.jpg';
then it fetches perfectly, hope it helps anybody who tries to send a local image using formdata, the summary looks like this now
const form = new FormData();
form.append('file', {
uri: source,
name: '123.jpg',
fileName: 'file', //optional
});
fetch(uri,{
method: 'post',
body: form,
})
.then(response => {
console.log("image uploaded")
console.log(response)
})
.catch(console.log);
In Formdata when you pass files, you need to pass 3 parameters where
key expected from the backend (in your case image).
It will be an object which has three properties named name, type, and uri where type is the mime type (ex: image/jpeg).
name of the file
Eg:
data.append("FilePath",{
name:"image.png",
type:"image/png",
uri:"content://com.camera/image.png"
},image.png)

Agora Unable to Start Cloud Recording

options1 = {
'method': 'POST',
'url': 'https://api.agora.io/v1/apps/' + appID + '/cloud_recording/resourceid/' + resourceId + '/mode/2/start',
'headers': {
'Content-Type': 'application/json',
'Authorization': 'Basic XXX'
},
body: JSON.stringify({
"cname": "lol",
"uid": "1",
"clientRequest": {
"token": token,
"recordingConfig": {
"maxIdleTime": 30,
"streamTypes": 2,
"channelType": 0,
"videoStreamType": 0,
"transcodingConfig": {
"height": 640,
"width": 360,
"bitrate": 500,
"fps": 15,
"mixedVideoLayout": 1,
"backgroundColor": "#FF0000"
},
"subscribeVideoUids": [
"123",
"456"
],
"subscribeAudioUids": [
"“123”",
"“456”"
],
"subscribeUidGroup": 0
},
"recordingFileConfig": {
"avFileType": [
"hls"
]
},
"storageConfig": {
"accessKey": config.writeAccessKeyId,
"region": 3,
"bucket": config.bucket,
"secretKey": config.writeSecretAccessKey,
"vendor": 1,
"fileNamePrefix": [
"directory1",
"directory2"
]
}
}
})
};
request(options1, function (error, response, body) {
if (error) throw new Error(error);
console.log(response.statusCode);
I referred to the Agora's Cloud Recording API. Authentication and resourceId work fine. The response.statusCode is always 404. Unable to locate the error. I tested on Postman and the URL is not working as well. May I know if any attributes are entered wrongly? Does the user have to join the channel before the recording can start?
In your url, you have specified mode/2/start.
It should be mode/mix/start.
You can refer the documentation here for more information:
https://docs.agora.io/en/cloud-recording/cloud_recording_api_rest?platform=All%20Platforms#parameters-1
Does cloud recording work for Android and iOS as well?

Receiving [object object] from API

I tried for hours but could not extract the object value
when I execute api in postman tool I received successful message:
[
{
"Name": "Raj",
"City": "HYD",
"Initial": "SSS"
},
{
"Name": "JOHN",
"City": "HYD",
"Initial": "SSS"
},
{
"Name": "Rakesh",
"City": "HYD",
"Initial": "SSS"
}
]
But when I am trying to access same from React native but it is showing me [object object]. How to extract Name field from it?
script:
fetch('http://190.1.120.198:3538/CustomerList/api/userList', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
username:'John',
password:'UZ4952!',
Organization:'NZE'
}),
}).then((response) => response.json())
.then((responseJson) => {
console.log("myMessage:"+responseJson);
})
.catch((error) => {
console.error(error);
});
It is because you are trying to print the responseJson in logs by concatenating it with a string. When you add an object to string it will always print [object object].
console.log("myMessage:"+responseJson);
Output:
myMessage:[object object]
If you want to print the exact value of your json response you can do that in these two ways:
console.log("myMessage:",responseJson);
console.log("myMessage:"+JSON.stringify(responseJson));