changeset 30:3e3fa35e3ce2

twitter sync likes, recommend mongodb configure pump2twitter, twitter2pump in webui
author Mathias Gebbe <mgebbe@intevation.de>
date Thu, 28 Aug 2014 18:40:39 +0200
parents 34cfa565f565
children 8238d312e281
files index.js_to_pump.io-client-app_lib_routes pumpbridge.json.example src/facebook.coffee src/google.coffee src/pumpio.coffee src/restartSYNC.sh src/routes.coffee src/sync.coffee src/syncALONE.coffee src/twitter.coffee src/usermap.coffee views/index.jade views/login.jade
diffstat 13 files changed, 163 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/index.js_to_pump.io-client-app_lib_routes	Tue Jul 29 16:06:05 2014 +0200
+++ b/index.js_to_pump.io-client-app_lib_routes	Thu Aug 28 18:40:39 2014 +0200
@@ -23,6 +23,7 @@
     User = require("../models/user"),
     Host = require("../models/host"),
     Usermap = require("../../../../lib/usermap"),
+    //Usermap = require("../../../../src/usermap"),
     RequestToken = require("../models/requesttoken"),
     RememberMe = require("../models/rememberme"),
     site = require("../models/site");
@@ -42,17 +43,21 @@
     var hosts, users, bank = Host.bank();
 
     if (req.user) {
-      var fb=false, gp=false, tw=false;
+      var fb=false, gp=false, tw=false, twfromesn=true, twtoesn=true;
        Usermap.search({
          user_pumpio: req.user.id
        }, function(err, result) {
           if(err) res.render('login', { pageTitle: "pumpbridge" });
           _.each(result, function(um) {
             if ( um.id.indexOf('@facebook') != -1 ) fb=true;
-            if ( um.id.indexOf('@twitter') != -1 ) tw=true;
+            if ( um.id.indexOf('@twitter') != -1 ) {
+              tw=true;
+              if(typeof um.fromesn != "undefined") twfromesn = um.fromesn;
+              if(typeof um.toesn != "undefined") twtoesn = um.toesn;
+            }
             if ( um.id.indexOf('@google') != -1 ) gp=true;
           });
-          res.render('index', { pageTitle: "pumpbridge" , user: req.user, usermapfb: fb, usermapgp: gp, usermaptw: tw});
+          res.render('index', { pageTitle: "pumpbridge" , user: req.user, usermapfb: fb, usermapgp: gp, usermaptw: tw, twfromesn: twfromesn, twtoesn: twtoesn});
          });
     } else {
         res.render('login', { pageTitle: "pumpbridge" });
--- a/pumpbridge.json.example	Tue Jul 29 16:06:05 2014 +0200
+++ b/pumpbridge.json.example	Thu Aug 28 18:40:39 2014 +0200
@@ -1,6 +1,6 @@
 {
-"driver": "redis",
-"params": {"host":"localhost","database":14,"port":6379},
+"driver": "mongodb",
+"params": {"host":"localhost","dbname": "pumpbridge"},
 "secret": "takeanother",
 "port": 443,
 "bounce": true,
--- a/src/facebook.coffee	Tue Jul 29 16:06:05 2014 +0200
+++ b/src/facebook.coffee	Thu Aug 28 18:40:39 2014 +0200
@@ -450,7 +450,6 @@
 
   https.get(options, (res) ->
     #console.log "Got response: " + res.statusCode
-
     res.on "data", (chunk) ->
       data += chunk
       return
--- a/src/google.coffee	Tue Jul 29 16:06:05 2014 +0200
+++ b/src/google.coffee	Thu Aug 28 18:40:39 2014 +0200
@@ -1,7 +1,7 @@
 # Copyright (C) 2014 by Intevation GmbH
 # Author: Mathias Gebbe <mgebbe@intevation.de>
 #
-# This file is Free Software under the Apache License, Version 2.0;
+# This file is Free Software under the Apache License, Version 3.0;
 # and comes with NO WARRANTY!
 # See the documentation coming with pumpbridge for details.
 
--- a/src/pumpio.coffee	Tue Jul 29 16:06:05 2014 +0200
+++ b/src/pumpio.coffee	Thu Aug 28 18:40:39 2014 +0200
@@ -140,6 +140,33 @@
       callback null, result
   return
 
+getLikes = (user, callback) ->
+  id = user.user_ESN.substr(0,user.user_ESN.indexOf('@'))
+  server = user.user_ESN.substr(user.user_ESN.indexOf('@')+1,user.user_ESN.length)
+  token = user.oauth_token.substr(0,user.oauth_token.indexOf(';'))
+  secret = user.oauth_token.substr(user.oauth_token.indexOf(';')+1,user.oauth_token.length)
+  # https://io.intevation.de/api/user/mgebbe/favorites
+  url = "https://" + server + "/api/user/" + id + "/favorites"
+  # get tokens and ask pump.io api for userinformation then update userdb
+  async.waterfall [
+   (callback) ->
+     Host.search {hostname: server}, callback
+   (host,callback)  ->
+     # get host from db
+     host = JSON.stringify(host)
+     host = JSON.parse(host)
+     #console.log JSON.stringify host
+     oauth = new OAuth.OAuth(host[0].request_token_endpoint, host[0].access_token_endpoint, host[0].client_id, host[0].client_secret, "1.0A", null, "HMAC-SHA1")
+     oauth.get url, token, secret, callback
+  ], (err,result) ->
+    if err
+      callback null, null
+    else
+      callback null, (result)
+  return
+
+
+
 isPublicActivity = (act) ->
   recip = []
   _.each [
@@ -159,4 +186,5 @@
 exports.getUserFeed = getUserFeed
 exports.getUser = getUser
 exports.getNote = getNote
+exports.getLikes = getLikes
 exports.postUser = postUser
--- a/src/restartSYNC.sh	Tue Jul 29 16:06:05 2014 +0200
+++ b/src/restartSYNC.sh	Thu Aug 28 18:40:39 2014 +0200
@@ -1,8 +1,8 @@
 #!/bin/bash
 
-cd /home/pumpbridge/pumpbridge/lib
+cd /home/pumpbridge/pumpbridge/src
 
-until node syncALONE.js; do
+until coffee syncALONE.coffee; do
     echo "sync crashed with exit code $?. Respawning.." >&2
     sleep 1
 done
--- a/src/routes.coffee	Tue Jul 29 16:06:05 2014 +0200
+++ b/src/routes.coffee	Thu Aug 28 18:40:39 2014 +0200
@@ -50,6 +50,10 @@
 
     twdelete = req.body.twdelete
 
+    twmode = req.body.twmode
+    if(req.body.twtoesn?) then twtoesn=true else twtoesn=false
+    if(req.body.twfromesn?) then twfromesn=true else twfromesn=false
+
     # create/update userdb entrys
     # SET THE CONNECTION BETWEENS PUMPIO AND ESN-ACCOUNT (facebook or google)
 
@@ -104,6 +108,19 @@
           saveUsermap(pumpid,fbid,token,fbtoken, (err, result) ->
             console.log 'fbsave.')
 
+    #### Twitter MODUS ###
+    if (twmode?)
+      console.log "mod tw account"
+      async.waterfall [
+        (callback) ->
+          Usermap.search {user_pumpio: twmode}, callback
+        (result, callback) ->
+          _.each result, (um) ->
+            if um.user_ESN.indexOf('@twitter') isnt -1
+              saveUsermapSelect(um.user_pumpio, um.user_ESN, um.oauth_token, um.extra_token,twfromesn,twtoesn,callback)
+            return
+       ], (err, result) ->
+
     if (fbdelete?)
       console.log "delete fb account"
       async.waterfall [
@@ -156,6 +173,25 @@
   saveMap.save (cb) ->
    #console.log 'saved.'
   callback null, saveMap
+  return
+
+# update or create usermap
+saveUsermapSelect = (pumpid, esnid, esntoken, extra, fromesn, toesn, callback) ->
+  saveMap = new Usermap(
+    id : Usermap.key(pumpid,esnid)
+    user_pumpio : pumpid
+    user_ESN : esnid
+    oauth_token : esntoken
+    extra_token : extra
+    fromesn : fromesn
+    toesn: toesn
+    created : Date.now()
+  )
+  saveMap.save (cb) ->
+   #console.log 'saved.'
+  callback null, saveMap
+  return
+
 
 # only create and not update usermap
 createUsermap = (pumpid,esnid,esntoken) ->
--- a/src/sync.coffee	Tue Jul 29 16:06:05 2014 +0200
+++ b/src/sync.coffee	Thu Aug 28 18:40:39 2014 +0200
@@ -112,6 +112,7 @@
   if network is 'twitter'
 
     post.text = post.text.replace(/(http[s]?:\/\/[^ ]+)/ig,'<a href="$1">$1<\/a>')
+
     parsed = "<img src='" + post.user.profile_image_url + "'></img> <a href='https://twitter.com/account/redirect_by_id/" + post.user.id + "'>" + post.user.name + "</a> <a href='https://twitter.com/" + post.user.screen_name + "/status/" + post.id_str + "'> writes </a> via " + network + " at " + post.created_at + ":<br><br>" + post.text
     _.each post.entities.media, (attachment) ->
       parsed += "<br><img src='" + attachment.media_url + "'></img>"
--- a/src/syncALONE.coffee	Tue Jul 29 16:06:05 2014 +0200
+++ b/src/syncALONE.coffee	Thu Aug 28 18:40:39 2014 +0200
@@ -39,9 +39,14 @@
   try
     Usermap.scan ((user) ->
       if user.id.indexOf('@twitter') isnt -1
-        console.log "start sync for twitter user"
-        Twitter.syncToESN(user)
-        Twitter.syncFromESN(user)
+        # do if true or undefined
+        unless user.toesn is false
+          console.log "start sync TOESN for twitter user"
+          Twitter.syncToESN(user)
+        unless user.fromesn is false
+          console.log "start sync FROMESN for twitter user"
+          Twitter.syncFromESN(user)
+          Twitter.postLike(user)
     ), (err) ->
   catch err
     console.log 'Twitter Error!' + err
--- a/src/twitter.coffee	Tue Jul 29 16:06:05 2014 +0200
+++ b/src/twitter.coffee	Thu Aug 28 18:40:39 2014 +0200
@@ -117,7 +117,7 @@
         (feed, callback) ->
           return if not feed?
           ti = new Date().getTime() - interval
-          async.eachLimit feed.items, 5, ((post, callback) ->
+          async.eachLimit feed.items, 1, ((post, callback) ->
             # do for each post
             ts = Date.parse(post.updated)
             if (ts >= ti and post.verb is "post" or post.verb is "share") and (post.object.objectType is "note" or post.object.objectType is "image") and (Pump.isPublicActivity(post)) and (typeof post.object.deleted is "undefined")
@@ -185,13 +185,13 @@
         return if not data? or data.length is 0
         console.log "data isnt empty for " + me
         ti = (new Date().getTime() - interval)
-        async.eachLimit data, 1, ((tweet, cb) ->
+        async.eachLimit data, 3, ((tweet, cb) ->
           async.waterfall [
             (callback) ->
-              FromESN.search {uid: tweet.id + "@twitter_to_" + me}, callback
+              FromESN.search {uid: tweet.id_str + "@twitter_to_" + me}, callback
             (result, callback) ->
               return if result.length isnt 0 or tweet.user.id_str is id
-              console.log "new tweet found"
+              console.log "tweet found"
               twitterdate = new Date(Date.parse(tweet.created_at.replace(/( +)/, " UTC$1")))
               ts = Date.parse(twitterdate)
               if (ts >= ti)
@@ -208,16 +208,16 @@
                 console.log "parse err " + err
                 return
               FromESN.create
-                postid: tweet.id + "@twitter"
+                postid: tweet.id_str + "@twitter"
                 sourceUser: tweet.user.id
-                sourcePost: 'https://twitter.com/'+tweet.user.name+"/status/" + tweet.id
+                sourcePost: 'https://twitter.com/'+tweet.user.screen_name+"/status/" + tweet.id_str
                 pumpPost: pumppost.object.id
                 recipientUser: me
                 created: Date.now()
               , callback
           ], (err, result) ->
             console.log "post a tweet to user " + me
-            cb()
+            cb
         ), (err) ->
           if (err)
             console.log "Error: " + err
@@ -225,6 +225,45 @@
             console.log "done FromESN twitter user " + me
       return
 
+    postLike: (user) ->
+      i = 0
+      me = user.user_pumpio
+      id = user.user_ESN.substr(0,user.user_ESN.indexOf('@'))
+      token = user.oauth_token
+      secret = user.extra_token
+      twit = new twitter(
+        consumer_key: client_id
+        consumer_secret: client_secret
+        access_token_key: token
+        access_token_secret: secret
+      )
+      console.log "try 2 find twitter likes for " + me
+      async.waterfall [
+        (callback) ->
+          Usermap.search {id: me + '_to_' + me}, callback
+        (pumpuser, callback) ->
+          Pump.getLikes(pumpuser[0], callback)
+        (likearray, callback) ->
+          return if not (likearray?) or likearray.length is 0
+          likes = JSON.parse(likearray)
+          return if not (likes?) or likes.items.length is 0
+          async.each likes.items,((note, cb) ->
+            async.waterfall [
+              (callback) ->
+                 FromESN.search {recipientUser: me, pumpPost: note.id}, callback
+              (fromesn, callback) ->
+                if (fromesn?) and fromesn.length isnt 0 and fromesn[0].sourcePost.indexOf('twitter.com') isnt -1
+                  #console.log fromesn[0]
+                  obj = fromesn[0].postid.substr(0,fromesn[0].postid.indexOf('@'))
+                  twit.post "/favorites/create.json",
+                    id: obj
+                  , (data) ->
+                    console.log "Twitter " + obj + " liked"
+            ], (err, result) ->
+          ), (err) ->
+      ], (err, result) ->
+      return
+
     getOAuth: (site) ->
       new OAuth(request_token_endpoint, access_token_endpoint, client_id, client_secret, "1.0", site.url("/authorized-for-twitter"), "HMAC-SHA1", null, # nonce size; use default
         "User-Agent": site.userAgent()
--- a/src/usermap.coffee	Tue Jul 29 16:06:05 2014 +0200
+++ b/src/usermap.coffee	Thu Aug 28 18:40:39 2014 +0200
@@ -17,6 +17,8 @@
     "user_ESN"
     "oauth_token"
     "extra_token"
+    "fromesn"
+    "toesn"
     "created"
   ]
   indices: [
--- a/views/index.jade	Tue Jul 29 16:06:05 2014 +0200
+++ b/views/index.jade	Thu Aug 28 18:40:39 2014 +0200
@@ -42,7 +42,7 @@
       'response_type' : 'code',
       'accesstype': 'offline',
       'approvalprompt': 'force',
-      'cookiepolicy': "https://server.example",
+      'cookiepolicy': "https://pumpbridge.me",
       'requestvisibleactions': 'http://schemas.google.com/AddActivity',
       'scope': 'https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email'
      });
@@ -128,6 +128,16 @@
          var twstatus = getCookie('twitterid')
          if (twstatus != "") $('#twstatus').html('<a href=https://twitter.com/account/redirect_by_id/' + twstatus + '> ' + getCookie('twitteruser') + '</a>');
 
+         var twfromesn = "#{twfromesn}";
+         var twtoesn = "#{twtoesn}";
+
+
+         if (twtoesn == "true") $("#twtoesn").prop("checked", true);
+         else $("#twtoesn").prop("checked", false);
+
+         if (twfromesn == "true") $("#twfromesn").prop("checked", true);
+         else $("#twfromesn").prop("checked", false);
+
          $.ajaxSetup({
              cache: true
          });
@@ -222,11 +232,23 @@
         #tw-info.tw-info
           i(id='twstatus') not logged in
           br
+          if usermaptw
+            form(class='',action='/bridge',method='post')
+             input(id='twmode',name='twmode',hidden='true',value=user.id)
+             input(id='twtoesn',name='twtoesn',type='checkbox',value='pump2twitter')
+             |  pump2twitter
+             br
+             input(id='twfromesn',name='twfromesn',type='checkbox',value='twitter2pump')
+             |  twitter2pump
+             br
+             button(id='twsavemode',type='submit',class='btn btn-default btn-xs')
+              | save modus
+            br
           form(class='',action='/bridge',method='post')
            input(id='twdeleted',name='twdelete',hidden='true',value=user.id)
            button(id='twdeletebutton',type='submit',class='btn btn-default btn-xs')
             | delete credentials
-          button(id='twloginbutton2',name='twloginbutton2',type='submit',class='btn btn-default btn-xs',onClick='location.href="/add-account"')
+         button(id='twloginbutton2',name='twloginbutton2',type='submit',class='btn btn-default btn-xs',onClick='location.href="/add-account"')
            | add credentials
        form(class='',action='/bridge',method='post')
          input(id='pumpid',name='pumpid',hidden='true',value=user.id)
@@ -238,9 +260,7 @@
          input(id='gpid',name='gpid',hidden='true')
          input(id='gptoken',name='gptoken',hidden='true',size=100)
          br
-         | you need to extra save the credentials
-         br
-         | for facebook and googleplus
+         | you need to extra save the credentials (facebook / google+)
          br
          input(type='submit',class='btn btn-default',value='save credentials')
    .footer
@@ -252,6 +272,6 @@
      p.
        <a href=https://wald.intevation.org/hg/pumpbridge/>pumpbridge</a> is Free Software and available under the Apache License 2.0.
        <br>
-       visit <a href=https://wald.intevation.org/projects/pumpbridge/>https://wald.intevation.org/projects/pumpbridge</a> for more informations!
+       visit <a href=https://wald.intevation.org/projects/pumpbridge/>https://wald.intevation.org/projects/pumpbridge</a> for more information!
        <br>
        pumpbridge is hosted and operated by <a href=https://io.intevation.de/mgebbe>Mathias Gebbe</a> <a href=/contact.html>(Contact)</a>      <br>
--- a/views/login.jade	Tue Jul 29 16:06:05 2014 +0200
+++ b/views/login.jade	Thu Aug 28 18:40:39 2014 +0200
@@ -4,7 +4,7 @@
     title= pageTitle
     link(rel='stylesheet', href='/stylesheets/style.css')
     link(rel='stylesheet', href='/stylesheets/bootstrap.min.css')
-    link(rel='icon', href='/images/favicon.ico',type='image/x-icon')    
+    link(rel='icon', href='/images/favicon.ico',type='image/x-icon')
 
  body
    block content
@@ -14,7 +14,7 @@
        h1(class='headline') pumpbridge.<br>connecting social networks
      form(action='/login', method='post')
        |Login with your pump.io account (WebFinger ID) to get started.
-       br 
+       br
        |(No pump.io account yet? <a href="http://pump.io/tryit">Try it</a>!)
        br
        input(class='login',id='webfinger',name='webfinger',size=30,type='text',placeholder='user@server.example')
@@ -27,6 +27,6 @@
    p.
      <a href=https://wald.intevation.org/hg/pumpbridge/>pumpbridge</a> is Free Software and available under the Apache License 2.0.
      <br>
-     visit <a href=https://wald.intevation.org/projects/pumpbridge/>https://wald.intevation.org/projects/pumpbridge</a> for more informations!
+     visit <a href=https://wald.intevation.org/projects/pumpbridge/>https://wald.intevation.org/projects/pumpbridge</a> for more information!
      <br>
      pumpbridge is hosted and operated by <a href=https://io.intevation.de/mgebbe>Mathias Gebbe</a> <a href=/contact.html>(Contact)</a>
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)