├── .gitignore ├── www ├── images │ ├── Save.png │ ├── 1-ChatterCast-Index.png │ ├── 5-ChatterCast-Success.png │ └── ChatterCast-BackgroundGradient.png ├── index.php ├── include │ ├── header.php │ ├── config.template.php │ ├── footer.php │ ├── inc.php │ ├── GeoloqiAPI.php │ └── Twitter.php ├── oauth.php └── prefs.php └── scripts └── seattle-911.php /.gitignore: -------------------------------------------------------------------------------- 1 | www/include/config.php 2 | 3 | -------------------------------------------------------------------------------- /www/images/Save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaronpk/ChatterCast-Seattle/master/www/images/Save.png -------------------------------------------------------------------------------- /www/images/1-ChatterCast-Index.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaronpk/ChatterCast-Seattle/master/www/images/1-ChatterCast-Index.png -------------------------------------------------------------------------------- /www/images/5-ChatterCast-Success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaronpk/ChatterCast-Seattle/master/www/images/5-ChatterCast-Success.png -------------------------------------------------------------------------------- /www/images/ChatterCast-BackgroundGradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aaronpk/ChatterCast-Seattle/master/www/images/ChatterCast-BackgroundGradient.png -------------------------------------------------------------------------------- /www/index.php: -------------------------------------------------------------------------------- 1 | oauth(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET); 8 | echo '
'; 9 | 10 | include('footer.php'); 11 | 12 | ?> -------------------------------------------------------------------------------- /www/include/header.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /www/include/config.template.php: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /www/include/footer.php: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /www/include/inc.php: -------------------------------------------------------------------------------- 1 | '; 39 | print_r($a); 40 | echo ''; 41 | } 42 | 43 | $geoloqi = new GeoloqiAPI(GEOLOQI_API_KEY, GEOLOQI_API_SECRET); 44 | 45 | if(!array_key_exists('SHELL', $_SERVER)) 46 | session_start(); 47 | 48 | $db = new PDO(PDO_DSN, PDO_USER, PDO_PASS); 49 | 50 | 51 | ?> 52 | -------------------------------------------------------------------------------- /scripts/seattle-911.php: -------------------------------------------------------------------------------- 1 | data; 10 | 11 | foreach($rows as $row) 12 | { 13 | $row_time = $row[10]; 14 | 15 | // Ignore calls older than 2 hours ago (this shouldn't happen once the script starts running regularly) 16 | # if($row_time + 7200 < time()) 17 | # continue; 18 | 19 | $check = $db->prepare('SELECT COUNT(1) AS num FROM seattle_911 WHERE uuid = :u'); 20 | $check->bindParam(':u', $row[1]); 21 | $check->execute(); 22 | $check = $check->fetch(); 23 | if($check['num'] == 0) 24 | { 25 | $insert = $db->prepare('INSERT INTO seattle_911 (uuid, data) VALUES(:u, :d)'); 26 | $insert->bindParam(':u', $row[1]); 27 | $insert->bindParam(':d', json_encode($row)); 28 | $insert->execute(); 29 | 30 | //irc_debug('[ChatterCast] Found new 911 call: ' . $row[9] . ' at ' . $row[8]); 31 | 32 | $query = $db->prepare('SELECT * FROM users WHERE instamapper_key != ""'); 33 | $query->execute(); 34 | foreach($query as $user) 35 | { 36 | $_SESSION['geoloqi_token'] = $user['geoloqi_access']; 37 | $_SESSION['geoloqi_refresh_token'] = $user['geoloqi_refresh']; 38 | 39 | $message = 'ChatterCast: ' . $row[9] . ' at ' . $row[8] . ' ' . date('g:ia', $row_time); 40 | echo 'Setting a geonote for ' . $user['username'] . ': ' . $message . ' expiring at ' . date('c', $row_time + 7200) . "\n"; 41 | 42 | $response = $geoloqi->request('geonote/create', array( 43 | 'text' => $message, 44 | 'latitude' => $row[11], 45 | 'longitude' => $row[12], 46 | 'radius' => 400, 47 | 'date_to' => date('c', $row_time + 7200) 48 | )); 49 | print_r($response); 50 | } 51 | 52 | } 53 | 54 | } 55 | 56 | ?> 57 | -------------------------------------------------------------------------------- /www/oauth.php: -------------------------------------------------------------------------------- 1 | oauth(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET); 7 | $_SESSION['access_token'] = $token['access_token']; 8 | $_SESSION['access_token_secret'] = $token['access_token_secret']; 9 | 10 | #$connection->oauth(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET, $token['access_token'], $token['access_token_secret']); 11 | 12 | $obj = $twitter->call('account/verify_credentials'); 13 | 14 | $_SESSION['username'] = $obj->screen_name; 15 | 16 | 17 | $query = $db->prepare('SELECT COUNT(1) AS num FROM users WHERE username = :username'); 18 | $query->bindParam(':username', $_SESSION['username'], PDO::PARAM_STR); 19 | $query->execute(); 20 | $row = $query->fetch(); 21 | 22 | if($row['num'] == 0) 23 | { 24 | // new user! insert a row 25 | $geoloqi_response = $geoloqi->request('user/create', array('username' => 'chattercast_' . $_SESSION['username'], 'email' => 'chattercast.' . $_SESSION['username'] . '@pin13.net')); 26 | 27 | $query = $db->prepare('INSERT INTO users (username, twitter_token, twitter_secret, date_created, geoloqi_access, geoloqi_refresh) VALUES(:u, :t, :s, :d, :ga, :gr)'); 28 | $query->bindParam(':u', $_SESSION['username'], PDO::PARAM_STR); 29 | $query->bindParam(':t', $_SESSION['access_token'], PDO::PARAM_STR); 30 | $query->bindParam(':s', $_SESSION['access_token_secret'], PDO::PARAM_STR); 31 | $query->bindParam(':d', date('Y-m-d H:i:s'), PDO::PARAM_STR); 32 | $query->bindParam(':ga', $geoloqi_response->access_token, PDO::PARAM_STR); 33 | $query->bindParam(':gr', $geoloqi_response->refresh_token, PDO::PARAM_STR); 34 | $query->execute(); 35 | 36 | irc('New ChatterCast user! ' . $_SESSION['username']); 37 | } 38 | else 39 | { 40 | $user = $db->prepare('SELECT * FROM users WHERE username = :username'); 41 | $user->bindParam(':username', $_SESSION['username']); 42 | $user->execute(); 43 | $user = $user->fetch(); 44 | irc('ChatterCast user ' . $_SESSION['username'] . ' logged back in'); 45 | $_SESSION['geoloqi_token'] = $user['geoloqi_access']; 46 | } 47 | 48 | header('Location: /prefs.php'); 49 | 50 | ?> -------------------------------------------------------------------------------- /www/prefs.php: -------------------------------------------------------------------------------- 1 | prepare('SELECT * FROM users WHERE username = :username'); 9 | $query->bindParam(':username', $_SESSION['username'], PDO::PARAM_STR); 10 | $query->execute(); 11 | $user = $query->fetch(); 12 | 13 | if(strtolower($_SERVER['REQUEST_METHOD']) == 'get') 14 | { 15 | ?> 16 |
17 | 18 |
Need help? Get your Instamapper API key
19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
Phone Number
Email
Instamapper API Key (20 digits)
39 |
40 |
41 | 42 | 43 |
44 | 45 |
46 | 47 | 60 | 61 | prepare('UPDATE users SET email = :email, phone = :phone, instamapper_key = :instamapper_key WHERE username = :username'); 66 | foreach(array('phone', 'email', 'instamapper_key') as $p) 67 | $query->bindParam(':' . $p, $_POST[$p], PDO::PARAM_STR); 68 | $query->bindParam(':username', $_SESSION['username'], PDO::PARAM_STR); 69 | $query->execute(); 70 | 71 | $user = $db->prepare('SELECT * FROM users WHERE username = :username'); 72 | $user->bindParam(':username', $_SESSION['username']); 73 | $user->execute(); 74 | $user = $user->fetch(); 75 | $_SESSION['geoloqi_token'] = $user['geoloqi_access']; 76 | 77 | $geoloqi_response = $geoloqi->request('account/set_phone', array('phone' => $_POST['phone'])); 78 | 79 | irc('[ChatterCast] ' . $_SESSION['username'] . ' Instamapper Key: ' . $_POST['instamapper_key'] . ' Phone: ' . $_POST['phone'] . ' Email: ' . $_POST['email']); 80 | 81 | echo '
'; 82 | } 83 | 84 | include('footer.php'); 85 | ?> -------------------------------------------------------------------------------- /www/include/GeoloqiAPI.php: -------------------------------------------------------------------------------- 1 | _clientID = $clientID; 12 | $this->_clientSecret = $clientSecret; 13 | 14 | if($baseURL) 15 | $this->_baseURL = $baseURL; 16 | else 17 | $this->_baseURL = GEOLOQI_API_BASEURL; 18 | 19 | if($baseURLSecure) 20 | $this->_baseURLSecure = $baseURLSecure; 21 | else 22 | $this->_baseURLSecure = GEOLOQI_API_BASEURL_SECURE; 23 | 24 | } 25 | 26 | public function request($method, $post=FALSE) 27 | { 28 | ob_start(); 29 | echo '
';
 30 | 		
 31 | 		$ch = curl_init();
 32 | 		
 33 | 		$httpHeader = array();
 34 | 
 35 | 		// TODO: Change this timezone to the logged-in user's timezone
 36 | 		$httpHeader[] = 'Timezone: ' . date('c') . ';;America/Los_Angeles';
 37 | 		
 38 | 		if(substr($method, 0, 5) == 'oauth' || substr($method, 0, 4) == 'user')
 39 | 		{
 40 | 			$client = array('client_id' => $this->_clientID, 'client_secret' => $this->_clientSecret);
 41 | 			curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
 42 | 			curl_setopt($ch, CURLOPT_USERPWD, implode(':', $client));
 43 | 			$baseURL = $this->_baseURL;
 44 | 		}
 45 | 		else
 46 | 		{
 47 | 			// Pass the OAuth token in the HTTP headers
 48 | 			$httpHeader[] = 'Authorization: OAuth ' . $_SESSION['geoloqi_token'];
 49 | 			
 50 | 			$baseURL = $this->_baseURLSecure;
 51 | 		}
 52 | 		
 53 | 		curl_setopt($ch, CURLOPT_URL, $baseURL . $method);
 54 | 	
 55 | 		if(is_array($post))
 56 | 		{
 57 | 			$post = http_build_query($post, '', '&');
 58 | 			curl_setopt($ch, CURLOPT_POST, TRUE);
 59 | 			curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
 60 | 		}
 61 | 		elseif(is_string($post))
 62 | 		{
 63 | 			$httpHeader[] = 'Content-Type: application/json';
 64 | 			curl_setopt($ch, CURLOPT_POST, TRUE);
 65 | 			curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
 66 | 		}
 67 | 
 68 | 		curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeader);
 69 | 		curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
 70 | 		curl_setopt($ch, CURLOPT_HEADER, TRUE);
 71 | 		curl_setopt($ch, CURLINFO_HEADER_OUT, TRUE);
 72 | 		
 73 | 		$response = curl_exec($ch);
 74 | 	
 75 | 		echo '
