Twitter from FWH apps

Twitter from FWH apps

Postby Antonio Linares » Tue Feb 12, 2013 12:43 pm

These are the first steps towards a Class Twitter for FWH based on Curl :-)

Based on this example:
http://www.barattalo.it/2010/09/09/how-to-change-twitter-status-with-php-and-curl-without-oauth/

and using the curl library for Harbour, available from here:
http://code.google.com/p/harbour-and-xharbour-builds/downloads/detail?name=hbcurl.zip&can=2&q=

This is the first test:
Code: Select all  Expand view  RUN
#include "FiveWin.ch"
#include "hbcurl.ch"

function Main()

   local hCurl, cPage := Space( 200 )

   curl_global_init()

   if ! Empty( hCurl := curl_easy_init() )
      curl_easy_setopt( hCurl, HB_CURLOPT_URL, "https://mobile.twitter.com/session/new" )
      curl_easy_setopt( hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )
      curl_easy_setopt( hCurl, HB_CURLOPT_FAILONERROR, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_FOLLOWLOCATION, 1 )
      // curl_easy_setopt( hCurl, HB_CURLOPT_RETURNTRANSFER, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_TIMEOUT, 5 )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEJAR, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEFILE, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_USERAGENT, "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 " )
        curl_easy_setopt( hCurl, HB_CURLOPT_ERRORBUFFER, @cPage )
       
        MsgInfo( curl_easy_perform( hCurl ) )
      MsgInfo( curl_easy_dl_buff_get( hCurl ) )
       
      curl_easy_reset( hCurl )
   endif

   curl_global_cleanup()

return nil


We need to find the value for CURLOPT_RETURNTRANSFER. It is not available in Harbour's hbcurl.ch
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42107
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Twitter from FWH apps

Postby Antonio Linares » Tue Feb 12, 2013 12:56 pm

Found :-)

#define HB_CURLOPT_RETURNTRANSFER 500
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42107
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Twitter from FWH apps

Postby Antonio Linares » Tue Feb 12, 2013 1:26 pm

This version already retrieves the Twitter web page :-)

Code: Select all  Expand view  RUN
#include "FiveWin.ch"
#include "hbcurl.ch"

function Main()

   local hCurl

   curl_global_init()

   if ! Empty( hCurl := curl_easy_init() )
      curl_easy_setopt( hCurl, HB_CURLOPT_URL, "https://mobile.twitter.com/session/new" )
      curl_easy_setopt( hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )
      curl_easy_setopt( hCurl, HB_CURLOPT_FAILONERROR, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_FOLLOWLOCATION, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_TIMEOUT, 5 )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEJAR, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEFILE, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_USERAGENT, "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 " )
       
        curl_easy_setopt( hCurl, HB_CURLOPT_DL_FILE_SETUP, "twitter.html" )
        curl_easy_perform( hCurl )
       
      curl_easy_reset( hCurl )
      MsgInfo( MemoRead( "twitter.html" ) )
   endif

   curl_global_cleanup()

return nil  
 
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42107
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Twitter from FWH apps

Postby Antonio Linares » Tue Feb 12, 2013 2:31 pm

A further step:

Code: Select all  Expand view  RUN
#include "FiveWin.ch"
#include "hbcurl.ch"

function Main()

   local hCurl, aMatch, cPage, cAction

   curl_global_init()

   if ! Empty( hCurl := curl_easy_init() )
      curl_easy_setopt( hCurl, HB_CURLOPT_URL, "https://mobile.twitter.com/session/new" )
      curl_easy_setopt( hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )
      curl_easy_setopt( hCurl, HB_CURLOPT_FAILONERROR, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_FOLLOWLOCATION, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_TIMEOUT, 5 )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEJAR, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEFILE, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_USERAGENT, "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 " )
       
      curl_easy_setopt( hCurl, HB_CURLOPT_DL_FILE_SETUP, "twitter.html" )
      curl_easy_perform( hCurl )
       
      curl_easy_reset( hCurl )
     
      cPage = MemoRead( "twitter.html" )
     
      aMatch  = HB_RegExAll( 'form action="(.*?)" method="(.*?)"', cPage, .F., .T. )
      cPage   = aMatch[ 1 ][ 2 ]
      cAction = aMatch[ 1 ][ 3 ]
     
      MsgInfo( cAction )
   endif

   curl_global_cleanup()

return nil  
 
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42107
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Twitter from FWH apps

Postby Antonio Linares » Tue Feb 12, 2013 2:55 pm

Retrieving the authenticity token:

