So I've started working on this twitter script that targets users who tweet about my website, and I want to set up this up with cron job to thank them for doing so. This is how it works:
Parses usernames from search page (15 in total)
Loops through all 15 user names and if its found in the twitter.txt file
it will stop the script
If the user name is not found in the twitter.txt file it will write
the user name to the twitter.txt file and then send a tweet to that user. (twitter.txt file helps to prevent sending of duplicate tweets to the same user)
So my issue is that this script currently sends out 15 tweets in one sitting and this would be considered spam. So I need help to be able to consolidate the user names in to 3 tweets. So each tweet will contain 5 user names. You will seet at the bottom of the script where i have the variables to store the usernames for the tweets.
//cURL
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "http://search.twitter.com/search.atom?q=MYWEBSITE");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$twitter = curl_exec($curl);
curl_close($curl);
//search html source page for user names
preg_match_all('/\<uri\>http\:\/\/twitter\.com\/(.*?)\<\/uri\>/', $twitter, $usernames);
//open the twitter text file and prepare for writing
$twitter = fopen("twitter.txt", "a");
//contents of the twitter text file (holds the twitter user names)
$contents = file_get_contents("twitter.txt");
//loop through each user name
foreach($usernames[1] as $username) {
//if user name is found in the twitter text file it states "Found" and script stops
if (strpos($contents, $username) !== FALSE) {
echo $username . " - <font color=\"red\">Found</font><br />";
//if user name is not found in the twitter text file it records the user name and tweets
} else {
//write to twitter text file
fwrite($twitter, $username."\r\n");
//shows what user names were recorded
echo $username . "<br />";
//user names for tweets
//this is where i need help dividing the usernames into these variables
$usernames_set_one = "";
$usernames_set_two = "";
$usernames_set_three = "";
//tweet
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, OAUTH_TOKEN, OAUTH_SECRET);
$content = $connection->get('account/verify_credentials');
//twitter message
$connection->post('statuses/update', array('status' => $usernames_set_one . ' thank you for tweeting about my website.' ));
$connection->post('statuses/update', array('status' => $usernames_set_two . ' thank you for tweeting about my website.' ));
$connection->post('statuses/update', array('status' => $usernames_set_three . ' thank you for tweeting about my website.' ));
return $connection;
}
}
//close the twitter text file no further writing
fclose($twitter);
You can use a while loop instead of foreach and then access the usernames as:
$usernames[1][$i];
$usernames[1][$i+1];
$usernames[1][$i+2];
For example:
$i = 0;
$count = count($usernames[1]);
while($i < $count - 3) //we will use $i+2 after all
{
$i++;
}
Change those 3 variables to arrays and when the first one is full add usernames to the second array and then to the third. When posting to twitter simply join the names with implode().
Related
I have a POST function contained in my page. I am trying to call it directly for my CURL Function, notice in the following code the url variable is set to http://dirtrif.loc/installs.php
//extract data from the post
//set POST variables
$cookie_name = "drcuserid";
if(isset($_COOKIE[$cookie_name]))
{
$cookie = $_COOKIE[$cookie_name];
}
$url = 'http://dirtrif.loc/installs.php';
$fields['username'] = $vbulletin->userinfo[username];
$fields['webmasteremail'] = $vbulletin->options[webmasteremail];
$fields['cookie'] = $_COOKIE[$cookie_name];
//url-ify the data for the POST
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string, '&');
//open connection
$ch = curl_init();
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
//execute post
$result = curl_exec($ch);
//close connection
curl_close($ch);
echo $fields_string;
This is causing an issue when the CURL script is executed, by navigating to the actual page and not running the portion that it's supposed to.
I currently have the post portion set up as follows in my installs.php:
if (isset($_POST['username'])) {
$vbulletin->db->query_write("
INSERT INTO " . TABLE_PREFIX . "installs (
username,
webmasteremail,
cookie
) VALUES (" .
$_POST['username'] .", '" .
$_POST['webmasteremail'] . ", '" .
$_POST['cookie'] . "'
)");
}
Is there a way I can change the URL in my CURL code to point directly to that part of the installs.php page?
the full contents of installs.php (note* I have made a few changes since posting this question)
<?php
// ####################### SET PHP ENVIRONMENT ###########################
error_reporting(E_ALL & ~E_NOTICE);
// #################### DEFINE IMPORTANT CONSTANTS #######################
define('THIS_SCRIPT', 'installs');
define('CSRF_PROTECTION', true);
define('CSRF_SKIP_LIST', '');
// ################### PRE-CACHE TEMPLATES AND DATA ######################
// pre-cache templates used by all actions
$globaltemplates = array(
'installs'
);
// pre-cache templates used by specific actions
$actiontemplates = array();
// ######################### REQUIRE BACK-END ############################
require_once('./global.php');
// ######################### VARIABLES ############################
$username = $_POST['username'];
$userid = $_POST['userid'];
$email = $_POST['email'];
$addontitle = $_POST['addontitle'];
$addonversion = $_POST['addonversion'];
$bburl = $_POST['bburl'];
$bbtitle = $_POST['bbtitle'];
$webmasteremail = $_POST['webmasteremail'];
$cookie = $_POST['cookie'];
if (isset($_POST['username'])) {
$db->query_write("
INSERT INTO " . TABLE_PREFIX . "installs (
username,userid,email,addontitle,addonversion,bburl,bbtitle,webmasteremail,cookie,dateline
) VALUES (
'$username',
'$userid',
'$email',
'$addontitle',
'$addonversion',
'$bburl',
'$bbtitle',
'$webmasteremail',
'$cookie',
NOW()
)");
}
// #######################################################################
// ######################## START MAIN SCRIPT ############################
// #######################################################################
$navbits = array();
$navbits[$parent] = 'Installs Page';
$navbits = construct_navbits($navbits);
eval('$navbar = "' . fetch_template('navbar') . '";');
eval('print_output("' . fetch_template('installs') . '");');
?>
Is there a way I can change the URL in my CURL code to point directly to that part of the installs.php page?
As for standard HTTP features: no, there is no explicit way of calling parts of a script.
Let's start from the beginning. What we would usually do in this situation is that we set the path in the URL to the file, that contains parts we want to execute. Then, it is up us to decide, how we design our program to know, which part should be executed. We can use POST parameters for that like you were trying. So far, so good.
Now, how do we divide our script, installs.php in your case, into pieces?
One good way is the one RamRaider already mentioned: use a POST parameter action and in installs.php, put code into a big switch. Example:
// installs.php
<?php
switch ($_POST['action']) {
case 'myfirstaction':
if (isset($_POST['username'])) {
$vbulletin->db->query_write("...");
}
break;
case 'myotheraction':
// code here
break;
}
?>
To call specific actions, just extend you $fields array:
<?php
// script that "can be executed from anywhere":
$fields['action'] = 'myfirstaction';
?>
I would say this is the cleanest way to do it in your situation. However, if installs.php is a larger script you are adjusting, this might be way too much work. In that case you may want to exit the script after running your code (thus, running only the code you want). You can simply write exit; and no further code will be executed. See: https://www.php.net/exit.
My script is working most of the times, but in every 8th try or so I get an error. I'll try and explain this. This is the error I get (or similar):
{"gameName":"F1 2011","gameTrailer":"http://cdn.akamai.steamstatic.com/steam/apps/81163/movie_max.webm?t=1447354814","gameId":"44360","finalPrice":1499,"genres":"Racing"}
{"gameName":"Starscape","gameTrailer":"http://cdn.akamai.steamstatic.com/steam/apps/900679/movie_max.webm?t=1447351523","gameId":"20700","finalPrice":999,"genres":"Action"}
Warning: file_get_contents(http://store.steampowered.com/api/appdetails?appids=400160): failed to open stream: HTTP request failed! in C:\xampp\htdocs\GoStrap\game.php on line 19
{"gameName":"DRAGON: A Game About a Dragon","gameTrailer":"http://cdn.akamai.steamstatic.com/steam/apps/2038811/movie_max.webm?t=1447373449","gameId":"351150","finalPrice":599,"genres":"Adventure"}
{"gameName":"Monster Mash","gameTrailer":"http://cdn.akamai.steamstatic.com/steam/apps/900919/movie_max.webm?t=1447352342","gameId":"36210","finalPrice":449,"genres":"Casual"}
I'm making an application that fetches information on a random Steam game from the Steam store. It's quite simple.
The script takes a (somewhat) random ID from a text file (working for sure)
The ID is added to the ending of an URL for the API, and uses file_get_contents to fetch the file. It then decodes json. (might be the problem somehow)
Search for my specified data. Final price & movie webm is not always there, hence the if(!isset())
Decide final price and ship back to ajax on index.php
The error code above suggests that I get the data I need in 4 cases, and an error once. I only wanna receive ONE json string and return it, and only in-case $game['gameTrailer'] and $game['final_price'] is set.
This is the php (it's not great, be kind):
<?php
//Run the script on ajax call
if(isset($_POST)) {
fetchGame();
}
function fetchGame() {
$gameFound = false;
while(!$gameFound) {
////////// ID-picker //////////
$f_contents = file("steam.txt");
$url = $f_contents[mt_rand(0, count($f_contents) - 1)];
$answer = explode('/',$url);
$gameID = $answer[4];
$trimmed = trim($gameID);
////////// Fetch game //////////
$json = file_get_contents('http://store.steampowered.com/api/appdetails?appids='.$trimmed);
$game_json = json_decode($json, true);
if(!isset($game_json[$trimmed]['data']['movies'][0]['webm']['max']) || !isset($game_json[$trimmed]['data']['price_overview']['final'])) {
continue;
}
$gameFound = true;
////////// Store variables //////////
$game['gameName'] = $game_json[$trimmed]['data']['name'];
$game['gameTrailer'] = $game_json[$trimmed]['data']['movies'][0]['webm']['max'];
$game['gameId'] = $trimmed;
$game['free'] = $game_json[$trimmed]['data']['is_free'];
$game['price'] = $game_json[$trimmed]['data']['price_overview']['final'];
$game['genres'] = $game_json[$trimmed]['data']['genres'][0]['description'];
if ($game['free'] == TRUE) {
$game['final_price'] = "Free";
} elseif($game['free'] == FALSE || $game['final_price'] != NULL) {
$game['final_price'] = $game['price'];
} else {
$game['final_price'] = "-";
}
}
////////// Return to AJAX (index.php) //////////
echo
json_encode(array(
'gameName' => $game['gameName'],
'gameTrailer' => $game['gameTrailer'],
'gameId' => $game['gameId'],
'finalPrice' => $game['final_price'],
'genres' => $game['genres'],
))
;
}
?>
Any help will be appreciated. Like, are there obvious reason as to why this is happening? Is there a significantly better way? Why is it re-iterating itself at least 4 times when it seems to have fetched that data I need? Sorry if this post is long, just trying to be detailed with a lacking php/json-vocabulary.
Kind regards, John
EDIT:
Sometimes it returns no error, just multiple objects:
{"gameName":"Prime World: Defenders","gameTrailer":"http://cdn.akamai.steamstatic.com/steam/apps/2028642/movie_max.webm?t=1447357836","gameId":"235360","finalPrice":899,"genres":"Casual"}
{"gameName":"Grand Ages: Rome","gameTrailer":"http://cdn.akamai.steamstatic.com/steam/apps/5190/movie_max.webm?t=1447351683","gameId":"23450","finalPrice":999,"genres":"Simulation"}
I'm making a website in which I'm trying to create a form that will send the user-input to a google spreadsheet in my google docs/drive... I found a Github project that lets people code the php... It includes 2 other php files which are needed for the script. The code is as follows:
My question is, how can I hide my password from this script under $u = / $p = ??
Anyone viewing the code can see my password.. how can I prevent that?
Link to the script's source is : http://www.farinspace.com/saving-form-data-to-google-spreadsheets/
<?php
// Zend library include path
set_include_path(get_include_path() . PATH_SEPARATOR . "$_SERVER[DOCUMENT_ROOT]/ZendGdata-1.8.1/library");
include_once("Google_Spreadsheet.php");
$u = "username#gmail.com";
$p = "password";
$ss = new Google_Spreadsheet($u,$p);
$ss->useSpreadsheet("My Spreadsheet");
$ss->useWorksheet("wks2");
// important:
// adding a leading alpha char prevents errors, there are issues
// when trying to lookup an identifier in a column where the
// value starts with both alpha and numeric characters, using a
// leading alpha character causes the column and its values to be
// seen as a strictly a strings/text
$id = "z" . md5(microtime(true));
$row = array
(
"id" => $id // used for later lookups
, "name" => "John Doe"
, "email" => "john#example.com"
, "comments" => "Hello world"
);
if ($ss->addRow($row)) echo "Form data successfully stored";
else echo "Error, unable to store data";
$row = array
(
"name" => "John Q Doe"
);
if ($ss->updateRow($row,"id=".$id)) echo "Form data successfully updated";
else echo "Error, unable to update spreadsheet data";
?>
You can attempt to hide if from peering eyes using the code below. It would still be discoverable if you tried, but at least it's away from open text view. All it does is add characters to the text and then subtract them before it uses the password.
Run this script using your original password
<?php
$password = "test";
echo "Original Password In Plain Text = $password\n";
$len=strlen($password);
$NewPassword = "";
for( $i = 0; $i <= $len-1; $i++ ) {
$charcode = ord(substr( $password, $i, 1 ));
$NewChar = $charcode+5; $NewLetter = chr($NewChar);
$NewPassword = $NewPassword . $NewLetter;
} echo "Modified Password to Use in Script = $NewPassword\n";
$OrigPassword = "";
for( $i = 0; $i <= $len-1; $i++ ) {
$charcode = ord(substr( $NewPassword, $i, 1 ));
$OrigChar = $charcode-5; $OrigLetter = chr($OrigChar);
$OrigPassword = $OrigPassword . $OrigLetter;
} echo "Convert the Modified back to the Original = $OrigPassword\n";
?>
Add this part to your script with the new password from the above script
$password = "yjxy";
$OrigPassword = "";
for( $i = 0; $i <= $len-1; $i++ ) {
$charcode = ord(substr( $password, $i, 1 ));
$OrigChar = $charcode-5; $OrigLetter = chr($OrigChar);
$OrigPassword = $OrigPassword . $OrigLetter;
} $password = $OrigPassword;
echo "Script thinks this is the password = $password\n";
The best way to hide the password is to save it in external file and then include it in your php script. Your file with this password let's say 'config.php' should be above DOCUMENT_ROOT to make it unaccesible via browser. It's common aproach and for example you can see it in Zend Framework directory structure where only "public" directory is visible for user. The proper CHMOD should be set to this file as well.
Under this link you have ZF directory structure where you can check location of config files.
This question has been asked and answered lots of times here (but not specifically for Google docs). Short answer is that there is nothing you can do.
Longer answer is that you can mitigate the possibility of the credentials being compromised by:
using credentials supplied the user rather than stored in code
using tokens supplied by the user as a means of decrypting credentials stored in your code (but this gets very complicated with lots of users)
storing the credentials in an include file held outside the document root
I have an array with user information and a web service on a site I can query for the status of a user (online/offline). What I would like to do is query the site every x seconds for the status of each user.
There are about 10 users and belwois an example of the array. I can change the array is needed. Only thing I need to enter manually is the username and full name. The "status" I can call from the server.
$users = array
(
"username"=>array("Fullname","Status"),
"johndoe"=>array("John Doe","Online"),
"janedoe"=>array("Jane Doe","Offline")
);
This is an example of the url I can use to query the site (the query returns only the users status (Online or Offline):
http://thesite.com:80/webservice/user/username/
This is the code I can use to get a specific user status:
$url = 'http://thesite.com:80/webservice/user/johndoe/';
$get = fopen($url, "r");
if ($get) {
while (!feof($get)) {
$state = fgets($get, 4096);
}
fclose($get);
}
echo "User johndoe is: ".$status;
// Output: User johndoe is: Online
Now I only need help with iterating through the users and site every x seconds and update the array with each user status in the last array field for the user.
Please note that below I use php and fopen as this is a cross-domain get function and I could not get ajax/jquery to work. I do not have the option to modify the webservice server.
Thanks :)
You need to create a cronjob script that runs every x seconds. That script should be an asynchronous request to this PHP function.
public function updateUsers(){
$users = $_SESSION['users'];
foreach($users as $username=>$data) {
$url = 'http://thesite.com:80/webservice/user/'.$username.'/';
$get = fopen($url, "r");
if ($get) {
while (!feof($get)) {
$status = fgets($get, 4096);
}
fclose($get);
}
$users[$username][] = $status;
}
$_SESSION['users'] = $users;
}
A guide for posting asynchronous requests . http://petewarden.typepad.com/searchbrowser/2008/06/how-to-post-an.html
Hope it helps :)
If your $users array don't changes, you can do this:
foreach($users as $username=>$userdata) {
$url = 'http://thesite.com:80/webservice/user/'.$username.'/';
$get = fopen($url, "r");
if ($get) {
while (!feof($get)) {
$state = fgets($get, 4096);
}
fclose($get);
}
$users[$username][1] = $state;
}
If you can change your $users array to be associative like this:
$users = array(
"username"=>array("fullname"=>"Fullname","status"=>"Status"),
"johndoe"=>array("fullname"=>"John Doe","status"=>"Online"),
"janedoe"=>array("fullname"=>"Jane Doe","status"=>"Offline")
);
That would let you use more key/values and a bit safer.
So in keeping with my last question, I'm working on scraping the friends feed from Twitter. I followed a tutorial to get this script written, pretty much step by step, so I'm not really sure what is wrong with it, and I'm not seeing any error messages. I've never really used cURL before save from the shell, and I'm extremely new to PHP so please bear with me.
<html>
<head>
<title>Twitcap</title>
</head>
<body>
<?php
function twitcap()
{
// Set your username and password
$user = 'osoleve';
$pass = '****';
// Set site in handler for cURL to download
$ch = curl_init("https://twitter.com/statuses/friends_timeline.xml");
// Set cURL's option
curl_setopt($ch,CURLOPT_HEADER,1); // We want to see the header
curl_setopt($ch,CURLOPT_TIMEOUT,30); // Set timeout to 30s
curl_setopt($ch,CURLOPT_USERPWD,$user.':'.$pass); // Set uname/pass
curl_setopt($ch,CURLOPT_RETURNTRANSER,1); // Do not send to screen
// For debugging purposes, comment when finished
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
// Execute the cURL command
$result = curl_exec($ch);
// Remove the header
// We only want everything after <?
$data = strstr($result, '<?');
// Return the data
$xml = new SimpleXMLElement($data);
return $xml;
}
$xml = twitcap();
echo $xml->status[0]->text;
?>
</body>
</html>
Wouldn't you actually need everything after "?>" ?
$data = strstr($result,'?>');
Also, are you using a free web host? I once had an issue where my hosting provider blocked access to Twitter due to people spamming it.
note that if you use strstr the returend string will actually include the needle-string. so you have to strip of the first 2 chars from the string
i would rather recommend a combination of the function substr and strpos!
anways, i think simplexml should be able to handle this header meaning i think this step is not necessary!
furthermore if i open the url i don't see the like header! and if strstr doesnt find the string it returns false, so you dont have any data in your current script
instead of $data = strstr($result, '<?'); try this:
if(strpos('?>',$data) !== false) {
$data = strstr($result, '?>');
} else {
$data = $result;
}