Upload image with twitter lite - node.js

I'm using twitter-lite library and I want to twit an image with text.
I'm able to twit only text, but My goal is twit with text and image.
At the moment I'm trying to use a static image like:
const fs = require("fs")
const imageData = fs.readFileSync("./public/images/watermark_update_idea.png")
const mediaUploadResponse = await client.post('statuses/upload', {
media:imageData,
}).catch(err => {
console.error(err);
});
But I get that error:
{
_headers: Headers {
[Symbol(map)]: [Object: null prototype] {
'cache-control': [Array],
connection: [Array],
'content-encoding': [Array],
'content-length': [Array],
'content-type': [Array],
date: [Array],
server: [Array],
'set-cookie': [Array],
'strict-transport-security': [Array],
'x-connection-hash': [Array],
'x-response-time': [Array],
'x-tsa-request-body-time': [Array]
}
},
errors: [ { message: 'Sorry, that page does not exist', code: 34 } ]
}
My main goal is to twit with buffer, But I get the same error.
I tried to replicate this test but without lucky.

Potentially two issues here:
Use different subdomains for uploading an image and for posting a tweet:
const Twitter = require("twitter-lite");
const client = Twitter({/* auth data */});
const upload = Twitter({/* auth data */, subdomain: "upload"});
You have to convert your image content to a base64 string:
const imageData = fs.readFileSync("./public/images/watermark_update_idea.png");
const { media_id_string } = await upload.post('media/upload', {
media: imageData.toString("base64")
});

Related

read ECONNRESET error occurs in nextjs geinitialProps when sending get request to api