Code: Select all  Expand view  RUN
#include "FiveWin.ch"
#include "hbcurl.ch"

function Main()

   local hCurl, aMatch, cPage, cURL, cAction

   curl_global_init()

   if ! Empty( hCurl := curl_easy_init() )
      curl_easy_setopt( hCurl, HB_CURLOPT_URL, "https://mobile.twitter.com/session/new" )
      curl_easy_setopt( hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )
      curl_easy_setopt( hCurl, HB_CURLOPT_FAILONERROR, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_FOLLOWLOCATION, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_TIMEOUT, 5 )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEJAR, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEFILE, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_USERAGENT, "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 " )
       
      curl_easy_setopt( hCurl, HB_CURLOPT_DL_FILE_SETUP, "twitter.html" )
      curl_easy_perform( hCurl )
       
      curl_easy_reset( hCurl )
     
      cPage = MemoRead( "twitter.html" )
     
      aMatch  = HB_RegExAll( 'form action="(.*?)" method="(.*?)"', cPage, .F., .T. )
      cURL    = aMatch[ 1 ][ 2 ]
      cAction = aMatch[ 1 ][ 3 ]
      aMatch  = HB_RegExAll( 'type="hidden" value="(.*?)"', cPage, .F., .T. )
      cAuthenticity_token = aMatch[ 1 ][ 2 ]
     
      MsgInfo( cAuthenticity_token )
   endif

   curl_global_cleanup()

return nil  
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42107
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Twitter from FWH apps

Postby Antonio Linares » Wed Feb 13, 2013 1:30 pm

This version already login into twitter :-)

UrlEncode() has been copied from tip_urlencode(), but I have included it so we don't need to link hbtip.

If you open, with your web browser, the file twitter.html that this app creates, you will see that you are already logged into your twitter account :-)

twitter.prg
Code: Select all  Expand view  RUN
#include "FiveWin.ch"
#include "hbcurl.ch"

function Main()

   TwitterSetStatus( cUserName, cPassword )

return nil

function TwitterSetStatus( cUser, cPassword, cStatus )

   local hCurl, aMatch, cPage, cURL, cAction, cAuthenticity_token, cPost

   curl_global_init()

   if ! Empty( hCurl := curl_easy_init() )
      curl_easy_setopt( hCurl, HB_CURLOPT_URL, "https://mobile.twitter.com/session/new" )
      curl_easy_setopt( hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )
      curl_easy_setopt( hCurl, HB_CURLOPT_FAILONERROR, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_FOLLOWLOCATION, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_TIMEOUT, 5 )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEJAR, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEFILE, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_USERAGENT, "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 " )
       
      curl_easy_setopt( hCurl, HB_CURLOPT_DL_FILE_SETUP, "twitter.html" )
      curl_easy_perform( hCurl )
       
      curl_easy_reset( hCurl )
     
      cPage = MemoRead( "twitter.html" )
     
      aMatch  = HB_RegExAll( 'form action="(.*?)" method="(.*?)"', cPage, .F., .T. )
      cURL    = aMatch[ 1 ][ 2 ]
      cAction = aMatch[ 1 ][ 3 ]
      aMatch  = HB_RegExAll( 'type="hidden" value="(.*?)"', cPage, .F., .T. )
      cAuthenticity_token = aMatch[ 1 ][ 2 ]
     
      cPost = "authenticity_token=" + urlencode( cAuthenticity_token ) + ;
              "&username=" + urlencode( cUser ) + ;
              "&password=" + urlencode( cPassword )
      curl_easy_init()
      curl_easy_setopt( hCurl, HB_CURLOPT_URL, cURL )
      curl_easy_setopt( hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )
      curl_easy_setopt( hCurl, HB_CURLOPT_FAILONERROR, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_FOLLOWLOCATION, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_TIMEOUT, 5 )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEJAR, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEFILE, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_USERAGENT, "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 " )
      curl_easy_setopt( hCurl, HB_CURLOPT_POSTFIELDS, cPost )
      curl_easy_setopt( hCurl, HB_CURLOPT_DL_FILE_SETUP, "twitter.html" )
      curl_easy_perform( hCurl )
      curl_easy_reset( hCurl )
     
      cPage = MemoRead( "twitter.html" )
      MsgInfo( cPage )
   endif

   curl_global_cleanup()

return nil  

#pragma BEGINDUMP

#include <hbapi.h>
#include <hbapiitm.h>
#include <hbapierr.h>

