Async API call error - twitter

I'm currently trying to call the twitter API using meteor and so far i got this:
updateTotalFoll:function(){
var Twit = Meteor.npmRequire('twit');
var T = new Twit({
consumer_key: 'AWzYAlWFRh9zsownZMg3',
consumer_secret: 'aYpL3zMPfqRgtX1usPQpEREEXVNPfNYna9FiIwTeDYR',
access_token: '4175010201-TEp9qNKO4mvjkj0GMjJFZIbGPYaVv4',
access_token_secret: 'EPpcJyN27E4PvhJpYaTHflNFOv3DuR05kTP2j'
});
var Id2=RandomCenas.findOne({api:"twitter"})._id;
T.get('statuses/user_timeline', { screen_name: 'jeknowledge' }, function (err, data, response){
//console.log(data[0].user.followers_count);
RandomCenas.update(Id2,{$set:{totalFoll:data[0].user.followers_count}});
});
}
with "RandomCenas" being a MongoDB.
What i'm trying to do is updating this collection with the info from the call , but i get this error
Error: Meteor code must always run within a Fiber.
Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.
I've searched the web for a way to counter this , but i cant seem to apply the solutions that i came across with.
Any help with how i can deal with this?

try it like that
T.get('statuses/user_timeline', { screen_name: 'jeknowledge' }, Meteor.bindEnvironment(function (err, data, response) {
//console.log(data[0].user.followers_count);
RandomCenas.update(Id2,{$set:{totalFoll:data[0].user.followers_count}});
}));
the reason this is happening is because callback function which you pass it's happening outside the current Meteor's Fiber check the answer Error: Meteor code must always run within a Fiber

Related

Using Stripe Terminal iOS SDK with Nativescript

I'm attempting to use the Stripe Terminal SDK in the Nativescript plugin seed and test it in the demo-angular app. I'm able to initialize the SDK by setting the connection token provider. When the SDK calls the provider's fetchConnectionToken method, the app crashes with no terminal output when the method calls the SDK-supplied completion handler. Debugging in XCode shows _EXC_BAD_ACCESS code=2.
Relevant code:
iOSFetchConnectionToken(completion: (p1: string, p2: NSError) => void) {
/* No crash if the following two lines are uncommented */
// completion(hardCodedTokenSecret, nullError);
// return;
Http.request({
url: DemoSharedStripeterminalBasic.serverAddress,
method: 'POST',
headers: {
"Content-Type": "application/json",
"Stripe-Public-Key": this.stripeTestKey
},
content: JSON.stringify({
connectedAccountId: this.connectedAccountId
})
}).then(response => {
const result = response.content?.toJSON();
secret = result.secret;
completion(secret, null); // App crashes with no output
})
}
The above function is assigned to the ConnectionTokenProvider's fetchConnectionToken method. I'm able to call the completion handler successfully before the HTTP request (using hardcoded or null values – see the commented lines at the top), but the crash occurs when I invoke the completion handler in the "then" block of the request, using either the returned value from my API server or a hardcoded/null value. Logging out the completion function gives "function () { [native code] }" which indicates that it's properly accessible in memory. I can't figure out where the bad access is coming from or why it's only happening inside the "then" block.
In the sample above, I'm using Nativescript's built in HTTP module, but I've also tried with JS fetch and have the same issue. I've also tried rewriting using async/await with no luck. My API server correctly returns a valid token (I successfully used the same one for the hard-coded token secret), so I know that isn't the issue either. Any help is hugely appreciated, thanks!

"message" : "Internal server error" issue with Lambda/API Gateway and iOS

