]> git.mxchange.org Git - friendica-addons.git/commitdiff
Merge commit 'upstream/master'
authorMichael Vogel <icarus@dabo.de>
Sun, 11 Mar 2012 18:27:18 +0000 (19:27 +0100)
committerMichael Vogel <icarus@dabo.de>
Sun, 11 Mar 2012 18:27:18 +0000 (19:27 +0100)
27 files changed:
blockem.tgz
blockem/blockem.php
communityhome.tgz
communityhome/twillingham/README [new file with mode: 0644]
communityhome/twillingham/communityhome.php [new file with mode: 0644]
dwpost.tgz [new file with mode: 0644]
dwpost/dwpost.css [new file with mode: 0644]
dwpost/dwpost.php [new file with mode: 0644]
facebook.tgz [changed mode: 0755->0644]
facebook/README
facebook/facebook.php
gnot.tgz [new file with mode: 0644]
gnot/gnot.css [new file with mode: 0755]
gnot/gnot.php [new file with mode: 0755]
irc/irc.php [new file with mode: 0644]
ljpost.tgz [new file with mode: 0644]
ljpost/ljpost.css [new file with mode: 0755]
ljpost/ljpost.php [new file with mode: 0755]
piwik.tgz
qcomment.tgz
qcomment/qcomment.php
statusnet.tgz
statusnet/statusnet.php
twitter.tgz
twitter/twitter.php
wppost.tgz
wppost/wppost.php

index 129a00652b979469e08b86f9fdb187bcb24c817a..ec7119f832cece136f5a921df77962c2c4a3f473 100755 (executable)
Binary files a/blockem.tgz and b/blockem.tgz differ
index 43f34554e24071cc92a492c2121a4b8d244f8632..9134bd0b654fea63fdfaeba3bd3fc01a4d4c4a08 100755 (executable)
@@ -101,15 +101,15 @@ function blockem_prepare_body(&$a,&$b) {
                }
        }
        if($found) {
-               $rnd = random_string(8);        
+               $rnd = random_string(8);
                $b['html'] = '<div id="blockem-wrap-' . $rnd . '" class="fakelink" onclick=openClose(\'blockem-' . $rnd . '\'); >' . sprintf( t('Blocked %s - Click to open/close'),$word ) . '</div><div id="blockem-' . $rnd . '" style="display: none; " >' . $b['html'] . '</div>';  
        }
 }
 
 
 function blockem_display_item(&$a,&$b) {
-       if(strstr($b['output'],'id="blockem-wrap-'))
-               $b['output'] = preg_replace('/\<img(.*?)src=\"(.*?)\" class=\"wall\-item\-photo(.*?)\>/','<img$1src="' . $a->get_baseurl() . "/images/default-profile-sm.jpg" . '" class="wall-item-photo$3>',$b['output']);
+       if(strstr($b['output']['body'],'id="blockem-wrap-'))
+               $b['output']['thumb'] = $a->get_baseurl() . "/images/default-profile-sm.jpg";
 }
 
 