This error occured in next.js app when i send a get request using axios in getInitialPros of _app.js file.
if (typeof window === "undefined") {
// user = await checkAuth(ctx);
// const token = ctx.req.headers.cookie;
console.log("TOKEN", ctx.req.headers);
if (ctx.req && ctx.req.headers.cookie) {
try {
res = await axiosClient("get", { cookie: ctx.req.headers.cookie }).get(
"/auth/currentuser"
);
user = res.data;
console.log("USER IN SERVER SIDE", user);
ctx.store.dispatch(setAuthenticatedUser(res.data));
} catch (err) {
console.log("ERROR in APP", err);
// console.log("USER FOUND IN APP.JS", res.data);
ctx.store.dispatch(removeAuthenticatedUser());
}
}
} else {
try {
res = await axiosClient("get").get("/auth/currentuser");
user = res.data;
// await checkAuth(ctx);
// await checkAuth(ctx,)
console.log("IN CLIENT", res.data);
} catch (err) {}
}
this error occurred when the page is refreshed but it only occurs on server side, not in client side.
ERROR in APP Error: read ECONNRESET
at TLSWrap.onStreamRead (internal/stream_base_commons.js:205:27) {
errno: 'ECONNRESET',
code: 'ECONNRESET',
syscall: 'read',
config: {
url: '/auth/currentuser',
method: 'get',
headers: {
Accept: 'application/json, text/plain, */*',
cookie: 'token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI1ZjNhYTJlMmQxN2YxMzAxYTA0NGUxYTIiLCJpYXQiOjE1OTgyODUyMDMsImV4cCI6MTU5ODI4ODgwM30.qtaW-D9P6tJHzL1uHZs3wlzF39UPVkPTLEieuqaVEJY',
'User-Agent': 'axios/0.19.2'
},
baseURL: 'https://tatkaladda.com/api/',
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
adapter: [Function: httpAdapter],
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
data: undefined
},
this error only occurred in production app not in development mode.
Node.js is not aware of any baseURL. Your browser is. So on the server side you have to provide the full path, on the client side when using relative links they're relative to the base url, eg https://example.com
By: Tim Neutkens - Co-author of Next.js and MDX
One of the suggested workaround is to use full path in the getInitialProps when using axios. In your case change this:
res = await axiosClient("get").get("/auth/currentuser");
to
res = await axiosClient("get").get("http://localhost:3000/auth/currentuser");
//or use external domian if you not on localhost i.e. https:api.example.com/auth/currentuser
If still this does not work, use axios API and set full path on baseUrl as follow:
// axios call
await axios({
method: 'GET',
url: 'http://abc.herokuapp.com/api/' //or baseURL: 'http://abc.herokuapp.com/api/'
)}
Have time! kindly read this, it might help: https://github.com/vercel/next.js/issues/5009
UPDATE
Also you can try to construct your baseURL from getInitialProps context
async getInitialProps({ req }) {
const protocol = req.headers['x-forwarded-proto'] || 'http'
const baseUrl = req ? `${protocol}://${req.headers.host}` : ''
const res = await fetch(baseUrl + '/api/recent/1')
...
}

Problems connecting Service Account to Admob API with Google-Auth-Library

I've been trying to connect to Admob API from an AWS Lambda to extract some values from reports automatically from time to time. I've successfully got google-auth-library-nodejs to a layer and I am trying to use it to connect to Admob API.
I've made sure to give my Service account an Owner role and I've added the necessary GOOGLE_APPLICATION_CREDENTIALS path to the environement variables.
This is the code that I've added to my Lambda:
const {GoogleAuth} = require('google-auth-library');
exports.handler = (event, context, callback) => {
async function main() {
const auth = new GoogleAuth({
scopes: ['https://www.googleapis.com/auth/admob.report'],
});
const client = await auth.getClient();
//console.log("client", JSON.stringify(client));
const url = `https://admob.googleapis.com/v1/accounts`;
const res = await client.request({ url });
console.log("res: ", JSON.stringify(res.data));
}
main().catch(console.error);
};
When I run the code, I get the following error:
ERROR GaxiosError: Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.
at Gaxios._request (/opt/nodejs/node_modules/gaxios/build/src/gaxios.js:85:23)
at processTicksAndRejections (internal/process/task_queues.js:94:5)
at async JWT.requestAsync (/opt/nodejs/node_modules/google-auth-library/build/src/auth/oauth2client.js:350:18)
at async main (/var/task/index.js:97:19) {
response: {
config: {
url: 'https://admob.googleapis.com/v1/accounts',
headers: [Object],
params: [Object: null prototype] {},
paramsSerializer: [Function: paramsSerializer],
validateStatus: [Function: validateStatus],
responseType: 'json',
method: 'GET'
},
data: { error: [Object] },
headers: {
'alt-svc': 'quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000',
'cache-control': 'private',
connection: 'close',
'content-encoding': 'gzip',
'content-type': 'application/json; charset=UTF-8',
date: 'Wed, 26 Feb 2020 18:41:51 GMT',
server: 'ESF',
'transfer-encoding': 'chunked',
vary: 'Origin, X-Origin, Referer',
'x-content-type-options': 'nosniff',
'x-frame-options': 'SAMEORIGIN',
'x-xss-protection': '0'
},
status: 401,
statusText: 'Unauthorized',
request: { responseURL: 'https://admob.googleapis.com/v1/accounts' }
},
config: {
url: 'https://admob.googleapis.com/v1/accounts',
headers: {
Authorization: 'Bearer [Removed]',
'User-Agent': 'google-api-nodejs-client/5.10.1',
'x-goog-api-client': 'gl-node/12.14.1 auth/5.10.1',
Accept: 'application/json'
},
params: [Object: null prototype] {},
paramsSerializer: [Function: paramsSerializer],
validateStatus: [Function: validateStatus],
responseType: 'json',
method: 'GET'
},
code: 401,
errors: [
{
message: 'Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.',
domain: 'global',
reason: 'unauthorized'
}
]
}
I've been trying to find my mistake by searching on google, stack overflow, reading tutorials about connecting to Admob API as well as reading the library's code. I would really appreciate if someone could point me towards a solution.
The problem is you are trying to use a service account where OAuth User Credentials are required. You will need to implement the OAuth 2 Flow where the user enters their Google username and password.
AdMob: Authorization for the request
Refer to the following Google example on how to create a node.js OAuth 2 client.
https://github.com/googleapis/google-auth-library-nodejs#oauth2

Koa 404 when calling from Vue

I am trying to build an app with Koa and Nuxt. this is what I have:
Define service to retrieve from firestore:
const Firestore = require('#google-cloud/firestore');
const getItems = () => {
const db = new Firestore({
projectId: '*******',
keyFilename: "******"
});
db.collection('items').get()
.then((snapshot) => {
return snapshot;
})
}
Define them in routes.js:
const Router = require('#koa/router');
const articleService = require('./services/itemservice');
const router = new Router();
router.get('/getitems', async(ctx, next) => {
ctx.body = articleService.getItems();
});
module.exports = router;
Add routes to retrieve from routes.js:
app.use(router.routes());
app.use(router.allowedMethods());
And finally call it from a component:
let articles = axios.get('/getitems')
.then(response => {
console.log(response);
})//.....
I am receiving this error:
response:
{ status: 404,
statusText: 'Not Found',
headers:
{ 'content-type': 'text/html; charset=us-ascii',
server: 'Microsoft-HTTPAPI/2.0',
date: 'Fri, 25 Oct 2019 16:08:00 GMT',
connection: 'close',
'content-length': '315' },
config:
{ url: '/getarticles',
method: 'get',
headers: [Object],
transformRequest: [Array],
transformResponse: [Array],
timeout: 0,
adapter: [Function: httpAdapter],
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
data: undefined },
request:
ClientRequest {
_header:
'GET /getitems HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nUser-Agent: axios/0.19.0\r\nHost: localhost\r\nConnection: close\r\n\r\n',
_onPendingData: [Function: noopPendingOutput],
agent: [Agent],
socketPath: undefined,
timeout: undefined,
method: 'GET',
path: '/getitems',
_ended: true,
res: [IncomingMessage],
aborted: undefined,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
_redirectable: [Writable],
[Symbol(isCorked)]: false,
[Symbol(outHeadersKey)]: [Object] },
data:
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">\r\n<HTML><HEAD><TITLE>Not Found</TITLE>\r\n<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>\r\n<BODY><h2>Not Found</h2>\r\n<hr><p>HTTP Error 404. The requested resource is not found.</p>\r\n</BODY></HTML>\r\n' },
isAxiosError: true,
toJSON: [Function] }
Can anyone point me in the right direction?
I've never built an app with Nuxt, but I'll try to help you anyway.
First, I recommend you to read about Promises:
- https://github.com/leonardomso/You-Dont-Know-JS/blob/master/async%20%26%20performance/ch3.md
- https://github.com/leonardomso/You-Dont-Know-JS/blob/master/es6%20%26%20beyond/ch8.md
(those are two chapters of a good JS book series!)
Second, you can try two things in order to find the bug:
- add a .catch block to your thenables, to check if something went wrong;
- add a dummy route that just logs an 'OK', to make sure the routes are be registered and up to respond.
I hope this will help you!
I had this problem with my nuxt / express.js app:
If you would try to type in your browser yourURL/getitems your nuxt app will try to route you to that page instead of just to show u the data.
First thing to do, how to say, you need to define what url your backend should handle.
You go to your nuxt.config.js and add this line of code:
serverMiddleware: ["~/api/index.js"],
That means you have a folder called api and in that folder you have an index.js file and thats your express.js / koa app.
Now in your index.js where your express.js / koa app is you need to add at the end of the line this peace of code:
module.exports = {
path: "/api",
handler: app
};
If everything works fine your URL should have now a prefix api and you should be able to get the data with localhost:PORT/api/getitems
Now nuxt wont try to route you to your url/api because it knows now that this is your backend
If you could provide me your folder structure of your nuxt app i could help you more.
Here is more information about serverMiddleware
https://nuxtjs.org/api/configuration-servermiddleware
EDIT:
somewhere you have a Folder, lets say ist named server or api
in that Folder there should be a index.js file and your routes, model, Controllers etc.
Lets say you have a Folder called server and in that Server you have index.js that should look something like this
const Koa = require('koa');
const app = new Koa();
Import routes from "./routes.js"
app.use(routes)
//here you define now your backend path
module.exports = {
//you can use any path you want
path: "/backend",
handler: app
};
app.listen(3000);
Now you Need to go to your nuxt.config.js file and Point to that index.js File
serverMiddleware: ["~/server/index.js"]
Now you can Access your data with axios:
axios.get("/backend/getitems").then(data => { console.log(data) })
You will Need to add backend to your axios url because thats the path you defined that your Server will handle.

How to parse a json file with nodejs

I got a little problem with the nodejs fetch module and more particularly with the JSON parse. When I want to parse the stock variable, he tells me that the size is equal to 0 ? But my file is not empty and the path is good.
The code is really simple but I don't know why this error append and I spend too much time on this.
Someone know why I get this error and how I can resolve it ?
here the code of my js file :
const fetch = require('node-fetch');
const keyword='test';
const url='http://localhost:8888/test.json';
fetch(url).then((stock) => {
console.log(stock);
const jsonFile = JSON.parse(stock);
const newCategory = jsonFile[test];
console.log(newCategory);
}).catch((e)=>{console.log(e)});
And the error in my terminal with the first console.log() :
Response {
size: 0,
timeout: 0,
[Symbol(Body internals)]:
{ body:
PassThrough {
_readableState: [ReadableState],
readable: true,
_events: [Object],
_eventsCount: 2,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: true,
_transformState: [Object] },
disturbed: false,
error: null },
[Symbol(Response internals)]:
{ url: 'http://localhost:8888/test.json',
status: 200,
statusText: 'OK',
headers: Headers { [Symbol(map)]: [Object] },
counter: 0 } }
SyntaxError: Unexpected token o in JSON at position 1
at JSON.parse (<anonymous>)
at fetch.then (/Users/me/Desktop/test_json/index.js:11:30)
at process._tickCallback (internal/process/next_tick.js:68:7)
The fetch api returns a Body object
you can call Body.json()
Using async/await:
const body = await fetch(url);
const json = await body.json();
console.log(json);
Using promises:
fetch(url).then((stock) => {
return stock.json()
}).then(json => {
console.log(json);
});
JSON.parse:
fetch(url).then((stock) => {
return stock.text()
}).then(text => {
console.log(JSON.parse(text));
});
You need to pass the body in json parse like bellow,
JSON.parse(stock.text())
Or you can directly use json data without parsing just using stock.json() function

node-soap - Proper method of calling function

I know absolutely nothing about SOAP lol, But a vital part of my software requires I use it for a particular webservice. The documentation for the webservice was written for .net so it makes it even harder for me to understand what I need to do here. On top of all that they require authentication.
For the connecting I do not need to authorize so I am able to retreive the describe function result. They are as follows:
I20151214-09:20:20.381(-8)? Getting inside soap client creation method
I20151214-09:20:20.722(-8)? Exception while invoking method 'createSoapClient' TypeError: Cannot call method 'describe' of undefined
I20151214-09:20:20.723(-8)? at Object.Soap.createClient (packages/zardak_soap/packages/zardak_soap.js:37:1)
I20151214-09:20:20.724(-8)? at [object Object].Meteor.methods.createSoapClient (controllers/server/testFiles.js:21:1)
I20151214-09:20:20.724(-8)? at maybeAuditArgumentChecks (livedata_server.js:1698:12)
I20151214-09:20:20.725(-8)? at livedata_server.js:708:19
I20151214-09:20:20.725(-8)? at [object Object]._.extend.withValue (packages/meteor/packages/meteor.js:1013:1)
I20151214-09:20:20.726(-8)? at livedata_server.js:706:40
I20151214-09:20:20.726(-8)? at [object Object]._.extend.withValue (packages/meteor/packages/meteor.js:1013:1)
I20151214-09:20:20.726(-8)? at livedata_server.js:704:46
I20151214-09:20:20.727(-8)? at tryCallTwo (C:\Users\Media Center\AppData\Local\.meteor\packages\promise\0.5.1\npm\node_modules\meteor-promise\node_modules\promise\lib\core.js:45:5)
I20151214-09:20:20.727(-8)? at doResolve (C:\Users\Media Center\AppData\Local\.meteor\packages\promise\0.5.1\npm\node_modules\meteor-promise\node_modules\promise\lib\core.js:171:13)
I20151214-09:20:21.996(-8)? Getting inside the return of the create client
I20151214-09:20:22.007(-8)? { PRIMEStandardV1_1:
I20151214-09:20:22.008(-8)? { PRIMEStandardV1_1Soap:
I20151214-09:20:22.009(-8)? { RunTrip: [Object],
I20151214-09:20:22.009(-8)? ReverseGeocode: [Object],
I20151214-09:20:22.010(-8)? FindLocationsInRadius: [Object],
I20151214-09:20:22.010(-8)? FindLocationsOnRoute: [Object],
I20151214-09:20:22.010(-8)? FindLocationsInState: [Object],
I20151214-09:20:22.011(-8)? GetAverageDieselPriceInState: [Object],
I20151214-09:20:22.012(-8)? TestRadiusGeofence: [Object],
I20151214-09:20:22.012(-8)? TestRouteGeofence: [Object],
I20151214-09:20:22.013(-8)? RunSimpleTrip: [Object],
I20151214-09:20:22.013(-8)? Geocode: [Object],
I20151214-09:20:22.014(-8)? GetTodaysUSDieselAverage: [Object],
I20151214-09:20:22.014(-8)? GetTodaysCanadianDieselAverage: [Object],
I20151214-09:20:22.015(-8)? GetTripDistance: [Object],
I20151214-09:20:22.016(-8)? ValidateLocation: [Object] },
I20151214-09:20:22.017(-8)? PRIMEStandardV1_1Soap12:
I20151214-09:20:22.017(-8)? { RunTrip: [Object],
I20151214-09:20:22.018(-8)? ReverseGeocode: [Object],
I20151214-09:20:22.019(-8)? FindLocationsInRadius: [Object],
I20151214-09:20:22.021(-8)? FindLocationsOnRoute: [Object],
I20151214-09:20:22.021(-8)? FindLocationsInState: [Object],
I20151214-09:20:22.022(-8)? GetAverageDieselPriceInState: [Object],
I20151214-09:20:22.022(-8)? TestRadiusGeofence: [Object],
I20151214-09:20:22.023(-8)? TestRouteGeofence: [Object],
I20151214-09:20:22.023(-8)? RunSimpleTrip: [Object],
I20151214-09:20:22.024(-8)? Geocode: [Object],
I20151214-09:20:22.025(-8)? GetTodaysUSDieselAverage: [Object],
I20151214-09:20:22.025(-8)? GetTodaysCanadianDieselAverage: [Object],
I20151214-09:20:22.026(-8)? GetTripDistance: [Object],
I20151214-09:20:22.026(-8)? ValidateLocation: [Object] } } }
caseless:
I20151216-11:53:14.658(-8)? { dict:
I20151216-11:53:14.658(-8)? { 'cache-control': 'private',
I20151216-11:53:14.659(-8)? 'content-type': 'text/xml; charset=utf- 8',
I20151216-11:53:14.659(-8)? server: 'Microsoft-IIS/7.0',
I20151216-11:53:14.660(-8)? 'x-aspnet-version': '4.0.30319',
I20151216-11:53:14.660(-8)? 'x-powered-by': 'ASP.NET',
I20151216-11:53:14.661(-8)? date: 'Wed, 16 Dec 2015 19:40:29 GMT',
I20151216-11:53:14.661(-8)? connection: 'close',
I20151216-11:53:14.662(-8)? 'content-length': '441' } },
I20151216-11:53:14.662(-8)? pipe: [Function],
I20151216-11:53:14.663(-8)? addListener: [Function: addListener],
I20151216-11:53:14.664(-8)? on: [Function: addListener],
I20151216-11:53:14.665(-8)? pause: [Function],
I20151216-11:53:14.665(-8)? resume: [Function],
I20151216-11:53:14.666(-8)? read: [Function],
I20151216-11:53:14.666(-8)? body: 'soap:ServerServer was unable to process request. ---> Object reference not set to an instance of an object.' }
I20151216-11:53:16.716(-8)? Error: [object Object]
I20151216-11:53:16.722(-8)? { Envelope: { Body: { Fault: [Object] } } }
I20151216-11:53:16.723(-8)? undefined
As you can see I am able to connect. Now the part that is trowing me off is to actually call one of these functions. Below is the code I am using to try to call the "RunSimpleTrip". However when I console log the Result it is a huge jumble of messages that end up running the buffer out on my cmd window and I can only see back a little ways none of it making sense.
var url = 'http://prime.promiles.com/Webservices/v1_1/PRIMEStandardV1_1.asmx?wsdl';
var simpleTrip = {
AvoidTollRoads: false,
BorderOpen: true,
RoutingMethod: "PRACTICAL",
TripLegs: [{LocationText: "77611"},
{LocationText: "90210"}]
}
Soap.createClient(url, function(err, client) {
console.log(client.describe());
client.setSecurity(new Soap.BasicAuthSecurity('hoperd', 'mailaaron', 'bkkyt'));
client.PRIMEStandardV1_1.PRIMEStandardV1_1Soap.RunSimpleTrip(simpleTrip, function(err, result, raw, soapHeader) {
//console.log("Result: ");
console.log(result);
console.log("Error: " + err.root);
console.log(err.root);
console.log(soapHeader);
// result is a javascript object
// raw is the raw response
// soapHeader is the response soap header as a javascript object
})
});
From the API's documentation this is how they call the same function using .net
PRIMEEnterpriseV1 PRIME = new PRIMEEnterpriseV1();
//Authorization Credentials
Credentials c = new Credentials();
c.Username = "MyUsername;
c.Password = "MyPassword";
c.CompanyCode ="MyCompanyCode";
SimpleTrip st = new SimpleTrip();
st.AvoidTollRoads = false;
st.BorderOpen = true;
st.RoutingMethod = com.promiles.PRIME.Enterprise.RouteMethod.PRACTICAL;
TripLeg[] Legs = new TripLeg[2];
//Origin
TripLeg t = new TripLeg();
t.LocationText = "77611";
Legs[0] = t;
//Destination
t = new TripLeg();
t.LocationText = "90210";
Legs[1] = t;
st.TripLegs = Legs;
//Call Function
SimpleTrip rt = PRIME.RunSimpleTrip(c, st);
I am hoping someone our there has a clue to this mystery for me or can point me in the right direction as to how to properly connect this this. Any and all help will be greatly appreciated.
So after much trial and error I was able to figure this out. The below code works to call the SimpleTrip and return a proper response from the server. My TripLegs arg still isn't 100% correct to what the SOAP is looking for but the code and the way to call it is.
var url = 'http://prime.promiles.com/Webservices/v1_1/PRIMEStandardV1_1.asmx?wsdl';
var credentials = { Username: "xxxxx",
Password: "xxxxxx",
CompanyCode: "xxxxx"
};
var simpleTrip = {
AvoidTollRoads: false,
BorderOpen: true,
RoutingMethod: "PRACTICAL",
VehicleType: "Tractor2AxleTrailer2Axle",
TripLegs: [{Location: {LocationText: "77611"}},
{Location: {LocationText: "90210"}}]
}
args = {c: credentials, BasicTrip: simpleTrip};
Soap.createClient(url, function(err, client) {
console.log(err);
console.log(simpleTrip);
client.RunSimpleTrip(args, function(err, result, raw, soapHeader) {
console.log(result);
//console.log(err.root);
console.log(err.root.Envelope);
})
});

Resources