'; 76 | echo "REQUEST HEADERS:\n"; 77 | echo trim(curl_getinfo($ch, CURLINFO_HEADER_OUT)) . "\n\n"; 78 | if($post) 79 | { 80 | echo "REQUEST BODY:\n"; 81 | echo (is_array($post) ? http_build_query($post) : $post) . "\n\n"; 82 | } 83 | echo '
'; 84 | 85 | echo "RESPONSE HEADERS:\n"; 86 | echo $response . "\n\n"; 87 | 88 | $headers = array(); 89 | $lines = explode("\n", $response); 90 | $endHeaders = FALSE; 91 | while($endHeaders == FALSE && count($lines) > 0) 92 | { 93 | $line = array_shift($lines); 94 | if(substr($line, 0, 1) == '{' || substr($line, 0, 1) == '[') 95 | { 96 | $endHeaders = TRUE; 97 | array_unshift($lines, $line); 98 | } 99 | else 100 | { 101 | $line = explode(': ', $line); 102 | if(count($line) == 2) 103 | { 104 | list($k, $v) = $line; 105 | $headers[trim($k)] = trim($v); 106 | } 107 | } 108 | } 109 | 110 | $body = implode("\n", $lines); 111 | 112 | $data = json_decode($body); 113 | 114 | echo "JSON RESPONSE:\n"; 115 | 116 | if(is_object($data) && property_exists($data, 'debug_output')) 117 | { 118 | echo '
' . $data->debug_output . '
'; 119 | unset($data->debug_output); 120 | } 121 | pa($data); 122 | 123 | if(array_key_exists('WWW-Authenticate', $headers) && preg_match('/error=\'expired_token\'/', $headers['WWW-Authenticate'])) 124 | { 125 | // If the token expired, use the refresh token to get a new access token 126 | $response = $this->request('oauth/token', array( 127 | 'grant_type' => 'refresh_token', 128 | 'refresh_token' => $_SESSION['geoloqi_refresh_token'] 129 | )); 130 | 131 | // Store the tokens in the session 132 | $_SESSION['geoloqi_token'] = $response->access_token; 133 | $_SESSION['geoloqi_refresh_token'] = $response->refresh_token; 134 | 135 | echo "SESSION\n"; 136 | pa($_SESSION); 137 | 138 | // Try the original request again 139 | // return $this->request($method, $post); 140 | die('ERROR'); 141 | return FALSE; 142 | } 143 | 144 | echo "\n"; 145 | 146 | echo '
'; 147 | $this->log(ob_get_clean()); 148 | 149 | return $data; 150 | } 151 | 152 | protected function log($msg) 153 | { 154 | static $fp = FALSE; 155 | if($fp == FALSE) 156 | $fp = fopen('api-log.htm', 'w'); 157 | fwrite($fp, $msg . "\n"); 158 | } 159 | } 160 | ?> -------------------------------------------------------------------------------- /www/include/Twitter.php: -------------------------------------------------------------------------------- 1 | array('http' => 'get', 'auth' => FALSE), 17 | 'statuses/friends_timeline' => array('http' => 'get', 'auth' => TRUE), 18 | 'statuses/user_timeline' => array('http' => 'get', 'auth' => FALSE), 19 | 'statuses/mentions' => array('http' => 'get', 'auth' => TRUE), 20 | 'statuses/show' => array('http' => 'get', 'auth' => FALSE), 21 | 'statuses/update' => array('http' => 'post', 'auth' => TRUE), 22 | 'statuses/destroy' => array('http' => 'post', 'auth' => TRUE), 23 | 'users/show' => array('http' => 'get', 'auth' => FALSE), 24 | 'statuses/friends' => array('http' => 'get', 'auth' => FALSE), 25 | 'statuses/followers' => array('http' => 'get', 'auth' => TRUE), 26 | 'direct_messages' => array('http' => 'get', 'auth' => TRUE), 27 | 'direct_messages/sent' => array('http' => 'get', 'auth' => TRUE), 28 | 'direct_messages/new' => array('http' => 'post', 'auth' => TRUE), 29 | 'direct_messages/destroy' => array('http' => 'post', 'auth' => TRUE), 30 | 'friendships/create' => array('http' => 'post', 'auth' => TRUE), 31 | 'friendships/destroy' => array('http' => 'post', 'auth' => TRUE), 32 | 'friendships/exists' => array('http' => 'get', 'auth' => TRUE), 33 | 'account/verify_credentials' => array('http' => 'get', 'auth' => TRUE), 34 | 'account/rate_limit_status' => array('http' => 'get', 'auth' => FALSE), 35 | 'account/end_session' => array('http' => 'post', 'auth' => TRUE), 36 | 'account/update_delivery_device'=> array('http' => 'post', 'auth' => TRUE), 37 | 'account/update_profile_colors' => array('http' => 'post', 'auth' => TRUE), 38 | 'account/update_profile' => array('http' => 'post', 'auth' => TRUE), 39 | 'favorites' => array('http' => 'get', 'auth' => TRUE), 40 | 'favorites/create' => array('http' => 'post', 'auth' => TRUE), 41 | 'notifications/follow' => array('http' => 'post', 'auth' => TRUE), 42 | 'notifications/leave' => array('http' => 'post', 'auth' => TRUE), 43 | 'blocks/create' => array('http' => 'post', 'auth' => TRUE), 44 | 'blocks/destroy' => array('http' => 'post', 'auth' => TRUE), 45 | 'help/test' => array('http' => 'get', 'auth' => FALSE) 46 | 47 | //'account/update_profile_image' => array('http' => 'post', 'auth' => TRUE), 48 | //'account/account/update_profile_background_image' => array('http' => 'post', 'auth' => TRUE), 49 | 50 | ); 51 | 52 | private $_conn; 53 | public $oauth; 54 | 55 | function __construct() 56 | { 57 | $this->_conn = new Twitter_Connection(); 58 | } 59 | 60 | public function auth($username, $password) 61 | { 62 | $this->deauth(); 63 | $this->_conn->auth($username, $password); 64 | } 65 | 66 | public function oauth($consumer_key, $consumer_secret, $access_token = NULL, $access_token_secret = NULL) 67 | { 68 | $this->deauth(); 69 | $this->oauth = new EpiTwitter($consumer_key, $consumer_secret, $access_token, $access_token_secret); 70 | $this->oauth->setToken($access_token, $access_token_secret); 71 | 72 | if ( $access_token === NULL && $access_token_secret === NULL && !isset($_GET['oauth_token']) ) 73 | { 74 | // Authenticate URL will seamlessly send the user back if the app is already approved 75 | //$url = $this->oauth->getAuthenticateUrl(); 76 | // Authorize URL makes the user approve the app every time 77 | $url = $this->oauth->getAuthorizeUrl(); 78 | 79 | return $url; 80 | } 81 | elseif ( $access_token === NULL && $access_token_secret === NULL && isset($_GET['oauth_token']) ) 82 | { 83 | $access_token = $_GET['oauth_token']; 84 | $this->oauth->setToken($access_token); 85 | 86 | $info = $this->oauth->getAccessToken(); 87 | 88 | if($info->oauth_token && $info->oauth_token_secret) 89 | { 90 | $response = array( 91 | 'access_token' => $info->oauth_token, 92 | 'access_token_secret' => $info->oauth_token_secret 93 | ); 94 | $this->oauth->setToken($response['access_token'], $response['access_token_secret']); 95 | 96 | return $response; 97 | } 98 | } 99 | 100 | return TRUE; 101 | } 102 | 103 | public function deauth() 104 | { 105 | $this->oauth = NULL; 106 | $this->_conn->deauth(); 107 | } 108 | 109 | public function search($method, $params = array()) 110 | { 111 | $url = $this->_url_api_search.$method.'.'.$this->_api_format; 112 | 113 | return $this->_conn->get($url, $params); 114 | } 115 | 116 | public function call($method, $params = array()) 117 | { 118 | // Firstly, assume we are using a GET non-authenticated call. 119 | 120 | $http = 'get'; 121 | $auth = FALSE; 122 | 123 | // Now we get our http and auth options from the methods array. 124 | 125 | if ( isset($this->_methods[$method]) ) 126 | { 127 | $http = $this->_methods[$method]['http']; 128 | $auth = $this->_methods[$method]['auth']; 129 | } 130 | 131 | if ( $auth === TRUE && ( $this->_conn->authed() || $this->oauth === NULL) ) 132 | { 133 | // method requires auth, and we have not authed yet. 134 | return NULL; 135 | } 136 | 137 | if ( $this->oauth !== NULL ) 138 | { 139 | $parts = explode('/', $method); 140 | 141 | if ( count($parts) > 1 ) 142 | { 143 | $method_string = $http.'_'.$parts[0].ucfirst($parts[1]); 144 | } 145 | else 146 | { 147 | $method_string = $http.'_'.$parts[0]; 148 | } 149 | 150 | $data = $this->oauth->$method_string($params); 151 | return $data; 152 | } 153 | 154 | $url = $this->_url_api . $method . '.' .$this->_api_format; 155 | 156 | return $this->_conn->$http($url, $params); 157 | } 158 | } 159 | 160 | class Twitter_Connection { 161 | 162 | private $_curl = NULL; 163 | private $_auth_method = NULL; 164 | private $_auth_user = NULL; 165 | private $_auth_pass = NULL; 166 | 167 | function __construct() 168 | { 169 | } 170 | 171 | private function _init() 172 | { 173 | $this->_curl = curl_init(); 174 | 175 | curl_setopt($this->_curl, CURLOPT_RETURNTRANSFER, TRUE); 176 | 177 | if ( $this->_auth_method == 'basic' ) 178 | { 179 | curl_setopt($this->_curl, CURLOPT_USERPWD, "$this->_auth_user:$this->_auth_pass"); 180 | } 181 | } 182 | 183 | public function authed() 184 | { 185 | if ( $this->_auth_method === NULL ) return FALSE; 186 | 187 | return TRUE; 188 | } 189 | 190 | public function auth($username, $password) 191 | { 192 | $this->deauth(); 193 | 194 | $this->_auth_method = 'basic'; 195 | $this->_auth_user = $username; 196 | $this->_auth_pass = $password; 197 | } 198 | 199 | public function deauth($auth_method = NULL) 200 | { 201 | if ( $auth_method == 'basic' || NULL ) 202 | { 203 | $this->_auth_user = NULL; 204 | $this->_auth_pass = NULL; 205 | } 206 | 207 | $this->_auth_method = NULL; 208 | } 209 | 210 | public function get($url, $params = array()) 211 | { 212 | $this->_init(); 213 | 214 | if ( is_array($params) && !empty($params) ) 215 | { 216 | $url = $url . '?' . $this->_params_to_query($params); 217 | } 218 | 219 | curl_setopt($this->_curl, CURLOPT_URL, $url); 220 | 221 | return $this->deserialize(curl_exec($this->_curl)); 222 | } 223 | 224 | public function post($url, $params = array()) 225 | { 226 | $this->_init(); 227 | 228 | if ( is_array($params) && !empty($params) ) 229 | { 230 | curl_setopt($this->_curl, CURLOPT_POSTFIELDS, $this->_params_to_query($params)); 231 | } 232 | 233 | curl_setopt($this->_curl, CURLOPT_POST, TRUE); 234 | curl_setopt($this->_curl, CURLOPT_URL, $url); 235 | 236 | return $this->deserialize(curl_exec($this->_curl)); 237 | } 238 | 239 | private function _params_to_query($params) 240 | { 241 | if ( !is_array($params) || empty($params) ) 242 | { 243 | return ''; 244 | } 245 | 246 | $query = ''; 247 | 248 | foreach ( $params as $key => $value ) 249 | { 250 | $query .= $key . '=' . $value . '&'; 251 | } 252 | 253 | return substr($query, 0, strlen($query) - 1);; 254 | } 255 | 256 | private function deserialize($result) 257 | { 258 | return json_decode($result); 259 | } 260 | } 261 | 262 | ?> --------------------------------------------------------------------------------