├── LICENSE
├── README.md
├── config.php
├── twitteroauth
├── LICENSE.md
├── README.md
├── autoload.php
├── composer.json
└── src
│ ├── Config.php
│ ├── Consumer.php
│ ├── HmacSha1.php
│ ├── Request.php
│ ├── Response.php
│ ├── SignatureMethod.php
│ ├── Token.php
│ ├── TwitterOAuth.php
│ ├── TwitterOAuthException.php
│ ├── Util.php
│ ├── Util
│ └── JsonDecoder.php
│ └── cacert.pem
└── urtb.php
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Spencer Lowe
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # UptimeRobot Twitter Bot
2 | I created this tool to post UptimeRobot alerts to twitter. Everything is customizable
3 | 
4 |
5 |
6 |
7 | [Live Example](https://twitter.com/NerdBaggyTest)
8 |
9 |
10 | ## Install
11 | - [Download Latest Release Here](https://github.com/nerdbaggy/uptimerobot-twitter-bot/releases/latest)
12 | - Unzip and upload to a web accessible folder
13 | - Add a new alert in UptimeRobot in the 'Web-Hook' category
14 | For example if your script is at spencerl.com/twitterbot/urtb.php the ***URL to Notify*** will be spencerl.com/twitterbot/urtb.php?
15 | - Configure twitter. See below
16 |
17 | ## Twitter
18 | You need to make 4 keys from twitter to get this working.
19 | [Click Here for Directions](https://themepacific.com/how-to-generate-api-key-consumer-token-access-key-for-twitter-oauth/994/)
20 | Once you have the 4 keys put them in the ***config.php***
21 |
22 | ## Message
23 | You can customize how the messages look when posting to Twitter. You can customize it to however you would like. Just needs to be below 140 chacters. But it can inculde emoji, ascii, links, hashtags, anything! You can customize the message with the variables below.
24 |
25 | ### Example
26 |
27 | ```
28 | ✔ {{host}} is now now up after {{downtime}} [{{timestamp}} {{timezone}}]
29 | ✖ {{host}} has gone down [{{timestamp}} {{timezone}}]
30 | ```
31 |
32 | | Variable | Example | Description |
33 | | ------------- | ------------- | ------------- |
34 | | {{host}} | Website | Name of the check |
35 | | {{id}} | 59426326 | ID of the check|
36 | | {{status}} | Up | Status of the check|
37 | | {{url}} | spencerl.com | Host of the check|
38 | | {{details}} | Timeout | Why the check failed|
39 | | {{downtime}} | 4 Minutes | How long a check was down for|
40 | | {{timestamp}} | 05:24 PM | Current time|
41 | | {{timezone}} | UTC | Timezone to get timestamp|
42 |
--------------------------------------------------------------------------------
/config.php:
--------------------------------------------------------------------------------
1 | '',
4 | 'consumerSecret' => '',
5 | 'accessToken' => '',
6 | 'accessTokenSecret' => '',
7 | );
8 |
9 | // You need to keep the timestamp in or Twitter will block messages
10 | $messages = array(
11 | // Message to send once a check has come back online
12 | "upMessage" => "✔ {{host}} is now now up after {{downtime}} [{{timestamp}} {{timezone}}]",
13 |
14 | // Message to send if a check comes back online but never got a down notification
15 | "upMessageNoDown" => "✔ {{host}} is now now up [{{timestamp}} {{timezone}}]",
16 |
17 | // Message to send when a check has gone down
18 | "downMessage" => "✖ {{host}} has gone down [{{timestamp}} {{timezone}}]",
19 | );
20 |
21 | // Timestamp to display in the twitter message
22 | // You can format it here: http://php.net/manual/en/function.date.php
23 | $timestampFormat = 'h:i A';
24 |
25 | // Timezone to display alerts in
26 | // http://php.net/manual/en/timezones.php
27 | $timezone = 'UTC';
28 |
29 | // Name of the cache file
30 | $cacheFile = 'twitterbot.cache';
31 |
32 | // What useragent must be present in the request
33 | $userAgentVerify = 'UptimeRobot';
34 |
35 | // IPs to allow requests to come from.
36 | // These are the engine IPs from https://uptimerobot.com/locations
37 | $uptimeRobotIps = array(
38 | "69.162.124.226",
39 | "69.162.124.227",
40 | "69.162.124.228",
41 | "69.162.124.229",
42 | "69.162.124.230",
43 | "69.162.124.231",
44 | "69.162.124.232",
45 | "69.162.124.233",
46 | "69.162.124.234",
47 | "69.162.124.235",
48 | "69.162.124.236",
49 | "69.162.124.237",
50 | "69.162.124.238"
51 | );
52 |
53 | // Allows requests to come from non approved sources
54 | // Don't use in production!!!!!!!!
55 | $debug = false;
56 |
--------------------------------------------------------------------------------
/twitteroauth/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009 Abraham Williams - http://abrah.am - abraham@abrah.am
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated documentation
5 | files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following
10 | conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/twitteroauth/README.md:
--------------------------------------------------------------------------------
1 | TwitterOAuth [](https://travis-ci.org/abraham/twitteroauth) [](https://scrutinizer-ci.com/g/abraham/twitteroauth/?branch=master) [](https://github.com/abraham/twitteroauth/issues) [](https://packagist.org/packages/abraham/twitteroauth)
2 | ------------
3 |
4 |
The most popular PHP library for Twitter's OAuth REST API.
5 |
6 | See documentation at https://twitteroauth.com.
7 |
8 | OAuth signing code originally sourced from [here](https://code.google.com/p/oauth/).
9 |
10 |
11 |
--------------------------------------------------------------------------------
/twitteroauth/autoload.php:
--------------------------------------------------------------------------------
1 | =5.5.0",
22 | "ext-curl": "*"
23 | },
24 | "require-dev": {
25 | "phpunit/phpunit": "4.7.*",
26 | "squizlabs/php_codesniffer": "2.3.*",
27 | "phpmd/phpmd": "2.2.*"
28 | },
29 | "autoload": {
30 | "psr-4": {
31 | "Abraham\\TwitterOAuth\\": "src"
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/twitteroauth/src/Config.php:
--------------------------------------------------------------------------------
1 |
9 | */
10 | class Config
11 | {
12 | /** @var int How long to wait for a response from the API */
13 | protected $timeout = 5;
14 | /** @var int how long to wait while connecting to the API */
15 | protected $connectionTimeout = 5;
16 | /**
17 | * Decode JSON Response as associative Array
18 | *
19 | * @see http://php.net/manual/en/function.json-decode.php
20 | *
21 | * @var bool
22 | */
23 | protected $decodeJsonAsArray = false;
24 | /** @var string User-Agent header */
25 | protected $userAgent = 'TwitterOAuth (+https://twitteroauth.com)';
26 | /** @var array Store proxy connection details */
27 | protected $proxy = [];
28 |
29 | /**
30 | * Set the connection and response timeouts.
31 | *
32 | * @param int $connectionTimeout
33 | * @param int $timeout
34 | */
35 | public function setTimeouts($connectionTimeout, $timeout)
36 | {
37 | $this->connectionTimeout = (int)$connectionTimeout;
38 | $this->timeout = (int)$timeout;
39 | }
40 |
41 | /**
42 | * @param bool $value
43 | */
44 | public function setDecodeJsonAsArray($value)
45 | {
46 | $this->decodeJsonAsArray = (bool)$value;
47 | }
48 |
49 | /**
50 | * @param string $userAgent
51 | */
52 | public function setUserAgent($userAgent)
53 | {
54 | $this->userAgent = (string)$userAgent;
55 | }
56 |
57 | /**
58 | * @param array $proxy
59 | */
60 | public function setProxy(array $proxy)
61 | {
62 | $this->proxy = $proxy;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/twitteroauth/src/Consumer.php:
--------------------------------------------------------------------------------
1 | key = $key;
25 | $this->secret = $secret;
26 | $this->callbackUrl = $callbackUrl;
27 | }
28 |
29 | /**
30 | * @return string
31 | */
32 | public function __toString()
33 | {
34 | return "Consumer[key=$this->key,secret=$this->secret]";
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/twitteroauth/src/HmacSha1.php:
--------------------------------------------------------------------------------
1 | getSignatureBaseString();
31 |
32 | $parts = [$consumer->secret, null !== $token ? $token->secret : ""];
33 |
34 | $parts = Util::urlencodeRfc3986($parts);
35 | $key = implode('&', $parts);
36 |
37 | return base64_encode(hash_hmac('sha1', $signatureBase, $key, true));
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/twitteroauth/src/Request.php:
--------------------------------------------------------------------------------
1 | parameters = $parameters;
26 | $this->httpMethod = $httpMethod;
27 | $this->httpUrl = $httpUrl;
28 | }
29 |
30 | /**
31 | * pretty much a helper function to set up the request
32 | *
33 | * @param Consumer $consumer
34 | * @param Token $token
35 | * @param string $httpMethod
36 | * @param string $httpUrl
37 | * @param array $parameters
38 | *
39 | * @return Request
40 | */
41 | public static function fromConsumerAndToken(
42 | Consumer $consumer,
43 | Token $token = null,
44 | $httpMethod,
45 | $httpUrl,
46 | array $parameters = []
47 | ) {
48 | $defaults = [
49 | "oauth_version" => Request::$version,
50 | "oauth_nonce" => Request::generateNonce(),
51 | "oauth_timestamp" => time(),
52 | "oauth_consumer_key" => $consumer->key
53 | ];
54 | if (null !== $token) {
55 | $defaults['oauth_token'] = $token->key;
56 | }
57 |
58 | $parameters = array_merge($defaults, $parameters);
59 |
60 | return new Request($httpMethod, $httpUrl, $parameters);
61 | }
62 |
63 | /**
64 | * @param string $name
65 | * @param string $value
66 | */
67 | public function setParameter($name, $value)
68 | {
69 | $this->parameters[$name] = $value;
70 | }
71 |
72 | /**
73 | * @param $name
74 | *
75 | * @return string|null
76 | */
77 | public function getParameter($name)
78 | {
79 | return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
80 | }
81 |
82 | /**
83 | * @return array
84 | */
85 | public function getParameters()
86 | {
87 | return $this->parameters;
88 | }
89 |
90 | /**
91 | * @param $name
92 | */
93 | public function removeParameter($name)
94 | {
95 | unset($this->parameters[$name]);
96 | }
97 |
98 | /**
99 | * The request parameters, sorted and concatenated into a normalized string.
100 | *
101 | * @return string
102 | */
103 | public function getSignableParameters()
104 | {
105 | // Grab all parameters
106 | $params = $this->parameters;
107 |
108 | // Remove oauth_signature if present
109 | // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.")
110 | if (isset($params['oauth_signature'])) {
111 | unset($params['oauth_signature']);
112 | }
113 |
114 | return Util::buildHttpQuery($params);
115 | }
116 |
117 | /**
118 | * Returns the base string of this request
119 | *
120 | * The base string defined as the method, the url
121 | * and the parameters (normalized), each urlencoded
122 | * and the concated with &.
123 | *
124 | * @return string
125 | */
126 | public function getSignatureBaseString()
127 | {
128 | $parts = [
129 | $this->getNormalizedHttpMethod(),
130 | $this->getNormalizedHttpUrl(),
131 | $this->getSignableParameters()
132 | ];
133 |
134 | $parts = Util::urlencodeRfc3986($parts);
135 |
136 | return implode('&', $parts);
137 | }
138 |
139 | /**
140 | * Returns the HTTP Method in uppercase
141 | *
142 | * @return string
143 | */
144 | public function getNormalizedHttpMethod()
145 | {
146 | return strtoupper($this->httpMethod);
147 | }
148 |
149 | /**
150 | * parses the url and rebuilds it to be
151 | * scheme://host/path
152 | *
153 | * @return string
154 | */
155 | public function getNormalizedHttpUrl()
156 | {
157 | $parts = parse_url($this->httpUrl);
158 |
159 | $scheme = $parts['scheme'];
160 | $host = strtolower($parts['host']);
161 | $path = $parts['path'];
162 |
163 | return "$scheme://$host$path";
164 | }
165 |
166 | /**
167 | * Builds a url usable for a GET request
168 | *
169 | * @return string
170 | */
171 | public function toUrl()
172 | {
173 | $postData = $this->toPostdata();
174 | $out = $this->getNormalizedHttpUrl();
175 | if ($postData) {
176 | $out .= '?' . $postData;
177 | }
178 | return $out;
179 | }
180 |
181 | /**
182 | * Builds the data one would send in a POST request
183 | *
184 | * @return string
185 | */
186 | public function toPostdata()
187 | {
188 | return Util::buildHttpQuery($this->parameters);
189 | }
190 |
191 | /**
192 | * Builds the Authorization: header
193 | *
194 | * @return string
195 | * @throws TwitterOAuthException
196 | */
197 | public function toHeader()
198 | {
199 | $first = true;
200 | $out = 'Authorization: OAuth';
201 | foreach ($this->parameters as $k => $v) {
202 | if (substr($k, 0, 5) != "oauth") {
203 | continue;
204 | }
205 | if (is_array($v)) {
206 | throw new TwitterOAuthException('Arrays not supported in headers');
207 | }
208 | $out .= ($first) ? ' ' : ', ';
209 | $out .= Util::urlencodeRfc3986($k) . '="' . Util::urlencodeRfc3986($v) . '"';
210 | $first = false;
211 | }
212 | return $out;
213 | }
214 |
215 | /**
216 | * @return string
217 | */
218 | public function __toString()
219 | {
220 | return $this->toUrl();
221 | }
222 |
223 | /**
224 | * @param SignatureMethod $signatureMethod
225 | * @param Consumer $consumer
226 | * @param Token $token
227 | */
228 | public function signRequest(SignatureMethod $signatureMethod, Consumer $consumer, Token $token = null)
229 | {
230 | $this->setParameter("oauth_signature_method", $signatureMethod->getName());
231 | $signature = $this->buildSignature($signatureMethod, $consumer, $token);
232 | $this->setParameter("oauth_signature", $signature);
233 | }
234 |
235 | /**
236 | * @param SignatureMethod $signatureMethod
237 | * @param Consumer $consumer
238 | * @param Token $token
239 | *
240 | * @return string
241 | */
242 | public function buildSignature(SignatureMethod $signatureMethod, Consumer $consumer, Token $token = null)
243 | {
244 | return $signatureMethod->buildSignature($this, $consumer, $token);
245 | }
246 |
247 | /**
248 | * @return string
249 | */
250 | public static function generateNonce()
251 | {
252 | return md5(microtime() . mt_rand());
253 | }
254 | }
255 |
--------------------------------------------------------------------------------
/twitteroauth/src/Response.php:
--------------------------------------------------------------------------------
1 |
9 | */
10 | class Response
11 | {
12 | /** @var string|null API path from the most recent request */
13 | private $apiPath;
14 | /** @var int HTTP status code from the most recent request */
15 | private $httpCode = 0;
16 | /** @var array HTTP headers from the most recent request */
17 | private $headers = [];
18 | /** @var array|object Response body from the most recent request */
19 | private $body = [];
20 | /** @var array HTTP headers from the most recent request that start with X */
21 | private $xHeaders = [];
22 |
23 | /**
24 | * @param string $apiPath
25 | */
26 | public function setApiPath($apiPath)
27 | {
28 | $this->apiPath = $apiPath;
29 | }
30 |
31 | /**
32 | * @return string|null
33 | */
34 | public function getApiPath()
35 | {
36 | return $this->apiPath;
37 | }
38 |
39 | /**
40 | * @param array|object $body
41 | */
42 | public function setBody($body)
43 | {
44 | $this->body = $body;
45 | }
46 |
47 | /**
48 | * @return array|object|string
49 | */
50 | public function getBody()
51 | {
52 | return $this->body;
53 | }
54 |
55 | /**
56 | * @param int $httpCode
57 | */
58 | public function setHttpCode($httpCode)
59 | {
60 | $this->httpCode = $httpCode;
61 | }
62 |
63 | /**
64 | * @return int
65 | */
66 | public function getHttpCode()
67 | {
68 | return $this->httpCode;
69 | }
70 |
71 | /**
72 | * @param array $headers
73 | */
74 | public function setHeaders($headers)
75 | {
76 | foreach ($headers as $key => $value) {
77 | if (substr($key, 0, 1) == 'x') {
78 | $this->xHeaders[$key] = $value;
79 | }
80 | }
81 | $this->headers = $headers;
82 | }
83 |
84 | /**
85 | * @return array
86 | */
87 | public function getsHeaders()
88 | {
89 | return $this->headers;
90 | }
91 |
92 | /**
93 | * @param array $xHeaders
94 | */
95 | public function setXHeaders($xHeaders)
96 | {
97 | $this->xHeaders = $xHeaders;
98 | }
99 |
100 | /**
101 | * @return array
102 | */
103 | public function getXHeaders()
104 | {
105 | return $this->xHeaders;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/twitteroauth/src/SignatureMethod.php:
--------------------------------------------------------------------------------
1 | buildSignature($request, $consumer, $token);
48 |
49 | // Check for zero length, although unlikely here
50 | if (strlen($built) == 0 || strlen($signature) == 0) {
51 | return false;
52 | }
53 |
54 | if (strlen($built) != strlen($signature)) {
55 | return false;
56 | }
57 |
58 | // Avoid a timing leak with a (hopefully) time insensitive compare
59 | $result = 0;
60 | for ($i = 0; $i < strlen($signature); $i++) {
61 | $result |= ord($built{$i}) ^ ord($signature{$i});
62 | }
63 |
64 | return $result == 0;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/twitteroauth/src/Token.php:
--------------------------------------------------------------------------------
1 | key = $key;
22 | $this->secret = $secret;
23 | }
24 |
25 | /**
26 | * Generates the basic string serialization of a token that a server
27 | * would respond to request_token and access_token calls with
28 | *
29 | * @return string
30 | */
31 | public function __toString()
32 | {
33 | return sprintf("oauth_token=%s&oauth_token_secret=%s",
34 | Util::urlencodeRfc3986($this->key),
35 | Util::urlencodeRfc3986($this->secret)
36 | );
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/twitteroauth/src/TwitterOAuth.php:
--------------------------------------------------------------------------------
1 |
15 | */
16 | class TwitterOAuth extends Config
17 | {
18 | const API_VERSION = '1.1';
19 | const API_HOST = 'https://api.twitter.com';
20 | const UPLOAD_HOST = 'https://upload.twitter.com';
21 | const UPLOAD_CHUNK = 40960; // 1024 * 40
22 |
23 | /** @var Response details about the result of the last request */
24 | private $response;
25 | /** @var string|null Application bearer token */
26 | private $bearer;
27 | /** @var Consumer Twitter application details */
28 | private $consumer;
29 | /** @var Token|null User access token details */
30 | private $token;
31 | /** @var HmacSha1 OAuth 1 signature type used by Twitter */
32 | private $signatureMethod;
33 |
34 | /**
35 | * Constructor
36 | *
37 | * @param string $consumerKey The Application Consumer Key
38 | * @param string $consumerSecret The Application Consumer Secret
39 | * @param string|null $oauthToken The Client Token (optional)
40 | * @param string|null $oauthTokenSecret The Client Token Secret (optional)
41 | */
42 | public function __construct($consumerKey, $consumerSecret, $oauthToken = null, $oauthTokenSecret = null)
43 | {
44 | $this->resetLastResponse();
45 | $this->signatureMethod = new HmacSha1();
46 | $this->consumer = new Consumer($consumerKey, $consumerSecret);
47 | if (!empty($oauthToken) && !empty($oauthTokenSecret)) {
48 | $this->token = new Token($oauthToken, $oauthTokenSecret);
49 | }
50 | if (empty($oauthToken) && !empty($oauthTokenSecret)) {
51 | $this->bearer = $oauthTokenSecret;
52 | }
53 | }
54 |
55 | /**
56 | * @param string $oauthToken
57 | * @param string $oauthTokenSecret
58 | */
59 | public function setOauthToken($oauthToken, $oauthTokenSecret)
60 | {
61 | $this->token = new Token($oauthToken, $oauthTokenSecret);
62 | }
63 |
64 | /**
65 | * @return string|null
66 | */
67 | public function getLastApiPath()
68 | {
69 | return $this->response->getApiPath();
70 | }
71 |
72 | /**
73 | * @return int
74 | */
75 | public function getLastHttpCode()
76 | {
77 | return $this->response->getHttpCode();
78 | }
79 |
80 | /**
81 | * @return array
82 | */
83 | public function getLastXHeaders()
84 | {
85 | return $this->response->getXHeaders();
86 | }
87 |
88 | /**
89 | * @return array|object|null
90 | */
91 | public function getLastBody()
92 | {
93 | return $this->response->getBody();
94 | }
95 |
96 | /**
97 | * Resets the last response cache.
98 | */
99 | public function resetLastResponse()
100 | {
101 | $this->response = new Response();
102 | }
103 |
104 | /**
105 | * Make URLs for user browser navigation.
106 | *
107 | * @param string $path
108 | * @param array $parameters
109 | *
110 | * @return string
111 | */
112 | public function url($path, array $parameters)
113 | {
114 | $this->resetLastResponse();
115 | $this->response->setApiPath($path);
116 | $query = http_build_query($parameters);
117 | return sprintf('%s/%s?%s', self::API_HOST, $path, $query);
118 | }
119 |
120 | /**
121 | * Make /oauth/* requests to the API.
122 | *
123 | * @param string $path
124 | * @param array $parameters
125 | *
126 | * @return array
127 | * @throws TwitterOAuthException
128 | */
129 | public function oauth($path, array $parameters = [])
130 | {
131 | $response = [];
132 | $this->resetLastResponse();
133 | $this->response->setApiPath($path);
134 | $url = sprintf('%s/%s', self::API_HOST, $path);
135 | $result = $this->oAuthRequest($url, 'POST', $parameters);
136 |
137 | if ($this->getLastHttpCode() != 200) {
138 | throw new TwitterOAuthException($result);
139 | }
140 |
141 | parse_str($result, $response);
142 | $this->response->setBody($response);
143 |
144 | return $response;
145 | }
146 |
147 | /**
148 | * Make /oauth2/* requests to the API.
149 | *
150 | * @param string $path
151 | * @param array $parameters
152 | *
153 | * @return array|object
154 | */
155 | public function oauth2($path, array $parameters = [])
156 | {
157 | $method = 'POST';
158 | $this->resetLastResponse();
159 | $this->response->setApiPath($path);
160 | $url = sprintf('%s/%s', self::API_HOST, $path);
161 | $request = Request::fromConsumerAndToken($this->consumer, $this->token, $method, $url, $parameters);
162 | $authorization = 'Authorization: Basic ' . $this->encodeAppAuthorization($this->consumer);
163 | $result = $this->request($request->getNormalizedHttpUrl(), $method, $authorization, $parameters);
164 | $response = JsonDecoder::decode($result, $this->decodeJsonAsArray);
165 | $this->response->setBody($response);
166 | return $response;
167 | }
168 |
169 | /**
170 | * Make GET requests to the API.
171 | *
172 | * @param string $path
173 | * @param array $parameters
174 | *
175 | * @return array|object
176 | */
177 | public function get($path, array $parameters = [])
178 | {
179 | return $this->http('GET', self::API_HOST, $path, $parameters);
180 | }
181 |
182 | /**
183 | * Make POST requests to the API.
184 | *
185 | * @param string $path
186 | * @param array $parameters
187 | *
188 | * @return array|object
189 | */
190 | public function post($path, array $parameters = [])
191 | {
192 | return $this->http('POST', self::API_HOST, $path, $parameters);
193 | }
194 |
195 | /**
196 | * Make DELETE requests to the API.
197 | *
198 | * @param string $path
199 | * @param array $parameters
200 | *
201 | * @return array|object
202 | */
203 | public function delete($path, array $parameters = [])
204 | {
205 | return $this->http('DELETE', self::API_HOST, $path, $parameters);
206 | }
207 |
208 | /**
209 | * Make PUT requests to the API.
210 | *
211 | * @param string $path
212 | * @param array $parameters
213 | *
214 | * @return array|object
215 | */
216 | public function put($path, array $parameters = [])
217 | {
218 | return $this->http('PUT', self::API_HOST, $path, $parameters);
219 | }
220 |
221 | /**
222 | * Upload media to upload.twitter.com.
223 | *
224 | * @param string $path
225 | * @param array $parameters
226 | * @param boolean $chunked
227 | *
228 | * @return array|object
229 | */
230 | public function upload($path, array $parameters = [], $chunked = false)
231 | {
232 | if ($chunked) {
233 | return $this->uploadMediaChunked($path, $parameters);
234 | } else {
235 | return $this->uploadMediaNotChunked($path, $parameters);
236 | }
237 | }
238 |
239 | /**
240 | * Private method to upload media (not chunked) to upload.twitter.com.
241 | *
242 | * @param string $path
243 | * @param array $parameters
244 | *
245 | * @return array|object
246 | */
247 | private function uploadMediaNotChunked($path, $parameters)
248 | {
249 | $file = file_get_contents($parameters['media']);
250 | $base = base64_encode($file);
251 | $parameters['media'] = $base;
252 | return $this->http('POST', self::UPLOAD_HOST, $path, $parameters);
253 | }
254 |
255 | /**
256 | * Private method to upload media (chunked) to upload.twitter.com.
257 | *
258 | * @param string $path
259 | * @param array $parameters
260 | *
261 | * @return array|object
262 | */
263 | private function uploadMediaChunked($path, $parameters)
264 | {
265 | // Init
266 | $init = $this->http('POST', self::UPLOAD_HOST, $path, [
267 | 'command' => 'INIT',
268 | 'media_type' => $parameters['media_type'],
269 | 'total_bytes' => filesize($parameters['media'])
270 | ]);
271 | // Append
272 | $segment_index = 0;
273 | $media = fopen($parameters['media'], 'rb');
274 | while (!feof($media))
275 | {
276 | $this->http('POST', self::UPLOAD_HOST, 'media/upload', [
277 | 'command' => 'APPEND',
278 | 'media_id' => $init->media_id_string,
279 | 'segment_index' => $segment_index++,
280 | 'media_data' => base64_encode(fread($media, self::UPLOAD_CHUNK))
281 | ]);
282 | }
283 | fclose($media);
284 | // Finalize
285 | $finalize = $this->http('POST', self::UPLOAD_HOST, 'media/upload', [
286 | 'command' => 'FINALIZE',
287 | 'media_id' => $init->media_id_string
288 | ]);
289 | return $finalize;
290 | }
291 |
292 | /**
293 | * @param string $method
294 | * @param string $host
295 | * @param string $path
296 | * @param array $parameters
297 | *
298 | * @return array|object
299 | */
300 | private function http($method, $host, $path, array $parameters)
301 | {
302 | $this->resetLastResponse();
303 | $url = sprintf('%s/%s/%s.json', $host, self::API_VERSION, $path);
304 | $this->response->setApiPath($path);
305 | $result = $this->oAuthRequest($url, $method, $parameters);
306 | $response = JsonDecoder::decode($result, $this->decodeJsonAsArray);
307 | $this->response->setBody($response);
308 | return $response;
309 | }
310 |
311 | /**
312 | * Format and sign an OAuth / API request
313 | *
314 | * @param string $url
315 | * @param string $method
316 | * @param array $parameters
317 | *
318 | * @return string
319 | * @throws TwitterOAuthException
320 | */
321 | private function oAuthRequest($url, $method, array $parameters)
322 | {
323 | $request = Request::fromConsumerAndToken($this->consumer, $this->token, $method, $url, $parameters);
324 | if (array_key_exists('oauth_callback', $parameters)) {
325 | // Twitter doesn't like oauth_callback as a parameter.
326 | unset($parameters['oauth_callback']);
327 | }
328 | if ($this->bearer === null) {
329 | $request->signRequest($this->signatureMethod, $this->consumer, $this->token);
330 | $authorization = $request->toHeader();
331 | } else {
332 | $authorization = 'Authorization: Bearer ' . $this->bearer;
333 | }
334 | return $this->request($request->getNormalizedHttpUrl(), $method, $authorization, $parameters);
335 | }
336 |
337 | /**
338 | * Make an HTTP request
339 | *
340 | * @param string $url
341 | * @param string $method
342 | * @param string $authorization
343 | * @param array $postfields
344 | *
345 | * @return string
346 | * @throws TwitterOAuthException
347 | */
348 | private function request($url, $method, $authorization, $postfields)
349 | {
350 | /* Curl settings */
351 | $options = [
352 | // CURLOPT_VERBOSE => true,
353 | CURLOPT_CAINFO => __DIR__ . DIRECTORY_SEPARATOR . 'cacert.pem',
354 | CURLOPT_CONNECTTIMEOUT => $this->connectionTimeout,
355 | CURLOPT_HEADER => true,
356 | CURLOPT_HTTPHEADER => ['Accept: application/json', $authorization, 'Expect:'],
357 | CURLOPT_RETURNTRANSFER => true,
358 | CURLOPT_SSL_VERIFYHOST => 2,
359 | CURLOPT_SSL_VERIFYPEER => true,
360 | CURLOPT_TIMEOUT => $this->timeout,
361 | CURLOPT_URL => $url,
362 | CURLOPT_USERAGENT => $this->userAgent,
363 | CURLOPT_ENCODING => 'gzip',
364 | ];
365 |
366 | if (!empty($this->proxy)) {
367 | $options[CURLOPT_PROXY] = $this->proxy['CURLOPT_PROXY'];
368 | $options[CURLOPT_PROXYUSERPWD] = $this->proxy['CURLOPT_PROXYUSERPWD'];
369 | $options[CURLOPT_PROXYPORT] = $this->proxy['CURLOPT_PROXYPORT'];
370 | $options[CURLOPT_PROXYAUTH] = CURLAUTH_BASIC;
371 | $options[CURLOPT_PROXYTYPE] = CURLPROXY_HTTP;
372 | }
373 |
374 | switch ($method) {
375 | case 'GET':
376 | break;
377 | case 'POST':
378 | $options[CURLOPT_POST] = true;
379 | $options[CURLOPT_POSTFIELDS] = Util::buildHttpQuery($postfields);
380 | break;
381 | case 'DELETE':
382 | $options[CURLOPT_CUSTOMREQUEST] = 'DELETE';
383 | break;
384 | case 'PUT':
385 | $options[CURLOPT_CUSTOMREQUEST] = 'PUT';
386 | break;
387 | }
388 |
389 | if (in_array($method, ['GET', 'PUT', 'DELETE']) && !empty($postfields)) {
390 | $options[CURLOPT_URL] .= '?' . Util::buildHttpQuery($postfields);
391 | }
392 |
393 |
394 | $curlHandle = curl_init();
395 | curl_setopt_array($curlHandle, $options);
396 | $response = curl_exec($curlHandle);
397 |
398 | // Throw exceptions on cURL errors.
399 | if (curl_errno($curlHandle) > 0) {
400 | throw new TwitterOAuthException(curl_error($curlHandle), curl_errno($curlHandle));
401 | }
402 |
403 | $this->response->setHttpCode(curl_getinfo($curlHandle, CURLINFO_HTTP_CODE));
404 | $parts = explode("\r\n\r\n", $response);
405 | $responseBody = array_pop($parts);
406 | $responseHeader = array_pop($parts);
407 | $this->response->setHeaders($this->parseHeaders($responseHeader));
408 |
409 | curl_close($curlHandle);
410 |
411 | return $responseBody;
412 | }
413 |
414 | /**
415 | * Get the header info to store.
416 | *
417 | * @param string $header
418 | *
419 | * @return array
420 | */
421 | private function parseHeaders($header)
422 | {
423 | $headers = [];
424 | foreach (explode("\r\n", $header) as $line) {
425 | if (strpos($line, ':') !== false) {
426 | list ($key, $value) = explode(': ', $line);
427 | $key = str_replace('-', '_', strtolower($key));
428 | $headers[$key] = trim($value);
429 | }
430 | }
431 | return $headers;
432 | }
433 |
434 | /**
435 | * Encode application authorization header with base64.
436 | *
437 | * @param Consumer $consumer
438 | *
439 | * @return string
440 | */
441 | private function encodeAppAuthorization($consumer)
442 | {
443 | // TODO: key and secret should be rfc 1738 encoded
444 | $key = $consumer->key;
445 | $secret = $consumer->secret;
446 | return base64_encode($key . ':' . $secret);
447 | }
448 | }
449 |
--------------------------------------------------------------------------------
/twitteroauth/src/TwitterOAuthException.php:
--------------------------------------------------------------------------------
1 |
7 | */
8 | class TwitterOAuthException extends \Exception
9 | {
10 | }
11 |
--------------------------------------------------------------------------------
/twitteroauth/src/Util.php:
--------------------------------------------------------------------------------
1 | array('b','c'), 'd' => 'e')
40 | *
41 | * @param mixed $input
42 | *
43 | * @return array
44 | */
45 | public static function parseParameters($input)
46 | {
47 | if (!isset($input) || !$input) {
48 | return [];
49 | }
50 |
51 | $pairs = explode('&', $input);
52 |
53 | $parameters = [];
54 | foreach ($pairs as $pair) {
55 | $split = explode('=', $pair, 2);
56 | $parameter = Util::urldecodeRfc3986($split[0]);
57 | $value = isset($split[1]) ? Util::urldecodeRfc3986($split[1]) : '';
58 |
59 | if (isset($parameters[$parameter])) {
60 | // We have already recieved parameter(s) with this name, so add to the list
61 | // of parameters with this name
62 |
63 | if (is_scalar($parameters[$parameter])) {
64 | // This is the first duplicate, so transform scalar (string) into an array
65 | // so we can add the duplicates
66 | $parameters[$parameter] = [$parameters[$parameter]];
67 | }
68 |
69 | $parameters[$parameter][] = $value;
70 | } else {
71 | $parameters[$parameter] = $value;
72 | }
73 | }
74 | return $parameters;
75 | }
76 |
77 | /**
78 | * @param $params
79 | *
80 | * @return string
81 | */
82 | public static function buildHttpQuery($params)
83 | {
84 | if (!$params) {
85 | return '';
86 | }
87 |
88 | // Urlencode both keys and values
89 | $keys = Util::urlencodeRfc3986(array_keys($params));
90 | $values = Util::urlencodeRfc3986(array_values($params));
91 | $params = array_combine($keys, $values);
92 |
93 | // Parameters are sorted by name, using lexicographical byte value ordering.
94 | // Ref: Spec: 9.1.1 (1)
95 | uksort($params, 'strcmp');
96 |
97 | $pairs = [];
98 | foreach ($params as $parameter => $value) {
99 | if (is_array($value)) {
100 | // If two or more parameters share the same name, they are sorted by their value
101 | // Ref: Spec: 9.1.1 (1)
102 | // June 12th, 2010 - changed to sort because of issue 164 by hidetaka
103 | sort($value, SORT_STRING);
104 | foreach ($value as $duplicateValue) {
105 | $pairs[] = $parameter . '=' . $duplicateValue;
106 | }
107 | } else {
108 | $pairs[] = $parameter . '=' . $value;
109 | }
110 | }
111 | // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61)
112 | // Each name-value pair is separated by an '&' character (ASCII code 38)
113 | return implode('&', $pairs);
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/twitteroauth/src/Util/JsonDecoder.php:
--------------------------------------------------------------------------------
1 |
7 | */
8 | class JsonDecoder
9 | {
10 | /**
11 | * Decodes a JSON string to stdObject or associative array
12 | *
13 | * @param string $string
14 | * @param bool $asArray
15 | *
16 | * @return array|object
17 | */
18 | public static function decode($string, $asArray)
19 | {
20 | if (version_compare(PHP_VERSION, '5.4.0', '>=') && !(defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) {
21 | return json_decode($string, $asArray, 512, JSON_BIGINT_AS_STRING);
22 | }
23 |
24 | return json_decode($string, $asArray);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/urtb.php:
--------------------------------------------------------------------------------
1 | $_GET['monitorFriendlyName'],
18 | "id" => intval($_GET['monitorID']),
19 | "status" => $_GET['alertTypeFriendlyName'],
20 | "url" => $_GET['monitorURL'],
21 | "details" => $_GET['alertDetails'],
22 | "downtime" => 0,
23 | "timestamp" => date($timestampFormat),
24 | "timezone" => $timezone,
25 | );
26 |
27 | //If there isnt a usable ID just die
28 | if ($alert['id'] === 0) {
29 | die();
30 | }
31 |
32 |
33 | // Load which hosts are currently down
34 | $currentDown = getCurrentDown();
35 |
36 | if ($alert['status'] === "Down"){
37 | // Make sure check isn't already down
38 | if (array_key_exists($alert['id'], $currentDown)) {
39 | error_log("Check got multiple down alerts, doing nothing");
40 | //die();
41 | }
42 | // Add the current down check
43 | $currentDown[$alert['id']] = time();
44 |
45 | } elseif ($alert['status'] === "Up"){
46 | // Get downtime
47 | $alert['downtime'] = calcTimeDifference($currentDown[$alert['id']]);
48 |
49 | // Now that its up, delete the down record
50 | unset($currentDown[$alert['id']]);
51 | }
52 | // Write which hosts are currently down
53 | writeCurrentDown($currentDown);
54 |
55 | // Generate the message
56 | $message = getMessage($alert);
57 |
58 | // Post message to twitter
59 | postTwitter($message);
60 |
61 |
62 | /**
63 | * Calculates how long the check was down for. I spent way to much time on this function
64 | * @param int $dt What time the check went down at in seconds since epoch
65 | * @return string Properly formated time difference
66 | */
67 | function calcTimeDifference($dt){
68 | // Used if there is no downtime record
69 | if (is_null($dt)){
70 | return "";
71 | }
72 |
73 | $downDt = new DateTime("@$dt");
74 | $nowDt = new DateTime();
75 | $day = $downDt->diff($nowDt)->format('%a');
76 | $hour = $downDt->diff($nowDt)->format('%h');
77 | $min = $downDt->diff($nowDt)->format('%i');
78 | $sec = $downDt->diff($nowDt)->format('%s');
79 | $downTime = "";
80 |
81 | if ($day == 1){
82 | $downTime .= "1 Day, ";
83 | } elseif ($day > 1){
84 | $downTime .= "$day Days, ";
85 | }
86 |
87 | if ($hour == 1){
88 | $downTime .= "1 Hour, ";
89 | } elseif ($hour > 1){
90 | $downTime .= "$hour Hours, ";
91 | }
92 |
93 | if ($min == 1){
94 | $downTime .= "1 Minute, ";
95 | } elseif ($min > 1){
96 | $downTime .= "$min Minutes, ";
97 | }
98 |
99 | if ($sec == 1){
100 | $downTime .= "1 Second";
101 | } elseif ($sec > 1){
102 | $downTime .= "$sec Seconds";
103 | }
104 |
105 | // Remove last , and space if present
106 | $downTime = rtrim($downTime, ', ');
107 |
108 | // Removes the last , and space and makes it into the word and
109 | $lastPos = strrpos($downTime, ', ');
110 | if ($lastPos != false){
111 | $downTime = substr_replace($downTime, " and ", $lastPos, 2);
112 | }
113 |
114 | return $downTime;
115 | }
116 |
117 | /**
118 | * Posts the message to twitter
119 | * @param string $message The message to post to twitter
120 | */
121 | function postTwitter($message){
122 | global $twitterConfig;
123 | $connection = new TwitterOAuth($twitterConfig['consumerKey'], $twitterConfig['consumerSecret'], $twitterConfig['accessToken'], $twitterConfig['accessTokenSecret']);
124 | $statues = $connection->post("statuses/update", ["status" => $message]);
125 | print_r($statues);
126 | }
127 |
128 | /**
129 | * Creates a properly formated message
130 | * @param mixed[] $alert Current info about the alert called
131 | * @return string Properly formated message
132 | */
133 | function getMessage($alert){
134 | global $messages;
135 |
136 | $variableRep = array(
137 | 'variable' => array('{{host}}', '{{id}}', '{{status}}', '{{url}}', '{{details}}', '{{downtime}}', '{{timestamp}}', '{{timezone}}'),
138 | 'replacement' => array($alert['host'], $alert['id'], $alert['status'], $alert['url'], $alert['details'], $alert['downtime'], $alert['timestamp'], $alert['timezone']),
139 | );
140 | if ($alert['status'] === "Down"){
141 | return str_replace($variableRep['variable'], $variableRep['replacement'], $messages['downMessage']);
142 | } elseif ($alert['status'] === "Up") {
143 | if ($alert['downtime'] === ""){
144 | return str_replace($variableRep['variable'], $variableRep['replacement'], $messages['upMessageNoDown']);
145 | }
146 | return str_replace($variableRep['variable'], $variableRep['replacement'], $messages['upMessage']);
147 | }
148 |
149 | }
150 |
151 | /**
152 | * Reads what checks are currently down from the file
153 | * @return mixed[] $currentDown Array of checks and the time they went down
154 | */
155 | function getCurrentDown(){
156 | global $cacheFile;
157 | $file = file_get_contents("./$cacheFile");
158 | if ($file === false){
159 | // Try and create file with empty array
160 | if (file_put_contents("./$cacheFile", serialize(array())) === false){
161 | error_log("Not able to write cache file. Manually create and make sure permissions are correct");
162 | die();
163 | }
164 | // Reget the file contents
165 | $file = file_get_contents("./$cacheFile");
166 | }
167 | return unserialize($file);
168 | }
169 |
170 | /**
171 | * Writes which checks are currently down to a file
172 | * @param mixed[] $currentDown Array of checks and the time they went down
173 | */
174 | function writeCurrentDown($currentDown){
175 | global $cacheFile;
176 | if (file_put_contents("./$cacheFile", serialize($currentDown)) === false){
177 | error_log("Not able to write cache file. Manually create and make sure permissions are correct");
178 | die();
179 | }
180 | }
181 |
182 | /**
183 | * Verifies that the request came from uptimeRobot
184 | * @return bool true if the request came from uptime robot, false if it did not
185 | */
186 | function verifyUptimeRobot(){
187 | global $debug, $uptimeRobotIps, $userAgentVerify;
188 |
189 | // Useful for local debugging
190 | if ($debug){
191 | return true;
192 | }
193 |
194 | // Make sure useragent string matches
195 | if (strpos($_SERVER['HTTP_USER_AGENT'], $userAgentVerify) === false){
196 | return false;
197 | }
198 |
199 | // Make sure IPs are from uptimerobot
200 | if (in_array($_SERVER['REMOTE_ADDR'], $uptimeRobotIps) === false){
201 | return false;
202 | }
203 |
204 | return true;
205 | }
206 |
--------------------------------------------------------------------------------