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.
Related
I'm trying to use the github-oauth2 provider in Torii, but I'm stumped on how I'm supposed to se tup some of the callbacks. I'll trace the code I'm using, as well as my understanding of it, and hopefully that can help pinpoint where I'm going wrong.
First, in my action, I'm calling torii's open method as it says to do in the docs:
this.get('torii').open('github-oauth2').then((data) => {
this.transitionTo('dashboard')
})
And, of course, I have the following setup in my config/environment.js:
var ENV = {
torii: {
// a 'session' property will be injected on routes and controllers
sessionServiceName: 'session',
providers: {
'github-oauth2': {
apiKey: 'my key',
redirectUri: 'http://127.0.0.1:3000/github_auth'
}
}
},
}
The redirectUri is for my Rails server. I have the same redirectUri setup on my github app, so they match.
Here's what I have on my server. It's likely this is where the problem is. I'll get to the symptoms at the end.
def github
client_id = 'my id'
client_secret = 'my secret'
code = params[:code]
#result = HTTParty.post("https://github.com/login/oauth/access_token?client_id=#{client_id}&client_secret=#{client_secret}&code=#{code}")
#access_token = #result.parsed_response.split('&')[0].split('=')[1]
render json: {access_token: #access_token}
end
So I post to github's access_token endpoint, as I'm supposed to, and I get back a result with an access token. Then I package up that access token as json.
The result of this is that the torii popup goes to the rails page:
Unfortunately, what I was hoping for was for the torii popup to disappear, give my app the access_token, and for the code to move on and execute the code in my then block.
Where am I going wrong?
Many thanks to Kevin Pfefferle, who helped me solve this and shared the code to his app (gitzoom) where he had implemented a solution.
So the first fix is to clear my redirectUri, and to set it on github to localhost:4200. This made the app redirect so that it's an Ember app that it's redirected to.
The second fix was to create a custom torii provider
//app/torii-providers/github.js
import Ember from 'ember';
import GitHubOauth2Provider from 'torii/providers/github-oauth2';
export default GitHubOauth2Provider.extend({
ajax: Ember.inject.service(),
fetch(data) {
return data;
},
open() {
return this._super().then((toriiData) => {
const authCode = toriiData.authorizationCode;
const serverUrl = `/github_auth?code=${authCode}`;
return this.get('ajax').request(serverUrl)
.then((data) => {
toriiData.accessToken = data.token;
return toriiData;
});
});
}
});
Not sure why this then triggers but the then I was using before didn't. Anyways, it grabs the data and returns it, and then the promise I was using before gets the data correctly.
this.get('torii').open('github-oauth2').then((data) => {
//do signon stuff with the data here
this.transitionTo('dashboard')
})
So there we go! Hopefully this helps other folks who are stuck in the future.
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
This is a question about best practices for making the JavaScript call that generates the standard "Connect to QuickBooks" button (for establishing a connection to QuickBooks Harmony via Intuit's v3 REST API).
If I follow Intuit's example, I would:
Reference https://appcenter.intuit.com/Content/IA/intuit.ipp.anywhere.js in a script tag.
Place the <ipp:connectToIntuit></ipp:connectToIntuit> tagset where I want the "Connect to QuickBooks" button to display
Cross my fingers and hope that intuit.ipp.anywhere.js isn't redirecting to a downtime message, again still exists
Make my call to intuit.ipp.anywhere.setup()
See the "Connect to QuickBooks" button
... which works (for many values of "works"), but feels pretty fragile:
If intuit.ipp.anywhere.js is redirecting to a downtime message (read: not JavaScript) or is otherwise unavailable, I'll get a script error.
If I get a script error (or something else goes wrong with Intuit's copy of the script), there isn't any feedback to the user, just a blank space where the "Connect to QuickBooks" button should be.
To make this all a little more resilient, I'm combining the reference to intuit.ipp.anywhere.js and the call to intuit.ipp.anywhere.setup() into a JQuery .ajax() call:
$.ajax({
url: 'https://appcenter.intuit.com/Content/IA/intuit.ipp.anywhere.js',
type: 'GET',
dataType: 'script',
timeout: 4000,
success: function(response) {
if (typeof intuit !== 'undefined') {
intuit.ipp.anywhere.setup({
menuProxy: 'MYMENUPROXYURL.aspx',
grantUrl: 'MYGRANTURL.aspx'
});
}
},
error: function(x, t, m) {
// show some friendly error message about Intuit downtime
}
});
... which also works (for a few more values of "works"):
My call to setup() is wrapped inside the success handler (and an additional check on the existence of the intuit Object), so I shouldn't get a script error if things go wrong.
If the GET of Intuit's script times out (after 4000ms) or returns something that isn't script, I'll show a friendly error message to the user.
Has anyone else taken a different approach?
And is Intuit back online?
That's similar to how we've handled it. We had wrapped it in jQuery.getScript call, but apparently the .fail handler doesn't work with cross domain script tags. Our solution is as follows:
<script type="text/javascript>
var timeoutID;
timeoutID = window.setTimeout(function () {
$("#ippConnectToIntuit").replaceWith('<p class="error-message">There was a problem communicating with QuickBooks. The service may be down or in heavy use. Try again later.</p>');
}, 5000);
$.getScript("https://appcenter.intuit.com/Content/IA/intuit.ipp.anywhere.js")
.done(function () {
window.clearTimeout(timeoutID);
intuit.ipp.anywhere.setup({
menuProxy: '/path/to/our/menu/proxy',
grantUrl: '/path/to/our/grant/url'
});
});
</script>
<div id="ippConnectToIntuit"><ipp:connecttointuit></ipp:connecttointuit></div>
Just a simple question:
I am using YUI3 framework for my website and want to use socket.io framework.
Now challenge is to use socket.io with YUI3.
As of now I am using socket.io logic inside YUI sandbox and its working fine.
BUT can there be any fallback of this approach ? If yes, then how should I integerate both ?
Here is the snippet of code:
<script type="text/javascript">
YUI().use('my-slide' , 'node', 'event','transition', function (Y) {
// connecting to nodejs server running on 7001 port for dynamic updates
var broadcast = io.connect('http://localhost:7001/getlatestbroadcast');
broadcast.on('status',function(data){
// some socket logic here
});
// Setting Listener
broadcast.on('moreData',function(data){
// some socket logic here
});
});
</script>
What you're doing definitely works, and there's no problem in using it that way unless you have a conflict with some other variable named io. A slightly more effective way of using Socket.IO (or any other external module in YUI) is to namespace it on the Y object instead:
YUI({
modules: {
'socket.io': {
fullpath: '/socket.io/socket.io.js'
}
},
onProgress: function (e) {
if (e.data[0].name === 'socket.io') {
YUI.add('socket.io', function (Y) {
Y.Socket = io;
});
}
}
}).use('socket.io', function (Y) {
var socket = Y.Socket.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
});
This takes the example from the socket.io website and lets you namespace it as Y.Socket. That way, only when you specifically do YUI().use('socket.io'), will you actually be able to access Y.Socket, which helps with keeping your code organized and loaded in the correct order, thanks to the YUI Loader.
Also, feel free to check out the Socket Model Sync YUI Gallery module I created, if you're looking for an easier way to integrate your YUI App Framework application with Socket.IO.
Hope this helps, and let me know if you have any more questions about integrating the two!
I get this error: Unexpected exception upon serializing continuation (not much help)
It is caused by the FetchUrlApp.fetch(); call. I akm using Google Apps Script for Sites, not Google Spreadsheets. The code works in the original instance but as soon as I copy and paste the code into a new project I get the above error message. I am accessing Google Docs APIs. I have read on other forums that I need authorization but I have been unable to gain the right authorization for the code to work. No prompt ever pops up when I run a copy of the code for the first time.
Code exert:
var oauthConfig = UrlFetchApp.addOAuthService("docs");
oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope=https://docs.google.com/feeds/");
oauthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oauthConfig.setConsumerKey(_consumerKey_);
oauthConfig.setConsumerSecret(_consumerSecret_);
var requestData3 = {
"method": "GET",
"headers": {"GData-Version": "3.0"},
"oAuthServiceName": "docs",
"oAuthUseToken": "always",
};
var url = "https://docs.google.com/feeds/" + userName + "/private/full/-/mine";
var result = UrlFetchApp.fetch(url, requestData3); //error occurs, any thoughts?
Thank you in advance,
James Krimm
You have to set both consumerKey and consumerSecret to "anonymous" in order to trigger the 3-legged OAuth process:
oauthConfig.setConsumerKey("anonymous");
oauthConfig.setConsumerSecret("anonymous");
Replace your two lines with these and the authorization popup dialog will show up, allowing the user to grant access to its documents.
What I would suggest is to write a special function that does nothing else than call the Oauth process and call it from the script editor once.
As an example, here is the one I have used recently to make the authorize popup appear :
function authorize(){
// function to call from the script editor to authorize googleOauth
var id=mailtemplatedoc
var url = 'https://docs.google.com/feeds/';
var doc = UrlFetchApp.fetch(url+'download/documents/Export? exportFormat=html&format=html&id='+id,
googleOAuth_('docs',url)).getContentText();
}
EDIT : And the missing part I had forgotten :
function googleOAuth_(name,scope) {
var oAuthConfig = UrlFetchApp.addOAuthService(name);
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey('anonymous');
oAuthConfig.setConsumerSecret('anonymous');
return {oAuthServiceName:name, oAuthUseToken:"always"};
}