I've set up a lambda function and created some GET and POST methods inside the API Gateway which seem to work fine when testing them inside the web application.
I am then trying to call the functions inside an iOS application which is set up using the mobile hub. The functions also work inside the testing facility via the mobile hub perfectly fine, however when I actually test the functions inside the app I get:
"message" : "Internal server error"
I know the error is not much to work from, but I can't figure out a way to get a more detailed error description.
Any ideas?
This may happen because your Lambda function is not set to return a HTTP status code.
Changing from
exports.handler = (event, context, callback) => {
callback(null, 'Hello from Lambda');
};
to
exports.handler = (event, context, callback) => {
callback(null, { statusCode: 200, body: 'Hello from Lambda' });
};
Should fix the issue.
The JSON.stringify() solved my issue. The response.body needs to be in String format and not as JSON. I hope this helps.
exports.sendRes = (body, status = 200) => {
var response = {
statusCode: status,
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(body)
};
return response;
};
I had the same issue with the following code:
exports.handler = async event => {
console.log("hello world");
return {
statusCode: 200,
body: event
};
};
To fix all I had to do was JSON.stringify() the body.
exports.handler = async event => {
console.log("hello world");
return {
statusCode: 200,
body: JSON.stringify(event), // <-- here
};
};
I had this problem until I click in "Deploy API" under the "Actions" button.
The other possible reason could be the payload/request/response limits on API Gateway (10MB) and/or Lambda (6MB)
None of the above answers worked for me. I was having a permission issue. Below is how I solved it.
Context
This is my lambda function:
exports.handler = function(event, context, callback) {
callback(null, {
statusCode: '200',
body: JSON.stringify({ 'message': 'hello world' }),
headers: {
'Content-Type': 'application/json',
},
});
};
I used terraform to provision api gateway and lambda. I used the example code provided by this blog post.
Diagnosis
In the lambda console I ran a test event on my lambda. As my lambda was super basic I used the hello world test template, named, and saved it. The test return success.
I checked cloudwatch logs, but couldn't find anything of use. I'm new to AWS so wasn't sure if I had to set anything up.
In the api gateway console I ran a test event. I just added Content-Type:application/json to the headers of the event and ran the test. For whatever weird reason the test results returned on the right side of the browser so had to scroll to the right to see them.
I got this result: Execution failed due to configuration error: Invalid permissions on Lambda function
SOLUTION
I checked the basic terraform example for api gateway and lambda integration here and noticed I was missing the aws_lambda_permission resource. This is needed to give permission to api gateway to invoke the lambda function.
For those that aren't using terraform here is a link to the aws docs on how to create the appropriate permissions.
please try to
Give execute lambda permission API Gateway
tick checkbox : Use Lambda Proxy integration
Handle null pointer for query string, headers & body.
I solved the issue by adding "isBase64Encoded": False/True to my lambda response
results = {
"statusCode": 200,
"headers": {"Content-Type": "application/json"},
"body": json.dumps(res),
"isBase64Encoded": False
}
In my case, the issue resolved while adding the integration Response and redeploying API

Parse-server Cloud Code Error 141 Invalid Function

I am running parse-server on Heroku, I am working on implementing a custom cloud code function, however every implementation returns invalid function code: 141, Version:1.12.0
I have successfully gotten the "hello" function to work, including 1 change I made to it:
Parse.Cloud.define('hello', function(req, res) {
console.log("received.........");
res.success('Hi');
});
The custom function I am trying to get working is a simple query to my database:
Parse.Cloud.define("titleQuery", function(request, response) {
var query = new Parse.Query("StudentNotes");
query.equalTo("title", request.params.title);
query.find({
success: function(results) {
console.log("received........." + results);
response.success(results);
},
error: function() {
console.log("received........." + error);
response.error("title lookup failed");
}
});
});
When I run this on iOS with the following code:
PFCloud.callFunctionInBackground("titleQuery", withParameters: ["title": "testTitle"]) {
(response: AnyObject ? , error : NSError ? ) - > Void in
let hello = response // as? String
print(hello)
}
I am querying my database in class "StudentNotes" for object title with the name "testTitle", I know for a fact that that object exists, however due to it throwing error 141 I do not receive anything. Any help would be greatly appreciated.
EDIT2: I have gotten custom cloud functions to work, however I cannot get any queries to my database to work. Can anyone post a confirmed working query that returns an object? Perhaps from the _User table so that I can copy/paste and ensure that my cloud code can access my database?
My process:
I edit the Main.js file and add in my cloud function.
Then i commit & push (successfully)
finally i restart my Heroku server
Then i still get an error 141 invalid function return
I have successfully solved this problem and gotten regular queries to work. The problem was in my Heroku config vars in the dashboard. My server URL was invalid, never changed from the default of "http://yourappname.com/parse/" I have to manually enter "yourappname".