HB_FUNC( URLENCODE )
{
   const char * cData     = hb_parc( 1 );
   HB_ISIZ      nLen      = hb_parclen( 1 );
   HB_BOOL      bComplete = hb_parldef( 2, HB_TRUE );
   char *       cRet;
   HB_ISIZ      nPos = 0, nPosRet = 0, nVal;
   char         cElem;

   if( ! cData )
   {
      hb_errRT_BASE( EG_ARG, 3012, NULL,
                     HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) );
      return;
   }

   if( ! nLen )
   {
      hb_retc_null();
      return;
   }

   /* Giving maximum final length possible */
   cRet = ( char * ) hb_xgrab( nLen * 3 + 1 );

   while( nPos < nLen )
   {
      cElem = cData[ nPos ];

      if( cElem == ' ' )
      {
         cRet[ nPosRet ] = '+';
      }
      else if(
         ( cElem >= 'A' && cElem <= 'Z' ) ||
         ( cElem >= 'a' && cElem <= 'z' ) ||
         ( cElem >= '0' && cElem <= '9' ) ||
         cElem == '.' || cElem == ',' || cElem == '&' ||
         cElem == '/' || cElem == ';' || cElem == '_' )
      {
         cRet[ nPosRet ] = cElem;
      }
      else if( ! bComplete && ( cElem == ':' || cElem == '?' || cElem == '=' ) )
      {
         cRet[ nPosRet ] = cElem;
      }
      else /* encode! */
      {
         cRet[ nPosRet++ ] = '%';
         nVal = ( ( HB_UCHAR ) cElem ) >> 4;
         cRet[ nPosRet++ ] = nVal < 10 ? '0' + ( char ) nVal : 'A' + ( char ) nVal - 10;
         nVal = ( ( HB_UCHAR ) cElem ) & 0x0F;
         cRet[ nPosRet ] = nVal < 10 ? '0' + ( char ) nVal : 'A' + ( char ) nVal - 10;
      }

      nPosRet++;
      nPos++;
   }

   hb_retclen_buffer( cRet, nPosRet );
}

#pragma ENDDUMP
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42107
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Twitter from FWH apps

Postby Antonio Linares » Mon Feb 18, 2013 4:24 pm

This version should work. Your tests and feedback are welcome :-)

Code: Select all  Expand view  RUN
#include "FiveWin.ch"
#include "hbcurl.ch"

function Main()

   TwitterSetStatus( "username", "password", "Testing from an app" )

return nil

function TwitterSetStatus( cUser, cPassword, cStatus )

   local hCurl, aMatch, cPage, cURL, cAction, cAuthenticity_token, cPost

   curl_global_init()

   if ! Empty( hCurl := curl_easy_init() )
      curl_easy_setopt( hCurl, HB_CURLOPT_URL, "https://mobile.twitter.com/session/new" )
      curl_easy_setopt( hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )
      curl_easy_setopt( hCurl, HB_CURLOPT_FAILONERROR, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_FOLLOWLOCATION, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_TIMEOUT, 5 )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEJAR, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEFILE, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_USERAGENT, "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 " )
       
      curl_easy_setopt( hCurl, HB_CURLOPT_DL_FILE_SETUP, "twitter.html" )
      curl_easy_perform( hCurl )
       
      curl_easy_reset( hCurl )
     
      cPage = MemoRead( "twitter.html" )
     
      aMatch  = HB_RegExAll( 'form action="(.*?)" method="(.*?)"', cPage, .F., .T. )
      cURL    = aMatch[ 1 ][ 2 ]
      cAction = aMatch[ 1 ][ 3 ]
      aMatch  = HB_RegExAll( 'type="hidden" value="(.*?)"', cPage, .F., .T. )
      cAuthenticity_token = aMatch[ 1 ][ 2 ]

      MsgInfo( cURL )
     
      cPost = "authenticity_token=" + urlencode( cAuthenticity_token ) + ;
              "&username=" + urlencode( cUser ) + ;
              "&password=" + urlencode( cPassword )
      curl_easy_init()
      curl_easy_setopt( hCurl, HB_CURLOPT_URL, cURL )
      curl_easy_setopt( hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )
      curl_easy_setopt( hCurl, HB_CURLOPT_FAILONERROR, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_FOLLOWLOCATION, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_TIMEOUT, 5 )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEJAR, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEFILE, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_USERAGENT, "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 " )
      curl_easy_setopt( hCurl, HB_CURLOPT_POSTFIELDS, cPost )
      curl_easy_setopt( hCurl, HB_CURLOPT_DL_FILE_SETUP, "twitter.html" )
      curl_easy_perform( hCurl )
      curl_easy_reset( hCurl )

      cPage = MemoRead( "twitter.html" )

      aMatch  = HB_RegExAll( 'form action="(.*?)" class="(.*?)" method="(.*?)"', cPage, .F., .T. )
      cURL    = aMatch[ 1 ][ 2 ]
      cAction = aMatch[ 1 ][ 3 ]
     
      cPage = MemoRead( "twitter.html" )
      aMatch  = HB_RegExAll( 'type="hidden" value="(.*?)"', cPage, .F., .T. )
      cAuthenticity_token = aMatch[ 1 ][ 2 ]

      cPost = "authenticity_token=" + urlencode( cAuthenticity_token ) + ;
              "&display_coordinates=" + "" + ;
              "&in_reply_to_status_id=" + "" + ;
              "&lat=" + "" + ;
              "&long=" + "" + ;
              "&place_id=" + "" + ;
              "&text=" + cStatus

      curl_easy_init()
      curl_easy_setopt( hCurl, HB_CURLOPT_URL, cURL )
      curl_easy_setopt( hCurl, HB_CURLOPT_SSL_VERIFYPEER, .F. )
      curl_easy_setopt( hCurl, HB_CURLOPT_FAILONERROR, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_FOLLOWLOCATION, 1 )
      curl_easy_setopt( hCurl, HB_CURLOPT_TIMEOUT, 5 )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEJAR, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_COOKIEFILE, "my_cookies.txt" )
      curl_easy_setopt( hCurl, HB_CURLOPT_USERAGENT, "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 " )
      curl_easy_setopt( hCurl, HB_CURLOPT_POSTFIELDS, cPost )
      curl_easy_setopt( hCurl, HB_CURLOPT_DL_FILE_SETUP, "twitter.html" )
      curl_easy_perform( hCurl )
      curl_easy_reset( hCurl )

      MsgInfo( "done" )
   endif

   curl_global_cleanup()