@@ -193,4 +193,4 @@ function blockem_init(&$a) {
        set_pconfig(local_user(),'blockem','words',$words);
        info( t('blockem settings updated') . EOL );
        killme();
-}
\ No newline at end of file
+}
index b08abd2ec236c20a20c24d7b8083cff317798e8c..ff915f2e73f6ba36f6d56053f5a9614cef3818a9 100755 (executable)
Binary files a/communityhome.tgz and b/communityhome.tgz differ
diff --git a/communityhome/twillingham/README b/communityhome/twillingham/README
new file mode 100644 (file)
index 0000000..bb57427
--- /dev/null
@@ -0,0 +1,7 @@
+Thomas Willingham
+
+This isn't even close to being worth a pull request, but some people might find it useful.
+
+Enable community home in your admin panel, then replace communityhome.php with this one to get a front page like mine (a normal front page, but with latest users shown in the sidebar, which looks bleak when there's nothing in it).
+
+There are more graceful ways of doing this, I used communityhome as I plan to make use of a limited stream and likes in future.
diff --git a/communityhome/twillingham/communityhome.php b/communityhome/twillingham/communityhome.php
new file mode 100644 (file)
index 0000000..102732a
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+/**
+ * Name: Community home
+ * Description: Show last community activity in homepage
+ * Version: 1.0
+ * Author: Fabio Comuni <http://kirgroup.com/profile/fabrixxm>
+ */
+
+
+require_once('mod/community.php');
+
+
+function communityhome_install() {
+       register_hook('home_content', 'addon/communityhome/communityhome.php', 'communityhome_home');
+       logger("installed communityhome");
+}
+
+function communityhome_uninstall() {
+       unregister_hook('home_content', 'addon/communityhome/communityhome.php', 'communityhome_home');
+       logger("removed communityhome");
+}
+
+function communityhome_home(&$a, &$o){
+       // custom css
+       $a->page['htmlhead'] .= '<link rel="stylesheet" type="text/css" href="'.$a->get_baseurl().'/addon/communityhome/communityhome.css" media="all" />';
+       
+       $aside = array(
+               '$tab_1' => t('Login'),
+               '$tab_2' => t('OpenID'),
+               '$noOid' => get_config('system','no_openid'),
+       );
+       
+       // login form
+       $aside['$login_title'] =  t('Login');
+       $aside['$login_form'] = login(($a->config['register_policy'] == REGISTER_CLOSED) ? false : true);
+       
+       // last 12 users
+       $aside['$lastusers_title'] = t('Latest users');
+       $aside['$lastusers_items'] = array();
+       $sql_extra = "";
+       $publish = (get_config('system','publish_all') ? '' : " AND `publish` = 1 " );
+       $order = " ORDER BY `register_date` DESC ";
+
+       $r = q("SELECT `profile`.*, `profile`.`uid` AS `profile_uid`, `user`.`nickname`
+                       FROM `profile` LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid` 
+                       WHERE `is-default` = 1 $publish AND `user`.`blocked` = 0 $sql_extra $order LIMIT %d , %d ",
+               0,
+               12
+       );
+       $tpl = file_get_contents( dirname(__file__).'/directory_item.tpl');
+       if(count($r)) {
+               $photo = 'thumb';
+               foreach($r as $rr) {
+                       $profile_link = $a->get_baseurl() . '/profile/' . ((strlen($rr['nickname'])) ? $rr['nickname'] : $rr['profile_uid']);
+                       $entry = replace_macros($tpl,array(
+                               '$id' => $rr['id'],
+                               '$profile-link' => $profile_link,
+                               '$photo' => $rr[$photo],
+                               '$alt-text' => $rr['name'],
+                       ));
+                       $aside['$lastusers_items'][] = $entry;
+               }
+       }
+       
+       // 12 most active users (by posts and contacts)
+       // this query don't work on some mysql versions
+       $r = q("SELECT `uni`.`contacts`,`uni`.`items`, `profile`.*, `profile`.`uid` AS `profile_uid`, `user`.`nickname`  FROM
+                       (SELECT COUNT(`id`) as `contacts`, `uid` FROM `contact` WHERE `self`=0 GROUP BY `uid`) AS `con`,
+                       (SELECT COUNT(`id`) as `items`, `uid` FROM `item` WHERE `item`.`changed` > DATE(NOW() - INTERVAL 1 MONTH) AND `item`.`wall` = 1 GROUP BY `uid`) AS `ite`,
+                       (
+                       SELECT `contacts`,`items`,`ite`.`uid` FROM `con` RIGHT OUTER JOIN `ite` ON `con`.`uid`=`ite`.`uid` 
+                       UNION ALL 
+                       SELECT `contacts`,`items`,`con`.`uid` FROM `con` LEFT OUTER JOIN `ite` ON `con`.`uid`=`ite`.`uid`
+                       ) AS `uni`, `user`, `profile`
+                       WHERE `uni`.`uid`=`user`.`uid`
+                       AND `uni`.`uid`=`profile`.`uid` AND `profile`.`publish`=1
+                       GROUP BY `uid`
+                       ORDER BY `items` DESC,`contacts` DESC
+                       LIMIT 0,10");
+       if($r && count($r)) {
+               $aside['$activeusers_title']  = t('Most active users');
+               $aside['$activeusers_items']  = array();
+               
+               $photo = 'thumb';
+               foreach($r as $rr) {
+                       $profile_link = $a->get_baseurl() . '/profile/' . ((strlen($rr['nickname'])) ? $rr['nickname'] : $rr['profile_uid']);
+                       $entry = replace_macros($tpl,array(
+                               '$id' => $rr['id'],
+                               '$profile-link' => $profile_link,
+                               '$photo' => $rr[$photo],
+                               '$alt-text' => sprintf("%s (%s posts, %s contacts)",$rr['name'], ($rr['items']?$rr['items']:'0'), ($rr['contacts']?$rr['contacts']:'0'))
+                       ));
+                       $aside['$activeusers_items'][] = $entry;
+               }
+       }
+       
+       
+       
+       
+       $tpl = file_get_contents(dirname(__file__).'/communityhome.tpl');
+       $a->page['aside'] = replace_macros($tpl, $aside);
+       $o = '';
+       if(file_exists('home.html'))
+       
+               $o .= file_get_contents('home.html');
+       
+}
diff --git a/dwpost.tgz b/dwpost.tgz
new file mode 100644 (file)
index 0000000..7841e41
Binary files /dev/null and b/dwpost.tgz differ
diff --git a/dwpost/dwpost.css b/dwpost/dwpost.css
new file mode 100644 (file)
index 0000000..8edab3d
--- /dev/null
@@ -0,0 +1,15 @@
+
+#ljpost-enable-label, #ljpost-username-label, #ljpost-password-label, #ljpost-bydefault-label {
+float: left;
+width: 200px;
+margin-top: 10px;
+}
+
+#ljpost-checkbox, #ljpost-username, #ljpost-password, #ljpost-bydefault {
+float: left;
+margin-top: 10px;
+}
+
+#ljpost-submit {
+margin-top: 15px;
+}
\ No newline at end of file
diff --git a/dwpost/dwpost.php b/dwpost/dwpost.php
new file mode 100644 (file)
index 0000000..5f8dcc7
--- /dev/null
@@ -0,0 +1,227 @@
+<?php
+
+/**
+ * Name: Dreamwidth Post Connector
+ * Description: Post to dreamwidth
+ * Version: 1.0
+ * Author: Tony Baldwin <http://tonybaldwin.me/friendica/profile/tony>
+ * Author: Michael Johnston
+ * Author: Cat Gray <https://free-haven.org/profile/catness>
+ */
+
+function dwpost_install() {
+    register_hook('post_local',           'addon/dwpost/dwpost.php', 'dwpost_post_local');
+    register_hook('notifier_normal',      'addon/dwpost/dwpost.php', 'dwpost_send');
+    register_hook('jot_networks',         'addon/dwpost/dwpost.php', 'dwpost_jot_nets');
+    register_hook('connector_settings',      'addon/dwpost/dwpost.php', 'dwpost_settings');
+    register_hook('connector_settings_post', 'addon/dwpost/dwpost.php', 'dwpost_settings_post');
+
+}
+function dwpost_uninstall() {
+    unregister_hook('post_local',       'addon/dwpost/dwpost.php', 'dwpost_post_local');
+    unregister_hook('notifier_normal',  'addon/dwpost/dwpost.php', 'dwpost_send');
+    unregister_hook('jot_networks',     'addon/dwpost/dwpost.php', 'dwpost_jot_nets');
+    unregister_hook('connector_settings',      'addon/dwpost/dwpost.php', 'dwpost_settings');
+    unregister_hook('connector_settings_post', 'addon/dwpost/dwpost.php', 'dwpost_settings_post');
+
+}
+
+
+function dwpost_jot_nets(&$a,&$b) {
+    if(! local_user())
+        return;
+
+    $dw_post = get_pconfig(local_user(),'dwpost','post');
+    if(intval($dw_post) == 1) {
+        $dw_defpost = get_pconfig(local_user(),'dwpost','post_by_default');
+        $selected = ((intval($dw_defpost) == 1) ? ' checked="checked" ' : '');
+        $b .= '<div class="profile-jot-net"><input type="checkbox" name="dwpost_enable" ' . $selected . ' value="1" /> '
+            . t('Post to Dreamwidth') . '</div>';
+    }
+}
+
+
+function dwpost_settings(&$a,&$s) {
+
+    if(! local_user())
+        return;
+
+    /* Add our stylesheet to the page so we can make our settings look nice */
+
+    $a->page['htmlhead'] .= '<link rel="stylesheet"  type="text/css" href="' . $a->get_baseurl() . '/addon/dwpost/dwpost.css' . '" media="all" />' . "\r\n";
+
+    /* Get the current state of our config variables */
+
+    $enabled = get_pconfig(local_user(),'dwpost','post');
+
+    $checked = (($enabled) ? ' checked="checked" ' : '');
+
+    $def_enabled = get_pconfig(local_user(),'dwpost','post_by_default');
+
+    $def_checked = (($def_enabled) ? ' checked="checked" ' : '');
+
+       $dw_username = get_pconfig(local_user(), 'dwpost', 'dw_username');
+       $dw_password = get_pconfig(local_user(), 'dwpost', 'dw_password');
+
+
+    /* Add some HTML to the existing form */
+
+    $s .= '<div class="settings-block">';
+    $s .= '<h3>' . t('Dreamwidth Post Settings') . '</h3>';
+    $s .= '<div id="dwpost-enable-wrapper">';
+    $s .= '<label id="dwpost-enable-label" for="dwpost-checkbox">' . t('Enable dreamwidth Post Plugin') . '</label>';
+    $s .= '<input id="dwpost-checkbox" type="checkbox" name="dwpost" value="1" ' . $checked . '/>';
+    $s .= '</div><div class="clear"></div>';
+
+    $s .= '<div id="dwpost-username-wrapper">';
+    $s .= '<label id="dwpost-username-label" for="dwpost-username">' . t('dreamwidth username') . '</label>';
+    $s .= '<input id="dwpost-username" type="text" name="dw_username" value="' . $dw_username . '" />';
+    $s .= '</div><div class="clear"></div>';
+
+    $s .= '<div id="dwpost-password-wrapper">';
+    $s .= '<label id="dwpost-password-label" for="dwpost-password">' . t('dreamwidth password') . '</label>';
+    $s .= '<input id="dwpost-password" type="password" name="dw_password" value="' . $dw_password . '" />';
+    $s .= '</div><div class="clear"></div>';
+
+    $s .= '<div id="dwpost-bydefault-wrapper">';
+    $s .= '<label id="dwpost-bydefault-label" for="dwpost-bydefault">' . t('Post to dreamwidth by default') . '</label>';
+    $s .= '<input id="dwpost-bydefault" type="checkbox" name="dw_bydefault" value="1" ' . $def_checked . '/>';
+    $s .= '</div><div class="clear"></div>';
+
+    /* provide a submit button */
+
+    $s .= '<div class="settings-submit-wrapper" ><input type="submit" id="dwpost-submit" name="dwpost-submit" class="settings-submit" value="' . t('Submit') . '" /></div></div>';
+
+}
+
+
+function dwpost_settings_post(&$a,&$b) {
+
+       if(x($_POST,'dwpost-submit')) {
+
+               set_pconfig(local_user(),'dwpost','post',intval($_POST['dwpost']));
+               set_pconfig(local_user(),'dwpost','post_by_default',intval($_POST['dw_bydefault']));
+               set_pconfig(local_user(),'dwpost','dw_username',trim($_POST['dw_username']));
+               set_pconfig(local_user(),'dwpost','dw_password',trim($_POST['dw_password']));
+
+       }
+
+}
+
+function dwpost_post_local(&$a,&$b) {
+
+       // This can probably be changed to allow editing by pointing to a different API endpoint
+
+       if($b['edit'])
+               return;
+
+       if((! local_user()) || (local_user() != $b['uid']))
+               return;
+
+       if($b['private'] || $b['parent'])
+               return;
+
+    $dw_post   = intval(get_pconfig(local_user(),'dwpost','post'));
+
+       $dw_enable = (($dw_post && x($_REQUEST,'dwpost_enable')) ? intval($_REQUEST['dwpost_enable']) : 0);
+
+       if($_REQUEST['api_source'] && intval(get_pconfig(local_user(),'dwpost','post_by_default')))
+               $dw_enable = 1;
+
+    if(! $dw_enable)
+       return;
+
+    if(strlen($b['postopts']))
+       $b['postopts'] .= ',';
+     $b['postopts'] .= 'dwpost';
+}
+
+
+
+
+function dwpost_send(&$a,&$b) {
+
+    if($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited']))
+        return;
+
+    if(! strstr($b['postopts'],'dwpost'))
+        return;
+
+    if($b['parent'] != $b['id'])
+        return;
+
+       // dreamwidth post in the LJ user's timezone. 
+       // Hopefully the person's Friendica account
+       // will be set to the same thing.
+
+       $tz = 'UTC';
+
+       $x = q("select timezone from user where uid = %d limit 1",
+               intval($b['uid'])
+       );
+       if($x && strlen($x[0]['timezone']))
+               $tz = $x[0]['timezone'];        
+
+       $dw_username = get_pconfig($b['uid'],'dwpost','dw_username');
+       $dw_password = get_pconfig($b['uid'],'dwpost','dw_password');
+       $dw_blog = 'http://www.dreamwidth.org/interface/xmlrpc';
+
+       if($dw_username && $dw_password && $dw_blog) {
+
+               require_once('include/bbcode.php');
+               require_once('include/datetime.php');
+
+               $title = $b['title'];
+               $post = bbcode($b['body']);
+               $post = xmlify($post);
+               $tags = dwpost_get_tags($b['tag']);
+
+               $date = datetime_convert('UTC',$tz,$b['created'],'Y-m-d H:i:s');
+               $year = intval(substr($date,0,4));
+               $mon  = intval(substr($date,5,2));
+               $day  = intval(substr($date,8,2));
+               $hour = intval(substr($date,11,2));
+               $min  = intval(substr($date,14,2));
+
+               $xml = <<< EOT
+<?xml version="1.0" encoding="utf-8"?>
+<methodCall><methodName>LJ.XMLRPC.postevent</methodName>
+<params><param>
+<value><struct>
+<member><name>year</name><value><int>$year</int></value></member>
+<member><name>mon</name><value><int>$mon</int></value></member>
+<member><name>day</name><value><int>$day</int></value></member>
+<member><name>hour</name><value><int>$hour</int></value></member>
+<member><name>min</name><value><int>$min</int></value></member>
+<member><name>event</name><value><string>$post</string></value></member>
+<member><name>username</name><value><string>$dw_username</string></value></member>
+<member><name>password</name><value><string>$dw_password</string></value></member>
+<member><name>subject</name><value><string>$title</string></value></member>
+<member><name>lineendings</name><value><string>unix</string></value></member>
+<member><name>ver</name><value><int>1</int></value></member>
+<member><name>props</name>
+<value><struct>
+<member><name>useragent</name><value><string>Friendica</string></value></member>
+<member><name>taglist</name><value><string>$tags</string></value></member>
+</struct></value></member>
+</struct></value>
+</param></params>
+</methodCall>
+
+EOT;
+
+               logger('dwpost: data: ' . $xml, LOGGER_DATA);
+
+               if($dw_blog !== 'test')
+                       $x = post_url($dw_blog,$xml);
+               logger('posted to dreamwidth: ' . ($x) ? $x : '', LOGGER_DEBUG);
+
+       }
+}
+
+function dwpost_get_tags($post)
+{
+       preg_match_all("/\]([^\[#]+)\[/",$post,$matches);
+       $tags = implode(', ',$matches[1]);
+       return $tags;
+}
old mode 100755 (executable)
new mode 100644 (file)
index 582d4e5..2cb406a
Binary files a/facebook.tgz and b/facebook.tgz differ
index ee7e489babff1b54996e489d7f4cd7e448b9d0b1..9687558e70bd9a0d1b8aefd167e4aea1a8f64402 100755 (executable)
@@ -17,13 +17,18 @@ Installing the Friendica/Facebook connector
      Replace with the settings Facebook gives you.
   d. Navigate to Set Web->Site URL & Domain -> Website Settings.  Set Site URL 
      to yoursubdomain.yourdomain.com.  Set Site Domain to your yourdomain.com.
+  e. Chose "Website" (the url should be your site URL with a trailing slash) in the
+     "Select how your app integrates with Facebook" section.
 2. Enable the facebook plugin by including it in .htconfig.php - e.g. 
     $a->config['system']['addon'] = 'plugin1,plugin2,facebook';
 3. Visit the Facebook Settings section of the "Settings->Plugin Settings" page.
    and click 'Install Facebook Connector'.
 4. This will ask you to login to Facebook and grant permission to the 
    plugin to do its stuff. Allow it to do so. 
-5. You're done. To turn it off visit the Plugin Settings page again and
+5. Optional step: If you want to use Facebook Real Time Updates (so new messages
+   and new contacts are added ~1min after they are postet / added on FB), go to
+   Settings -> plugins -> facebook and press the "Activate Real-Time Updates"-button.
+6. You're done. To turn it off visit the Plugin Settings page again and
    'Remove Facebook posting'.
 
 Vidoes and embeds will not be posted if there is no other content. Links 
index c5f3a0b70f30f6c4950d828c8afd1af143b3dbc8..b2f21b93ed291abb84d56dcb696b72fe9df76f76 100755 (executable)
@@ -1,8 +1,9 @@
 <?php
 /**
  * Name: Facebook Connector
- * Version: 1.0
+ * Version: 1.1
  * Author: Mike Macgirvin <http://macgirvin.com/profile/mike>
+ *         Tobias Hößl <https://github.com/CatoTH/>
  */
 
 /**
  *    and click 'Install Facebook Connector'.
  * 4. This will ask you to login to Facebook and grant permission to the 
  *    plugin to do its stuff. Allow it to do so. 
- * 5. You're done. To turn it off visit the Plugin Settings page again and
+ * 5. Optional step: If you want to use Facebook Real Time Updates (so new messages
+ *    and new contacts are added ~1min after they are postet / added on FB), go to
+ *    Settings -> plugins -> facebook and press the "Activate Real-Time Updates"-button.
+ * 6. You're done. To turn it off visit the Plugin Settings page again and
  *    'Remove Facebook posting'.
  *
  * Vidoes and embeds will not be posted if there is no other content. Links 
@@ -53,6 +57,8 @@ function facebook_install() {
        register_hook('connector_settings',  'addon/facebook/facebook.php', 'facebook_plugin_settings');
        register_hook('cron',             'addon/facebook/facebook.php', 'facebook_cron');
        register_hook('queue_predeliver', 'addon/facebook/facebook.php', 'fb_queue_hook');
+       
+       if (get_config('facebook', 'realtime_active') == 1) facebook_subscription_add_users(); // Restore settings, if the plugin was installed before
 }
 
 
@@ -67,6 +73,8 @@ function facebook_uninstall() {
        // hook moved
        unregister_hook('post_local_end',  'addon/facebook/facebook.php', 'facebook_post_hook');
        unregister_hook('plugin_settings',  'addon/facebook/facebook.php', 'facebook_plugin_settings');
+       
+       if (get_config('facebook', 'realtime_active') == 1) facebook_subscription_del_users();
 }
 
 
@@ -76,10 +84,93 @@ function facebook_module() {}
 
 
 
-/* If a->argv[1] is a nickname, this is a callback from Facebook oauth requests. */
+// If a->argv[1] is a nickname, this is a callback from Facebook oauth requests.
+// If $_REQUEST["realtime_cb"] is set, this is a callback from the Real-Time Updates API
 
 function facebook_init(&$a) {
+       
+       if (x($_REQUEST, "realtime_cb") && x($_REQUEST, "realtime_cb")) {
+               logger("facebook_init: Facebook Real-Time callback called", LOGGER_DEBUG);
+               
+               if (x($_REQUEST, "hub_verify_token")) {
+                       // this is the verification callback while registering for real time updates
+                       
+                       $verify_token = get_config('facebook', 'cb_verify_token');
+                       if ($verify_token != $_REQUEST["hub_verify_token"]) {
+                               logger('facebook_init: Wrong Facebook Callback Verifier - expected ' . $verify_token . ', got ' . $_REQUEST["hub_verify_token"]);
+                               return;
+                       }
+                       
+                       if (x($_REQUEST, "hub_challenge")) {
+                               logger('facebook_init: Answering Challenge: ' . $_REQUEST["hub_challenge"], LOGGER_DATA);
+                               echo $_REQUEST["hub_challenge"];
+                               die();
+                       }
+               }
+               
+               require_once('include/items.php');
+               
+               // this is a status update
+               $content = file_get_contents("php://input");
+               if (is_numeric($content)) $content = file_get_contents("php://input");
+               $js = json_decode($content);
+               logger(print_r($js, true), LOGGER_DATA);
+               
+               if (!isset($js->object) || $js->object != "user" || !isset($js->entry)) {
+                       logger('facebook_init: Could not parse Real-Time Update data', LOGGER_DEBUG);
+                       return;
+               }
+               
+               $affected_users = array("feed" => array(), "friends" => array());
+               
+               foreach ($js->entry as $entry) {
+                       $fbuser = $entry->uid;
+                       foreach ($entry->changed_fields as $field) {
+                               if (!isset($affected_users[$field])) {
+                                       logger('facebook_init: Unknown field "' . $field . '"');
+                                       continue;
+                               }
+                               if (in_array($fbuser, $affected_users[$field])) continue;
+                               
+                               $r = q("SELECT `uid` FROM `pconfig` WHERE `cat` = 'facebook' AND `k` = 'self_id' AND `v` = '%s' LIMIT 1", dbesc($fbuser));
+                               if(! count($r))
+                                       continue;
+                               $uid = $r[0]['uid'];
+                               
+                               $access_token = get_pconfig($uid,'facebook','access_token');
+                               if(! $access_token)
+                                       return;
+                               
+                               switch ($field) {
+                                       case "feed":
+                                               logger('facebook_init: FB-User ' . $fbuser . ' / feed', LOGGER_DEBUG);
+                                               
+                                               if(! get_pconfig($uid,'facebook','no_wall')) {
+                                                       $private_wall = intval(get_pconfig($uid,'facebook','private_wall'));
+                                                       $s = fetch_url('https://graph.facebook.com/me/feed?access_token=' . $access_token);
+                                                       if($s) {
+                                                               $j = json_decode($s);
+                                                               logger('facebook_init: wall: ' . print_r($j,true), LOGGER_DATA);
+                                                               fb_consume_stream($uid,$j,($private_wall) ? false : true);
+                                                       }
+                                               }
+                                               
+                                       break;
+                                       case "friends":
+                                               logger('facebook_init: FB-User ' . $fbuser . ' / friends', LOGGER_DEBUG);
+                                               
+                                               fb_get_friends($uid, false);
+                                               set_pconfig($uid,'facebook','friend_check',time());
+                                       break;
+                                       default:
+                                               logger('facebook_init: Unknown callback field for ' . $fbuser, LOGGER_NORMAL);
+                               }
+                               $affected_users[$field][] = $fbuser;
+                       }
+               }
+       }
 
+       
        if($a->argc != 2)
                return;
        $nick = $a->argv[1];
@@ -91,8 +182,8 @@ function facebook_init(&$a) {
                return;
 
        $uid           = $r[0]['uid'];
-       $auth_code     = (($_GET['code']) ? $_GET['code'] : '');
-       $error         = (($_GET['error_description']) ? $_GET['error_description'] : '');
+       $auth_code     = (x($_GET, 'code') ? $_GET['code'] : '');
+       $error         = (x($_GET, 'error_description') ? $_GET['error_description'] : '');
 
 
        if($error)
@@ -119,7 +210,7 @@ function facebook_init(&$a) {
                        if(get_pconfig($uid,'facebook','no_linking') === false)
                                set_pconfig($uid,'facebook','no_linking',1);
                        fb_get_self($uid);
-                       fb_get_friends($uid);
+                       fb_get_friends($uid, true);
                        fb_consume_all($uid);
 
                }
@@ -140,116 +231,46 @@ function fb_get_self($uid) {
        }
 }
 
-
-
-function fb_get_friends($uid) {
-
-       $r = q("SELECT `uid` FROM `user` WHERE `uid` = %d AND `account_expired` = 0 LIMIT 1",
-               intval($uid)
+function fb_get_friends_sync_new($uid, $access_token, $person) {
+       $link = 'http://facebook.com/profile.php?id=' . $person->id;
+       
+       $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' LIMIT 1",
+               intval($uid),
+               dbesc($link)
        );
-       if(! count($r))
-               return;
-
-       $access_token = get_pconfig($uid,'facebook','access_token');
-
-       $no_linking = get_pconfig($uid,'facebook','no_linking');
-       if($no_linking)
-               return;
+       
+       if (count($r) == 0) {
+               logger('fb_get_friends: new contact found: ' . $link, LOGGER_DEBUG);
+               
+               fb_get_friends_sync_full($uid, $access_token, $person);
+       }
+}
 
-       if(! $access_token)
-               return;
-       $s = fetch_url('https://graph.facebook.com/me/friends?access_token=' . $access_token);
+function fb_get_friends_sync_full($uid, $access_token, $person) {
+       $s = fetch_url('https://graph.facebook.com/' . $person->id . '?access_token=' . $access_token);
        if($s) {
-               logger('facebook: fb_get_friends: ' . $s, LOGGER_DATA);
-               $j = json_decode($s);
-               logger('facebook: fb_get_friends: json: ' . print_r($j,true), LOGGER_DATA);
-               if(! $j->data)
-                       return;
-               foreach($j->data as $person) {
-                       $s = fetch_url('https://graph.facebook.com/' . $person->id . '?access_token=' . $access_token);
-                       if($s) {
-                               $jp = json_decode($s);
-                               logger('fb_get_friends: info: ' . print_r($jp,true), LOGGER_DATA);
+               $jp = json_decode($s);
+               logger('fb_get_friends: info: ' . print_r($jp,true), LOGGER_DATA);
 
-                               // always use numeric link for consistency
+               // always use numeric link for consistency
 
-                               $jp->link = 'http://facebook.com/profile.php?id=' . $person->id;
-
-                               // check if we already have a contact
-
-                               $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' LIMIT 1",
-                                       intval($uid),
-                                       dbesc($jp->link)
-                               );                      
-
-                               if(count($r)) {
-
-                                       // check that we have all the photos, this has been known to fail on occasion
-
-                                       if((! $r[0]['photo']) || (! $r[0]['thumb']) || (! $r[0]['micro'])) {  
-                                               require_once("Photo.php");
-
-                                               $photos = import_profile_photo('https://graph.facebook.com/' . $jp->id . '/picture', $uid, $r[0]['id']);
-
-                                               $r = q("UPDATE `contact` SET `photo` = '%s', 
-                                                       `thumb` = '%s',
-                                                       `micro` = '%s', 
-                                                       `name-date` = '%s', 
-                                                       `uri-date` = '%s', 
-                                                       `avatar-date` = '%s'
-                                                       WHERE `id` = %d LIMIT 1
-                                               ",
-                                                       dbesc($photos[0]),
-                                                       dbesc($photos[1]),
-                                                       dbesc($photos[2]),
-                                                       dbesc(datetime_convert()),
-                                                       dbesc(datetime_convert()),
-                                                       dbesc(datetime_convert()),
-                                                       intval($r[0]['id'])
-                                               );                      
-                                       }       
-                                       continue;
-                               }
-                               else {
+               $jp->link = 'http://facebook.com/profile.php?id=' . $person->id;
 
-                                       // create contact record 
-                                       $r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`, 
-                                               `name`, `nick`, `photo`, `network`, `rel`, `priority`,
-                                               `writable`, `blocked`, `readonly`, `pending` )
-                                               VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, 0, 0, 0 ) ",
-                                               intval($uid),
-                                               dbesc(datetime_convert()),
-                                               dbesc($jp->link),
-                                               dbesc(normalise_link($jp->link)),
-                                               dbesc(''),
-                                               dbesc(''),
-                                               dbesc($jp->id),
-                                               dbesc('facebook ' . $jp->id),
-                                               dbesc($jp->name),
-                                               dbesc(($jp->nickname) ? $jp->nickname : strtolower($jp->first_name)),
-                                               dbesc('https://graph.facebook.com/' . $jp->id . '/picture'),
-                                               dbesc(NETWORK_FACEBOOK),
-                                               intval(CONTACT_IS_FRIEND),
-                                               intval(1),
-                                               intval(1)
-                                       );
-                               }
+               // check if we already have a contact
 