How to retrieve Medium stories for a user from the API?

I'm trying to integrate Medium blogging into an app by showing some cards with posts images and links to the original Medium publication.
From Medium API docs I can see how to retrieve publications and create posts, but it doesn't mention retrieving posts. Is retrieving posts/stories for a user currently possible using the Medium's API?
The API is write-only and is not intended to retrieve posts (Medium staff told me)
You can simply use the RSS feed as such:
https://medium.com/feed/#your_profile
You can simply get the RSS feed via GET, then if you need it in JSON format just use a NPM module like rss-to-json and you're good to go.
Edit:
It is possible to make a request to the following URL and you will get the response. Unfortunately, the response is in RSS format which would require some parsing to JSON if needed.
https://medium.com/feed/#yourhandle
⚠️ The following approach is not applicable anymore as it is behind Cloudflare's DDoS protection.
If you planning to get it from the Client-side using JavaScript or jQuery or Angular, etc. then you need to build an API gateway or web service that serves your feed. In the case of PHP, RoR, or any server-side that should not be the case.
You can get it directly in JSON format as given beneath:
https://medium.com/#yourhandle/latest?format=json
In my case, I made a simple web service in the express app and host it over Heroku. React App hits the API exposed over Heroku and gets the data.
const MEDIUM_URL = "https://medium.com/#yourhandle/latest?format=json";
router.get("/posts", (req, res, next) => {
request.get(MEDIUM_URL, (err, apiRes, body) => {
if (!err && apiRes.statusCode === 200) {
let i = body.indexOf("{");
const data = body.substr(i);
res.send(data);
} else {
res.sendStatus(500).json(err);
}
});
});
Nowadays this URL:
https://medium.com/#username/latest?format=json
sits behind Cloudflare's DDoS protection service so instead of consistently being served your feed in JSON format, you will usually receive instead an HTML which is suppose to render a website to complete a reCAPTCHA and leaving you with no data from an API request.
And the following:
https://medium.com/feed/#username
has a limit of the latest 10 posts.
I'd suggest this free Cloudflare Worker that I made for this purpose. It works as a facade so you don't have to worry about neither how the posts are obtained from source, reCAPTCHAs or pagination.
Full article about it.
Live example. To fetch the following items add the query param ?next= with the value of the JSON field next which the API provides.
const MdFetch = async (name) => {
const res = await fetch(
`https://api.rss2json.com/v1/api.json?rss_url=https://medium.com/feed/${name}`
);
return await res.json();
};
const data = await MdFetch('#chawki726');
To get your posts as JSON objects
you can replace your user name instead of #USERNAME.
https://api.rss2json.com/v1/api.json?rss_url=https://medium.com/feed/#USERNAME
With that REST method you would do this: GET https://api.medium.com/v1/users/{{userId}}/publications and this would return the title, image, and the item's URL.
Further details: https://github.com/Medium/medium-api-docs#32-publications .
You can also add "?format=json" to the end of any URL on Medium and get useful data back.
Use this url, this url will give json format of posts
Replace studytact with your feed name
https://api.rss2json.com/v1/api.json?rss_url=https://medium.com/feed/studytact
I have built a basic function using AWS Lambda and AWS API Gateway if anyone is interested. A detailed explanation is found on this blog post here and the repository for the the Lambda function built with Node.js is found here on Github. Hopefully someone here finds it useful.
(Updating the JS Fiddle and the Clay function that explains it as we updated the function syntax to be cleaner)
I wrapped the Github package #mark-fasel was mentioning below into a Clay microservice that enables you to do exactly this:
Simplified Return Format: https://www.clay.run/services/nicoslepicos/medium-get-user-posts-new/code
I put together a little fiddle, since a user was asking how to use the endpoint in HTML to get the titles for their last 3 posts:
https://jsfiddle.net/h405m3ma/3/
You can call the API as:
curl -i -H "Content-Type: application/json" -X POST -d '{"username":"nicolaerusan"}' https://clay.run/services/nicoslepicos/medium-get-users-posts-simple
You can also use it easily in your node code using the clay-client npm package and just write:
Clay.run('nicoslepicos/medium-get-user-posts-new', {"profile":"profileValue"})
.then((result) => {
// Do what you want with returned result
console.log(result);
})
.catch((error) => {
console.log(error);
});
Hope that's helpful!
Check this One you will get all info about your own post........
mediumController.getBlogs = (req, res) => {
parser('https://medium.com/feed/#profileName', function (err, rss) {
if (err) {
console.log(err);
}
var stories = [];
for (var i = rss.length - 1; i >= 0; i--) {
var new_story = {};
new_story.title = rss[i].title;
new_story.description = rss[i].description;
new_story.date = rss[i].date;
new_story.link = rss[i].link;
new_story.author = rss[i].author;
new_story.comments = rss[i].comments;
stories.push(new_story);
}
console.log('stories:');
console.dir(stories);
res.json(200, {
Data: stories
})
});
}
I have created a custom REST API to retrieve the stats of a given post on Medium, all you need is to send a GET request to my custom API and you will retrieve the stats as a Json abject as follows:
Request :
curl https://endpoint/api/stats?story_url=THE_URL_OF_THE_MEDIUM_STORY
Response:
{
"claps": 78,
"comments": 1
}
The API responds within a reasonable response time (< 2 sec), you can find more about it in the following Medium article.

