You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

141 lines
4.3 KiB

  1. <?php
  2. namespace p3k\XRay\Formats;
  3. use DOMDocument, DOMXPath;
  4. use DateTime, DateTimeZone;
  5. class Facebook extends Format {
  6. public static function matches_host($url) {
  7. $host = parse_url($url, PHP_URL_HOST);
  8. // TODO: match hosts like 'm.facebook.com' and 'mbasic.facebook.com'
  9. return in_array($host, ['www.facebook.com','facebook.com']);
  10. }
  11. public static function matches($url) {
  12. return self::matches_host($url);
  13. }
  14. public static function parse($http_response) {
  15. $fbObject = $http_response['body'];
  16. $url = $http_response['url'];
  17. if(is_string($fbObject)) $fbObject = json_decode($fbObject, true);
  18. $parts = self::extract_url_parts($url);
  19. if($parts['type'] == 'event') {
  20. $event = array(
  21. 'type' => 'event',
  22. 'url' => $url,
  23. 'name' => $fbObject['name'],
  24. 'start' => $fbObject['start_time']
  25. );
  26. if(isset($fbObject['end_time'])) $event['end'] = $fbObject['end_time'];
  27. if(isset($fbObject['description'])) $event['summary'] = $fbObject['description'];
  28. // Is the event linked to a Page?
  29. if(isset($fbObject['place']['id'])) {
  30. $card = array(
  31. 'type' => 'card',
  32. 'url' => 'https://facebook.com/'.$fbObject['place']['id'],
  33. 'name' => $fbObject['place']['name']
  34. );
  35. if(isset($fbObject['place']['location'])) {
  36. $location = $fbObject['place']['location'];
  37. if(isset($location['zip'])) $card['postal-code'] = $location['zip'];
  38. if(isset($location['city'])) $card['locality'] = $location['city'];
  39. if(isset($location['state'])) $card['region'] = $location['state'];
  40. if(isset($location['street'])) $card['street-address'] = $location['street'];
  41. if(isset($location['country'])) $card['country'] = $location['country'];
  42. if(isset($location['latitude'])) $card['latitude'] = (string)$location['latitude'];
  43. if(isset($location['longitude'])) $card['longitude'] = (string)$location['longitude'];
  44. }
  45. $event['location'] = $card['url'];
  46. $event['refs'] = array($card);
  47. // If we only have a name, use that
  48. } elseif(isset($fbObject['place']['name'])) {
  49. $event['location'] = $fbObject['place']['name'];
  50. }
  51. $event['post-type'] = \p3k\XRay\PostType::discover($event);
  52. return [
  53. 'data' => $event,
  54. 'original' => $fbObject,
  55. 'source-format' => 'facebook',
  56. ];
  57. }
  58. }
  59. public static function fetch($url, $creds) {
  60. $parts = self::extract_url_parts($url);
  61. if(!$parts or $parts['api_uri'] == false) {
  62. return [
  63. 'error' => 'unsupported_url',
  64. 'error_description' => 'This Facebook URL is not supported',
  65. 'error_code' => 400,
  66. ];
  67. }
  68. $fb = new \Facebook\Facebook(array(
  69. 'app_id' => $creds['facebook_app_id'],
  70. 'app_secret' => $creds['facebook_app_secret'],
  71. 'default_graph_version' => 'v2.9',
  72. ));
  73. $fbApp = new \Facebook\FacebookApp($creds['facebook_app_id'], $creds['facebook_app_secret']);
  74. $token = $fbApp->getAccessToken();
  75. $request = new \Facebook\FacebookRequest($fbApp, $token, 'GET', $parts['api_uri']);
  76. try {
  77. $response = $fb->getClient()->sendRequest($request);
  78. } catch(\Facebook\Exceptions\FacebookResponseException $e) {
  79. return [
  80. 'error' => 'facebook_graph_error',
  81. 'error_description' => 'Graph returned an error: ' . $e->getMessage(),
  82. 'error_code' => 400,
  83. ];
  84. } catch(\Facebook\Exceptions\FacebookSDKException $e) {
  85. return [
  86. 'error' => 'facebook_sdk_error',
  87. 'error_description' => 'Facebook SDK returned an error: ' . $e->getMessage(),
  88. 'error_code' => 400,
  89. ];
  90. }
  91. return [
  92. 'code' => 200,
  93. 'body' => $response->getDecodedBody(),
  94. 'url' => $url
  95. ];
  96. }
  97. private static function extract_url_parts($url) {
  98. $response = false;
  99. if(preg_match('~https://(.*?).?facebook.com/([^/]+)/posts/(\d+)/?$~', $url, $match)) {
  100. // TODO: how do we get these?
  101. // $response['type'] = 'entry';
  102. // $response['api_uri'] = false;
  103. } elseif(preg_match('~https://(.*?).?facebook.com/events/(\d+)/?$~', $url, $match)) {
  104. $response['type'] = 'event';
  105. $response['api_uri'] = '/'.$match[2];
  106. }
  107. return $response;
  108. }
  109. }