return nil  

#pragma BEGINDUMP

#include <hbapi.h>
#include <hbapiitm.h>
#include <hbapierr.h>

HB_FUNC( URLENCODE )
{
   const char * cData     = hb_parc( 1 );
   HB_ISIZ      nLen      = hb_parclen( 1 );
   HB_BOOL      bComplete = hb_parldef( 2, HB_TRUE );
   char *       cRet;
   HB_ISIZ      nPos = 0, nPosRet = 0, nVal;
   char         cElem;

   if( ! cData )
   {
      hb_errRT_BASE( EG_ARG, 3012, NULL,
                     HB_ERR_FUNCNAME, 1, hb_paramError( 1 ) );
      return;
   }

   if( ! nLen )
   {
      hb_retc_null();
      return;
   }

   /* Giving maximum final length possible */
   cRet = ( char * ) hb_xgrab( nLen * 3 + 1 );

   while( nPos < nLen )
   {
      cElem = cData[ nPos ];

      if( cElem == ' ' )
      {
         cRet[ nPosRet ] = '+';
      }
      else if(
         ( cElem >= 'A' && cElem <= 'Z' ) ||
         ( cElem >= 'a' && cElem <= 'z' ) ||
         ( cElem >= '0' && cElem <= '9' ) ||
         cElem == '.' || cElem == ',' || cElem == '&' ||
         cElem == '/' || cElem == ';' || cElem == '_' )
      {
         cRet[ nPosRet ] = cElem;
      }
      else if( ! bComplete && ( cElem == ':' || cElem == '?' || cElem == '=' ) )
      {
         cRet[ nPosRet ] = cElem;
      }
      else /* encode! */
      {
         cRet[ nPosRet++ ] = '%';
         nVal = ( ( HB_UCHAR ) cElem ) >> 4;
         cRet[ nPosRet++ ] = nVal < 10 ? '0' + ( char ) nVal : 'A' + ( char ) nVal - 10;
         nVal = ( ( HB_UCHAR ) cElem ) & 0x0F;
         cRet[ nPosRet ] = nVal < 10 ? '0' + ( char ) nVal : 'A' + ( char ) nVal - 10;
      }

      nPosRet++;
      nPos++;
   }

   hb_retclen_buffer( cRet, nPosRet );
}

#pragma ENDDUMP
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42107
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Twitter from FWH apps

Postby Antonio Linares » Fri Feb 22, 2013 2:54 am

Examples to implement the Twitter search API:

http://www.desarrolloweb.com/articulos/api-twitter-php-curl.html
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42107
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 29 guests