Meteor Twitter Help (Meteor NOOB)

I just started learning MeteorJS and after completing the tutorial, I decided to play around with the Twitter API. Initially, I followed this tutorial
http://artsdigital.co/exploring-twitter-api-meteor-js/
Once completing that, what I wanted to do is scrape data from a tweet and display it on the client side.
N/A = proper authentication
Here's the code I've written:
if (Meteor.isClient) {
Session.setDefault('screen_name', 'John');
Template.hello.helpers({
screen_name: function () {
return Session.get('screen_name');
}
});
Template.hello.events({
'click button': function () {
T.get('search/tweets',
{
q: '#UCLA',
count: 1
},
function(err,data,response) {
var user_name = data.statuses[0].users.screen_name;
Session.set('screen_name', user_name);
}
)
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
var Twit = Meteor.npmRequire('twit');
var T = new Twit({
consumer_key: 'N/A', // API key
consumer_secret: 'N/A', // API secret
access_token: 'N/A',
access_token_secret: 'N/A'
});
});
}
What I believe the problem is that, the 'click button' function, the 'T' is seen to be undefined so the compiler doesn't know what that is or where it came. That thought did spark a thought in my mind to move what I have written inside the
if (Meteor.isServer) to if (Meteor.isClient)
But to no avail. It didn't work. What my reasoning is that once Meteor starts, the server starts, so if the server declares the variable T, shouldn't we be able to access it on the client side too?
I'm not sure if my approach is correct/don't know the conventions of Meteor/Meteor NOOB..so if someone could please help me, that will be highly appreciated!
Thanks!
You put a "var" declaration in front of your "T" variable. This binds the scope to the server side context of the app. I bet if you got rid of the var and made "T" global, then you would be able to access it from the client side as well.

Resources