-                               $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1",
-                                       dbesc($jp->link),
-                                       intval($uid)
-                               );
+               $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' LIMIT 1",
+                       intval($uid),
+                       dbesc($jp->link)
+               );                      
 
-                               if(! count($r)) {
-                                       continue;
-                               }
+               if(count($r)) {
 
-                               $contact = $r[0];
-                               $contact_id  = $r[0]['id'];
+                       // check that we have all the photos, this has been known to fail on occasion
 
+                       if((! $r[0]['photo']) || (! $r[0]['thumb']) || (! $r[0]['micro'])) {  
                                require_once("Photo.php");
 
-                               $photos = import_profile_photo($r[0]['photo'],$uid,$contact_id);
+                               $photos = import_profile_photo('https://graph.facebook.com/' . $jp->id . '/picture', $uid, $r[0]['id']);
 
                                $r = q("UPDATE `contact` SET `photo` = '%s', 
                                        `thumb` = '%s',
@@ -265,11 +286,102 @@ function fb_get_friends($uid) {
                                        dbesc(datetime_convert()),
                                        dbesc(datetime_convert()),
                                        dbesc(datetime_convert()),
-                                       intval($contact_id)
+                                       intval($r[0]['id'])
                                );                      
+                       }       
+                       return;
+               }
+               else {
 
-                       }
+                       // create contact record 
+                       $r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`, 
+                               `name`, `nick`, `photo`, `network`, `rel`, `priority`,
+                               `writable`, `blocked`, `readonly`, `pending` )
+                               VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, 0, 0, 0 ) ",
+                               intval($uid),
+                               dbesc(datetime_convert()),
+                               dbesc($jp->link),
+                               dbesc(normalise_link($jp->link)),
+                               dbesc(''),
+                               dbesc(''),
+                               dbesc($jp->id),
+                               dbesc('facebook ' . $jp->id),
+                               dbesc($jp->name),
+                               dbesc(($jp->nickname) ? $jp->nickname : strtolower($jp->first_name)),
+                               dbesc('https://graph.facebook.com/' . $jp->id . '/picture'),
+                               dbesc(NETWORK_FACEBOOK),
+                               intval(CONTACT_IS_FRIEND),
+                               intval(1),
+                               intval(1)
+                       );
+               }
+
+               $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1",
+                       dbesc($jp->link),
+                       intval($uid)
+               );
+
+               if(! count($r)) {
+                       return;
                }
+
+               $contact = $r[0];
+               $contact_id  = $r[0]['id'];
+
+               require_once("Photo.php");
+
+               $photos = import_profile_photo($r[0]['photo'],$uid,$contact_id);
+
+               $r = q("UPDATE `contact` SET `photo` = '%s', 
+                       `thumb` = '%s',
+                       `micro` = '%s', 
+                       `name-date` = '%s', 
+                       `uri-date` = '%s', 
+                       `avatar-date` = '%s'
+                       WHERE `id` = %d LIMIT 1
+               ",
+                       dbesc($photos[0]),
+                       dbesc($photos[1]),
+                       dbesc($photos[2]),
+                       dbesc(datetime_convert()),
+                       dbesc(datetime_convert()),
+                       dbesc(datetime_convert()),
+                       intval($contact_id)
+               );                      
+
+       }
+}
+
+// if $fullsync is true, only new contacts are searched for
+
+function fb_get_friends($uid, $fullsync = true) {
+
+       $r = q("SELECT `uid` FROM `user` WHERE `uid` = %d AND `account_expired` = 0 LIMIT 1",
+               intval($uid)
+       );
+       if(! count($r))
+               return;
+
+       $access_token = get_pconfig($uid,'facebook','access_token');
+
+       $no_linking = get_pconfig($uid,'facebook','no_linking');
+       if($no_linking)
+               return;
+
+       if(! $access_token)
+               return;
+       $s = fetch_url('https://graph.facebook.com/me/friends?access_token=' . $access_token);
+       if($s) {
+               logger('facebook: fb_get_friends: ' . $s, LOGGER_DATA);
+               $j = json_decode($s);
+               logger('facebook: fb_get_friends: json: ' . print_r($j,true), LOGGER_DATA);
+               if(! $j->data)
+                       return;
+               foreach($j->data as $person)
+                       if ($fullsync)
+                               fb_get_friends_sync_full($uid, $access_token, $person);
+                       else
+                               fb_get_friends_sync_new($uid, $access_token, $person);
        }
 }
 
@@ -314,7 +426,7 @@ function facebook_post(&$a) {
                elseif(intval($no_linking) && intval($linkvalue)) {
                        // FB linkage is now allowed - import stuff.
                        fb_get_self($uid);
-                       fb_get_friends($uid);
+                       fb_get_friends($uid, true);
                        fb_consume_all($uid);
                }
 
@@ -339,7 +451,7 @@ function facebook_content(&$a) {
        }
 
        if($a->argc > 1 && $a->argv[1] === 'friends') {
-               fb_get_friends(local_user());
+               fb_get_friends(local_user(), true);
                info( t('Updating contacts') . EOL);
        }
 
@@ -457,13 +569,40 @@ function facebook_cron($a,$b) {
                        if($last_friend_check) 
                                $next_friend_check = $last_friend_check + 86400;
                        if($next_friend_check <= time()) {
-                               fb_get_friends($rr['uid']);
+                               fb_get_friends($rr['uid'], true);
                                set_pconfig($rr['uid'],'facebook','friend_check',time());
                        }
                        fb_consume_all($rr['uid']);
                }
-       }       
-
+       }
+       
+       if (get_config('facebook', 'realtime_active') == 1) {
+               if (!facebook_check_realtime_active()) {
+                       
+                       logger('facebook_cron: Facebook is not sending Real-Time Updates any more, although it is supposed to. Trying to fix it...', LOGGER_NORMAL);
+                       facebook_subscription_add_users();
+                       
+                       if (facebook_check_realtime_active()) 
+                               logger('facebook_cron: Successful', LOGGER_NORMAL);
+                       else {
+                               logger('facebook_cron: Failed', LOGGER_NORMAL);
+                               
+                               if(strlen($a->config['admin_email']) && !get_config('facebook', 'realtime_err_mailsent')) {
+                                       $res = mail($a->config['admin_email'], t('Problems with Facebook Real-Time Updates'), 
+                                               "Hi!\n\nThere's a problem with the Facebook Real-Time Updates that cannob be solved automatically. Maybe an permission issue?\n\nThis e-mail will only be sent once.",
+                                               'From: ' . t('Administrator') . '@' . $_SERVER['SERVER_NAME'] . "\n"
+                                               . 'Content-type: text/plain; charset=UTF-8' . "\n"
+                                               . 'Content-transfer-encoding: 8bit'
+                                       );
+                                       
+                                       set_config('facebook', 'realtime_err_mailsent', 1);
+                               }
+                       }
+               } else { // !facebook_check_realtime_active()
+                       del_config('facebook', 'realtime_err_mailsent');
+               }
+       }
+       
        set_config('facebook','last_poll', time());
 
 }
@@ -479,6 +618,27 @@ function facebook_plugin_settings(&$a,&$b) {
 
 }
 
+
+function facebook_plugin_admin(&$a, &$o){
+       
+       $activated = facebook_check_realtime_active();
+       if ($activated) {
+               $o = t('Real-Time Updates are activated.') . '<br><br>';
+               $o .= '<input type="submit" name="real_time_deactivate" value="' . t('Deactivate Real-Time Updates') . '">';
+       } else {
+               $o = t('Real-Time Updates not activated.') . '<br><input type="submit" name="real_time_activate" value="' . t('Activate Real-Time Updates') . '">';
+       }
+}
+
+function facebook_plugin_admin_post(&$a, &$o){
+       if (x($_REQUEST,'real_time_activate')) {
+               facebook_subscription_add_users();
+       }
+       if (x($_REQUEST,'real_time_deactivate')) {
+               facebook_subscription_del_users();
+       }
+}
+
 function facebook_jot_nets(&$a,&$b) {
        if(! local_user())
                return;
@@ -1158,3 +1318,188 @@ function fb_consume_stream($uid,$j,$wall = false) {
        }
 }
 
+
+function fb_get_app_access_token() {
+       
+       $acc_token = get_config('facebook','app_access_token');
+       
+       if ($acc_token !== false) return $acc_token;
+       
+       $appid = get_config('facebook','appid');
+       $appsecret = get_config('facebook', 'appsecret');
+       
+       if ($appid === false || $appsecret === false) {
+               logger('fb_get_app_access_token: appid and/or appsecret not set', LOGGER_DEBUG);
+               return false;
+       }
+       
+       $x = fetch_url('https://graph.facebook.com/oauth/access_token?client_id=' . $appid . '&client_secret=' . $appsecret . "&grant_type=client_credentials");
+       
+       if(strpos($x,'access_token=') !== false) {
+               logger('fb_get_app_access_token: returned access token: ' . $x, LOGGER_DATA);
+       
+               $token = str_replace('access_token=', '', $x);
+               if(strpos($token,'&') !== false)
+                       $token = substr($token,0,strpos($token,'&'));
+               
+               if ($token == "") {
+                       logger('fb_get_app_access_token: empty token: ' . $x, LOGGER_DEBUG);
+                       return false;
+               }
+               set_config('facebook','app_access_token',$token);
+               return $token;
+       } else {
+               logger('fb_get_app_access_token: response did not contain an access_token: ' . $x, LOGGER_DATA);
+               return false;
+       }
+}
+
+function facebook_subscription_del_users() {
+       $a = get_app();
+       $access_token = fb_get_app_access_token();
+       
+       $url = "https://graph.facebook.com/" . get_config('facebook', 'appid'  ) . "/subscriptions?access_token=" . $access_token;
+       facebook_delete_url($url);
+       
+       del_config('facebook', 'realtime_active');
+}
+
+function facebook_subscription_add_users() {
+       
+       $a = get_app();
+       $access_token = fb_get_app_access_token();
+       
+       $url = "https://graph.facebook.com/" . get_config('facebook', 'appid'  ) . "/subscriptions?access_token=" . $access_token;
+       
+       list($usec, $sec) = explode(" ", microtime());
+       $verify_token = sha1($usec . $sec . rand(0, 999999999));
+       set_config('facebook', 'cb_verify_token', $verify_token);
+       
+       $cb = $a->get_baseurl() . '/facebook/?realtime_cb=1';
+       
+       $j = post_url($url,array(
+               "object" => "user",
+               "fields" => "feed,friends",
+               "callback_url" => $cb,
+               "verify_token" => $verify_token,
+       ));
+       del_config('facebook', 'cb_verify_token');
+       
+       if ($j) {
+               logger("Facebook reponse: " . $j, LOGGER_DATA);
+               
+               if (facebook_check_realtime_active()) set_config('facebook', 'realtime_active', 1);
+       };
+}
+
+function facebook_subscriptions_get() {
+       
+       $access_token = fb_get_app_access_token();
+       if (!$access_token) return null;
+       
+       $url = "https://graph.facebook.com/" . get_config('facebook', 'appid'  ) . "/subscriptions?access_token=" . $access_token;
+       $j = fetch_url($url);
+       $ret = null;
+       if ($j) {
+               $x = json_decode($j);
+               if (isset($x->data)) $ret = $x->data;
+       }
+       return $ret;
+}
+
+
+function facebook_check_realtime_active() {
+       $ret = facebook_subscriptions_get();
+       if (is_null($ret)) return false;
+       if (is_array($ret)) foreach ($ret as $re) if (is_object($re) && $re->object == "user") return true;
+       return false;
+}
+
+
+
+
+// DELETE-request to $url
+
+if(! function_exists('facebook_delete_url')) {
+function facebook_delete_url($url,$headers = null, &$redirects = 0, $timeout = 0) {
+       $a = get_app();
+       $ch = curl_init($url);
+       if(($redirects > 8) || (! $ch)) 
+               return false;
+
+       curl_setopt($ch, CURLOPT_HEADER, true);
+       curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
+       curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
+       curl_setopt($ch, CURLOPT_USERAGENT, "Friendica");
+
+       if(intval($timeout)) {
+               curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
+       }
+       else {
+               $curl_time = intval(get_config('system','curl_timeout'));
+               curl_setopt($ch, CURLOPT_TIMEOUT, (($curl_time !== false) ? $curl_time : 60));
+       }
+
+       if(defined('LIGHTTPD')) {
+               if(!is_array($headers)) {
+                       $headers = array('Expect:');
+               } else {
+                       if(!in_array('Expect:', $headers)) {
+                               array_push($headers, 'Expect:');
+                       }
+               }
+       }
+       if($headers)
+               curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+
+       $check_cert = get_config('system','verifyssl');
+       curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
+       $prx = get_config('system','proxy');
+       if(strlen($prx)) {
+               curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
+               curl_setopt($ch, CURLOPT_PROXY, $prx);
+               $prxusr = get_config('system','proxyuser');
+               if(strlen($prxusr))
+                       curl_setopt($ch, CURLOPT_PROXYUSERPWD, $prxusr);
+       }
+
+       $a->set_curl_code(0);
+
+       // don't let curl abort the entire application
+       // if it throws any errors.
+
+       $s = @curl_exec($ch);
+
+       $base = $s;
+       $curl_info = curl_getinfo($ch);
+       $http_code = $curl_info['http_code'];
+
+       $header = '';
+
+       // Pull out multiple headers, e.g. proxy and continuation headers
+       // allow for HTTP/2.x without fixing code
+
+       while(preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/',$base)) {
+               $chunk = substr($base,0,strpos($base,"\r\n\r\n")+4);
+               $header .= $chunk;
+               $base = substr($base,strlen($chunk));
+       }
+
+       if($http_code == 301 || $http_code == 302 || $http_code == 303) {
+        $matches = array();
+        preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches);
+        $url = trim(array_pop($matches));
+        $url_parsed = @parse_url($url);
+        if (isset($url_parsed)) {
+            $redirects++;
+            return delete_url($url,$headers,$redirects,$timeout);
+        }
+    }
+       $a->set_curl_code($http_code);
+       $body = substr($s,strlen($header));
+
+       $a->set_curl_headers($header);
+
+       curl_close($ch);
+       return($body);
+}}
\ No newline at end of file
diff --git a/gnot.tgz b/gnot.tgz
new file mode 100644 (file)
index 0000000..fbf7f26
Binary files /dev/null and b/gnot.tgz differ
diff --git a/gnot/gnot.css b/gnot/gnot.css
new file mode 100755 (executable)
index 0000000..ccafdaf
--- /dev/null
@@ -0,0 +1,16 @@
+
+#gnot-desc {
+       margin-bottom: 10px;
+}
+
+#gnot-label {
+       float: left;
+       width: 200px;
+       margin-bottom: 25px;
+}
+
+#gnot {
+       float: left;
+}
+
+
diff --git a/gnot/gnot.php b/gnot/gnot.php
new file mode 100755 (executable)
index 0000000..fd8fdfd
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+/**
+ * Name: Gnot
+ * Description: Thread email comment notifications on Gmail and anonymise them
+ * Version: 1.0
+ * Author: Mike Macgirvin <http://macgirvin.com/profile/mike>
+ * 
+ *
+ */
+
+
+function gnot_install() {
+
+       register_hook('plugin_settings', 'addon/gnot/gnot.php', 'gnot_settings');
+       register_hook('plugin_settings_post', 'addon/gnot/gnot.php', 'gnot_settings_post');
+       register_hook('enotify_mail', 'addon/gnot/gnot.php', 'gnot_enotify_mail');
+
+       logger("installed gnot");
+}
+
+
+function gnot_uninstall() {
+
+       unregister_hook('plugin_settings', 'addon/gnot/gnot.php', 'gnot_settings');
+       unregister_hook('plugin_settings_post', 'addon/gnot/gnot.php', 'gnot_settings_post');
+       unregister_hook('enotify_mail', 'addon/gnot/gnot.php', 'gnot_enotify_mail');
+
+
+       logger("removed gnot");
+}
+
+
+
+/**
+ *
+ * Callback from the settings post function.
+ * $post contains the $_POST array.
+ * We will make sure we've got a valid user account
+ * and if so set our configuration setting for this person.
+ *
+ */
+
+function gnot_settings_post($a,$post) {
+       if(! local_user() || (! x($_POST,'gnot-submit')))
+               return;
+
+       set_pconfig(local_user(),'gnot','enable',intval($_POST['gnot']));
+       info( t('Gnot settings updated.') . EOL);
+}
+
+
+/**
+ *
+ * Called from the Plugin Setting form. 
+ * Add our own settings info to the page.
+ *
+ */
+
+
+
+function gnot_settings(&$a,&$s) {
+
+       if(! local_user())
+               return;
+
+       /* Add our stylesheet to the page so we can make our settings look nice */
+
+       $a->page['htmlhead'] .= '<link rel="stylesheet"  type="text/css" href="' . $a->get_baseurl() . '/addon/gnot/gnot.css' . '" media="all" />' . "\r\n";
+
+       /* Get the current state of our config variable */
+
+       $gnot = intval(get_pconfig(local_user(),'gnot','enable'));
+
+       $gnot_checked = (($gnot) ? ' checked="checked" ' : '' );
+       
+       /* Add some HTML to the existing form */
+
+       $s .= '<div class="settings-block">';
+       $s .= '<h3>' . t('Gnot Settings') . '</h3>';
+       $s .= '<div id="gnot-wrapper">';
+       $s .= '<div id="gnot-desc">' . t("Allows threading of email comment notifications on Gmail and anonymising the subject line.") . '</div>';
+       $s .= '<label id="gnot-label" for="gnot">' . t('Enable this plugin/addon?') . '</label>';
+       $s .= '<input id="gnot-input" type="checkbox" name="gnot" value="1"'.  $gnot_checked . '/>';
+       $s .= '</div><div class="clear"></div>';
+
+       /* provide a submit button */
+
+       $s .= '<div class="settings-submit-wrapper" ><input type="submit" name="gnot-submit" class="settings-submit" value="' . t('Submit') . '" /></div></div>';
+
+}
+
+
+function gnot_enotify_mail(&$a,&$b) {
+       if((! $b['uid']) || (! intval(get_pconfig($b['uid'], 'gnot','enable'))))
+               return;
+       if($b['type'] == NOTIFY_COMMENT)
+               $b['subject'] = sprintf( t('[Friendica:Notify] Comment to conversation #%d'), $b['parent']);
+}
+
diff --git a/irc/irc.php b/irc/irc.php
new file mode 100644 (file)
index 0000000..397844e
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/**
+* Name: IRC Chat Plugin
+* Description: add an Internet Relay Chat chatroom
+* Version: 1.0
+* Author: tony baldwin <http://tonybaldwin.me>
+*/
+
+
+function irc_install() {
+register_hook('app_menu', 'addon/irc/irc.php', 'irc_app_menu');
+}
+
+function irc_uninstall() {
+unregister_hook('app_menu', 'addon/irc/irc.php', 'irc_app_menu');
+
+}
+
+function irc_app_menu($a,&$b) {
+$b['app_menu'][] = '<div class="app-title"><a href="irc">' . t('irc Chatroom') . '</a></div>';
+}
+
+
+function irc_module() {
+return;
+}
+
+
+function irc_content(&$a) {
+
+$baseurl = $a->get_baseurl() . '/addon/irc';
+$o = '';
+
+
+ // add the chatroom frame and some html
+  $o .= <<< EOT
+<h2>IRC chat</h2>
+<iframe src="http://webchat.freenode.net?channels=friendica" width="600" height="600"></iframe>
+EOT;
+
+return $o;
+    
+}
+
+
diff --git a/ljpost.tgz b/ljpost.tgz
new file mode 100644 (file)
index 0000000..60c223f
Binary files /dev/null and b/ljpost.tgz differ
diff --git a/ljpost/ljpost.css b/ljpost/ljpost.css
new file mode 100755 (executable)
index 0000000..2087d3f
--- /dev/null
@@ -0,0 +1,32 @@
+
+#ljpost-enable-label, #ljpost-username-label, #ljpost-password-label, #ljpost-bydefault-label {
+<<<<<<< HEAD
+       float: left;
+       width: 200px;
+       margin-top: 10px;
+}
+
+#ljpost-checkbox, #ljpost-username, #ljpost-password, #ljpost-bydefault {
+       float: left;
+       margin-top: 10px;
+}
+
+#ljpost-submit {
+       margin-top: 15px;
+}
+
+=======
+float: left;
+width: 200px;
+margin-top: 10px;
+}
+
+#ljpost-checkbox, #ljpost-username, #ljpost-password, #ljpost-bydefault {
+float: left;
+margin-top: 10px;
+}
+
+#ljpost-submit {
+margin-top: 15px;
+}
+>>>>>>> 99d9fddb6af9e872266666038447771e42ce13b4
diff --git a/ljpost/ljpost.php b/ljpost/ljpost.php
new file mode 100755 (executable)
index 0000000..e1bd2d6
--- /dev/null
@@ -0,0 +1,246 @@
+<?php
+
+/**
+ * Name: LiveJournal Post Connector
+ * Description: Post to LiveJournal
+ * Version: 1.0
+ * Author: Tony Baldwin <http://tonybaldwin.me/friendica/profile/tony>
+ * Author: Michael Johnston
+ * Author: Cat Gray <https://free-haven.org/profile/catness>
+ */
+
+function ljpost_install() {
+    register_hook('post_local',           'addon/ljpost/ljpost.php', 'ljpost_post_local');
+    register_hook('notifier_normal',      'addon/ljpost/ljpost.php', 'ljpost_send');
+    register_hook('jot_networks',         'addon/ljpost/ljpost.php', 'ljpost_jot_nets');
+    register_hook('connector_settings',      'addon/ljpost/ljpost.php', 'ljpost_settings');
+    register_hook('connector_settings_post', 'addon/ljpost/ljpost.php', 'ljpost_settings_post');
+
+}
+function ljpost_uninstall() {
+    unregister_hook('post_local',       'addon/ljpost/ljpost.php', 'ljpost_post_local');
+    unregister_hook('notifier_normal',  'addon/ljpost/ljpost.php', 'ljpost_send');
+    unregister_hook('jot_networks',     'addon/ljpost/ljpost.php', 'ljpost_jot_nets');
+    unregister_hook('connector_settings',      'addon/ljpost/ljpost.php', 'ljpost_settings');
+    unregister_hook('connector_settings_post', 'addon/ljpost/ljpost.php', 'ljpost_settings_post');
+
+}
+
+
+function ljpost_jot_nets(&$a,&$b) {
+    if(! local_user())
+        return;
+
+    $lj_post = get_pconfig(local_user(),'ljpost','post');
+    if(intval($lj_post) == 1) {
+        $lj_defpost = get_pconfig(local_user(),'ljpost','post_by_default');
+        $selected = ((intval($lj_defpost) == 1) ? ' checked="checked" ' : '');
+        $b .= '<div class="profile-jot-net"><input type="checkbox" name="ljpost_enable" ' . $selected . ' value="1" /> '
+            . t('Post to LiveJournal') . '</div>';
+    }
+}
+
+
+function ljpost_settings(&$a,&$s) {
+
+    if(! local_user())
+        return;
+
+    /* Add our stylesheet to the page so we can make our settings look nice */
+
+    $a->page['htmlhead'] .= '<link rel="stylesheet"  type="text/css" href="' . $a->get_baseurl() . '/addon/ljpost/ljpost.css' . '" media="all" />' . "\r\n";
+
+    /* Get the current state of our config variables */
+
+    $enabled = get_pconfig(local_user(),'ljpost','post');
+
+    $checked = (($enabled) ? ' checked="checked" ' : '');
+
+    $def_enabled = get_pconfig(local_user(),'ljpost','post_by_default');
+
+    $def_checked = (($def_enabled) ? ' checked="checked" ' : '');
+
+       $lj_username = get_pconfig(local_user(), 'ljpost', 'lj_username');
+       $lj_password = get_pconfig(local_user(), 'ljpost', 'lj_password');
+
+
+    /* Add some HTML to the existing form */
+
+    $s .= '<div class="settings-block">';
+    $s .= '<h3>' . t('LiveJournal Post Settings') . '</h3>';
+    $s .= '<div id="ljpost-enable-wrapper">';
+    $s .= '<label id="ljpost-enable-label" for="ljpost-checkbox">' . t('Enable LiveJournal Post Plugin') . '</label>';
+    $s .= '<input id="ljpost-checkbox" type="checkbox" name="ljpost" value="1" ' . $checked . '/>';
+    $s .= '</div><div class="clear"></div>';
+
+    $s .= '<div id="ljpost-username-wrapper">';
+    $s .= '<label id="ljpost-username-label" for="ljpost-username">' . t('LiveJournal username') . '</label>';
+    $s .= '<input id="ljpost-username" type="text" name="lj_username" value="' . $lj_username . '" />';
+    $s .= '</div><div class="clear"></div>';
+
+    $s .= '<div id="ljpost-password-wrapper">';
+    $s .= '<label id="ljpost-password-label" for="ljpost-password">' . t('LiveJournal password') . '</label>';
+    $s .= '<input id="ljpost-password" type="password" name="lj_password" value="' . $lj_password . '" />';
+    $s .= '</div><div class="clear"></div>';
+
+    $s .= '<div id="ljpost-bydefault-wrapper">';
+    $s .= '<label id="ljpost-bydefault-label" for="ljpost-bydefault">' . t('Post to LiveJournal by default') . '</label>';
+    $s .= '<input id="ljpost-bydefault" type="checkbox" name="lj_bydefault" value="1" ' . $def_checked . '/>';
+    $s .= '</div><div class="clear"></div>';
+
+    /* provide a submit button */
+
+    $s .= '<div class="settings-submit-wrapper" ><input type="submit" id="ljpost-submit" name="ljpost-submit" class="settings-submit" value="' . t('Submit') . '" /></div></div>';
+
+}
+
+
+function ljpost_settings_post(&$a,&$b) {
+
+       if(x($_POST,'ljpost-submit')) {
+
+               set_pconfig(local_user(),'ljpost','post',intval($_POST['ljpost']));
+               set_pconfig(local_user(),'ljpost','post_by_default',intval($_POST['lj_bydefault']));
+               set_pconfig(local_user(),'ljpost','lj_username',trim($_POST['lj_username']));
+               set_pconfig(local_user(),'ljpost','lj_password',trim($_POST['lj_password']));
+
+       }
+
+}
+
+function ljpost_post_local(&$a,&$b) {
+
+       // This can probably be changed to allow editing by pointing to a different API endpoint
+
+       if($b['edit'])
+               return;
+
+       if((! local_user()) || (local_user() != $b['uid']))
+               return;
+
+       if($b['private'] || $b['parent'])
+               return;
+
+    $lj_post   = intval(get_pconfig(local_user(),'ljpost','post'));
+
+       $lj_enable = (($lj_post && x($_REQUEST,'ljpost_enable')) ? intval($_REQUEST['ljpost_enable']) : 0);
+
+       if($_REQUEST['api_source'] && intval(get_pconfig(local_user(),'ljpost','post_by_default')))
+               $lj_enable = 1;
+
+    if(! $lj_enable)
+       return;
+
+    if(strlen($b['postopts']))
+       $b['postopts'] .= ',';
+     $b['postopts'] .= 'ljpost';
+}
+
+
+
+
+function ljpost_send(&$a,&$b) {
+
+    if($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited']))
+        return;
+
+    if(! strstr($b['postopts'],'ljpost'))
+        return;
+
+    if($b['parent'] != $b['id'])
+        return;
+
+       // LiveJournal post in the LJ user's timezone. 
+       // Hopefully the person's Friendica account
+       // will be set to the same thing.
+
+       $tz = 'UTC';
+
+       $x = q("select timezone from user where uid = %d limit 1",
+               intval($b['uid'])
+       );
+       if($x && strlen($x[0]['timezone']))
+               $tz = $x[0]['timezone'];        
+
+       $lj_username = xmlify(get_pconfig($b['uid'],'ljpost','lj_username'));
+       $lj_password = xmlify(get_pconfig($b['uid'],'ljpost','lj_password'));
+       $lj_journal = xmlify(get_pconfig($b['uid'],'ljpost','lj_journal'));
+//     if(! $lj_journal)
+//             $lj_journal = $lj_username;
+
+       $lj_blog = xmlify(get_pconfig($b['uid'],'ljpost','lj_blog'));
+       if(! strlen($lj_blog))
+               $lj_blog = xmlify('http://www.livejournal.com/interface/xmlrpc');
+
+       if($lj_username && $lj_password && $lj_blog) {
+
+               require_once('include/bbcode.php');
+               require_once('include/datetime.php');
+
+               $title = xmlify($b['title']);
+               $post = bbcode($b['body']);
+               $post = xmlify($post);
+               $tags = ljpost_get_tags($b['tag']);
+
+               $date = datetime_convert('UTC',$tz,$b['created'],'Y-m-d H:i:s');
+               $year = intval(substr($date,0,4));
+               $mon  = intval(substr($date,5,2));
+               $day  = intval(substr($date,8,2));
+               $hour = intval(substr($date,11,2));
+               $min  = intval(substr($date,14,2));
+
+               $xml = <<< EOT
+<?xml version="1.0" encoding="utf-8"?>
+<methodCall>
+  <methodName>LJ.XMLRPC.postevent</methodName>
+  <params>
+    <param><value>
+        <struct>
+        <member><name>username</name><value><string>$lj_username</string></value></member>
+        <member><name>password</name><value><string>$lj_password</string></value></member>
+        <member><name>event</name><value><string>$post</string></value></member>
+        <member><name>subject</name><value><string>$title</string></value></member>
+        <member><name>lineendings</name><value><string>unix</string></value></member>
+        <member><name>year</name><value><int>$year</int></value></member>
+        <member><name>mon</name><value><int>$mon</int></value></member>
+        <member><name>day</name><value><int>$day</int></value></member>
+        <member><name>hour</name><value><int>$hour</int></value></member>
+        <member><name>min</name><value><int>$min</int></value></member>
+               <member><name>usejournal</name><value><string>$lj_username</string></value></member>
+               <member>
+                       <name>props</name>
+                       <value>
+                               <struct>
+                                       <member>
+                                               <name>useragent</name>
+                                               <value><string>Friendica</string></value>
+                                       </member>
+                                       <member>
+                                               <name>taglist</name>
+                                               <value><string>$tags</string></value>
+                                       </member>
+                               </struct>
+                       </value>
+               </member>
+        </struct>
+    </value></param>
+  </params>
+</methodCall>
+
+EOT;
+
+               logger('ljpost: data: ' . $xml, LOGGER_DATA);
+
+               if($lj_blog !== 'test')
+                       $x = post_url($lj_blog,$xml);
+               logger('posted to livejournal: ' . ($x) ? $x : '', LOGGER_DEBUG);
+
+       }
+}
+
+function ljpost_get_tags($post)
+{
+       preg_match_all("/\]([^\[#]+)\[/",$post,$matches);
+       $tags = implode(', ',$matches[1]);
+       return $tags;
+}
index 2e572dc16a885970edfb88539df6d12e4e02b14f..65c92244a6d4f3f3dcf323f94d30e3c5bc523613 100755 (executable)
Binary files a/piwik.tgz and b/piwik.tgz differ
index 76dffda1c46b5eac43e558fa50e9ffa378a801e4..1ab55a43f8d3a0cc5b146950d35c7a65b5211726 100644 (file)
Binary files a/qcomment.tgz and b/qcomment.tgz differ
index 45e6332ef3603f5a0da6b74fe3da26608d9a5175..6b37257995412748a71daf5548a6dafdef912b6c 100755 (executable)
@@ -53,6 +53,7 @@ function qcomment_addon_settings(&$a,&$s) {
     $s .= '<div class="settings-block">';
     $s .= '<h3>' . t('Quick Comment Settings') . '</h3>';
     $s .= '<div id="qcomment-wrapper">';
+       $s .= '<div id="qcomment-desc">' . t("Quick comments are found near comment boxes, sometimes hidden. Click them to provide simple replies.") . '</div>';
     $s .= '<label id="qcomment-label" for="qcomment-words">' . t('Enter quick comments, one per line') . ' </label>';
     $s .= '<textarea id="qcomment-words" type="text" name="qcomment-words" >' . htmlspecialchars(unxmlify($words)) . '</textarea>';
     $s .= '</div><div class="clear"></div>';
index 3f248156943b5f594a78c840b05f8996033c7f63..05d56d88222be4e8b1c0154f2493d4fcdb54534f 100755 (executable)
Binary files a/statusnet.tgz and b/statusnet.tgz differ
index a76399260f78838bab2b8b2e8202d85493509d37..8f2fbf8190965e9a95a0a2237e3985ae341d4b2d 100755 (executable)
@@ -327,6 +327,9 @@ function statusnet_settings(&$a,&$s) {
                        $details = $connection->get('account/verify_credentials');
                        $s .= '<div id="statusnet-info" ><img id="statusnet-avatar" src="'.$details->profile_image_url.'" /><p id="statusnet-info-block">'. t('Currently connected to: ') .'<a href="'.$details->statusnet_profile_url.'" target="_statusnet">'.$details->screen_name.'</a><br /><em>'.$details->description.'</em></p></div>';
                        $s .= '<p>'. t('If enabled all your <strong>public</strong> postings can be posted to the associated StatusNet account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.') .'</p>';
+                        if ($a->user['hidewall']) {
+                            $s .= '<p>'. t('<strong>Note</strong>: Due your privacy settings (<em>Hide your profile details from unknown viewers?</em>) the link potentially included in public postings relayed to StatusNet will lead the visitor to a blank page informing the visitor that the access to your profile has been restricted.') .'</p>';
+                        }
                        $s .= '<div id="statusnet-enable-wrapper">';
                        $s .= '<label id="statusnet-enable-label" for="statusnet-checkbox">'. t('Allow posting to StatusNet') .'</label>';
                        $s .= '<input id="statusnet-checkbox" type="checkbox" name="statusnet-enable" value="1" ' . $checked . '/>';
index 1b93943c2117c0b40715b7735dd0fe165fa34699..e3fbdec50cd041db5154c1a6d883b4341b6151a2 100755 (executable)
Binary files a/twitter.tgz and b/twitter.tgz differ
index 3b816e3be07ee1360ec21ee062979d2af1b4a3b3..fd0324635fa5c407eb65a98b08e814297b570d0e 100755 (executable)
@@ -183,6 +183,9 @@ function twitter_settings(&$a,&$s) {
                        $details = $connection->get('account/verify_credentials');
                        $s .= '<div id="twitter-info" ><img id="twitter-avatar" src="'.$details->profile_image_url.'" /><p id="twitter-info-block">'. t('Currently connected to: ') .'<a href="https://twitter.com/'.$details->screen_name.'" target="_twitter">'.$details->screen_name.'</a><br /><em>'.$details->description.'</em></p></div>';
                        $s .= '<p>'. t('If enabled all your <strong>public</strong> postings can be posted to the associated Twitter account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.') .'</p>';
+                        if ($a->user['hidewall']) {
+                            $s .= '<p>'. t('<strong>Note</strong>: Due your privacy settings (<em>Hide your profile details from unknown viewers?</em>) the link potentially included in public postings relayed to Twitter will lead the visitor to a blank page informing the visitor that the access to your profile has been restricted.') .'</p>';
+                        }
                        $s .= '<div id="twitter-enable-wrapper">';
                        $s .= '<label id="twitter-enable-label" for="twitter-checkbox">'. t('Allow posting to Twitter'). '</label>';
                        $s .= '<input id="twitter-checkbox" type="checkbox" name="twitter-enable" value="1" ' . $checked . '/>';
index 6dad5c117973a78a07fc7ea29a3b82d21bed43aa..12f96d3b0c569d433447d2fb11310e8ef953834f 100755 (executable)
Binary files a/wppost.tgz and b/wppost.tgz differ
index 5c1482e7864c46f07e69db795ae1d703eddd4b88..264a342c0c0733c5934b218bb0f9646984e3257b 100755 (executable)
@@ -161,8 +161,8 @@ function wppost_send(&$a,&$b) {
         return;
 
 
-       $wp_username = get_pconfig($b['uid'],'wppost','wp_username');
-       $wp_password = get_pconfig($b['uid'],'wppost','wp_password');
+       $wp_username = xmlify(get_pconfig($b['uid'],'wppost','wp_username'));
+       $wp_password = xmlify(get_pconfig($b['uid'],'wppost','wp_password'));
        $wp_blog = get_pconfig($b['uid'],'wppost','wp_blog');
 
        if($wp_username && $wp_password && $wp_blog) {
@@ -174,8 +174,7 @@ function wppost_send(&$a,&$b) {
                $post = xmlify($post);
 
                $xml = <<< EOT
-
-<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>
+<?xml version=\"1.0\" encoding=\"utf-8\"?>
 <methodCall>
   <methodName>blogger.newPost</methodName>
   <params>
@@ -194,7 +193,7 @@ EOT;
 
                if($wp_blog !== 'test')
                        $x = post_url($wp_blog,$xml);
-               logger('posted to wordpress: ' . ($x) ? $x : '');
+               logger('posted to wordpress: ' . (($x) ? $x : ''), LOGGER_DEBUG);
 
        }
 }