public function run()
 {
     // 前回のデータを取得
     $oldCards = $this->converter->convert($this->reader->read(storage_path() . $this->lastDataFile, '[]'));
     if (is_null($oldCards)) {
         return false;
     }
     // URL生成
     $url = 'https://trello.com/1/lists/' . env('TRELLO_LIST_ID') . '/cards' . '?key=' . env('TRELLO_KEY') . '&token=' . env('TRELLO_TOKEN');
     // Trelloよりカード情報取得
     if (false === ($json = $this->getter->get($url))) {
         return false;
     }
     // 取得したカード情報(JSON形式)を配列へ変換
     if (is_null($cards = $this->converter->convert($json))) {
         return false;
     }
     $created = new CardCreated();
     $updated = new CardUpdated();
     $currentCards = [];
     foreach ($cards as $card) {
         // 保存用データ作成
         $id = $card['id'];
         // 日本時間で保存したほうが分かりやすい
         $carbonTime = (new Carbon($card['dateLastActivity']))->timezone('Asia/Tokyo');
         $timeString = $carbonTime->toDateTimeString();
         $currentCards[$id] = $timeString;
         // 直前のデーターに存在していなければ新規カード
         if (!array_key_exists($id, $oldCards)) {
             $created->id = $id;
             $created->name = $card['name'];
             $created->time = $carbonTime;
             $this->dispatcher->fire($created);
             continue;
         }
         // IDが一致するのに最終更新時間が異なっていれば更新
         if ($timeString !== $oldCards[$id]) {
             $updated->id = $id;
             $updated->name = $card['name'];
             $updated->time = $carbonTime;
             $this->dispatcher->fire($updated);
         }
     }
     $deleted = new CardDeleted();
     // 削除されたカードを選択
     $deletedCards = array_diff_key($oldCards, $currentCards);
     foreach ($deletedCards as $deletedId => $time) {
         $deleted->id = $deletedId;
         $this->dispatcher->fire($deleted);
     }
     // 今回の取得データをファイルへ保存
     $this->file->put(storage_path() . $this->lastDataFile, json_encode($currentCards));
     return true;
 }
 /**
  * 受け取ったイベントをTrelloのリストにログする
  *
  * @param  MonitorableInterface  $event
  * @return void
  */
 public function handle(MonitorBaseEvent $event)
 {
     // サイト状態リスト上のカードを取得
     $url = 'https://trello.com/1/lists/' . env('TRELLO_SITES_STATUS_LIST') . '/cards' . '?key=' . env('TRELLO_KEY') . '&token=' . env('TRELLO_TOKEN');
     if (false === ($result = $this->getter->get($url))) {
         \Log::notice('TrelloからWebサイト監視リストの情報が取得できませんでした。');
         return;
     }
     $cards = $this->converter->convert($result);
     foreach ($cards as $card) {
         if ($card['name'] === $event->url) {
             $updateCard = $card;
             break;
         }
     }
     if (isset($updateCard)) {
         // 既存ラベル色取得、緑と赤は削除
         $labels = array_diff(array_column($updateCard['labels'], 'color'), ['green', 'red']);
         $labelString = implode(',', $labels);
         // 既存カード更新
         if ($event instanceof SiteUpped) {
             // サイト復活時
             // ラベル色緑設定
             $url = 'https://trello.com/1/cards/' . $updateCard['id'] . '/labels' . '?key=' . env('TRELLO_KEY') . '&token=' . env('TRELLO_TOKEN') . '&value=' . trim($labelString . ',green', ',');
             $result = $this->putter->put($url);
             // 説明文からダウン時間情報削除
             $url = 'https://trello.com/1/cards/' . $updateCard['id'] . '/desc' . '?key=' . env('TRELLO_KEY') . '&token=' . env('TRELLO_TOKEN') . '&value=' . urlencode(trim(preg_replace('/<.+より停止中 >/u', '', $updateCard['desc'])));
             $result = $this->putter->put($url);
         } else {
             // サイトダウン時
             // ラベル色赤設定
             $url = 'https://trello.com/1/cards/' . $updateCard['id'] . '/labels' . '?key=' . env('TRELLO_KEY') . '&token=' . env('TRELLO_TOKEN') . '&value=' . trim($labelString . ',red', ',');
             $result = $this->putter->put($url);
             // 説明文にダウン時間情報追加
             $url = 'https://trello.com/1/cards/' . $updateCard['id'] . '/desc' . '?key=' . env('TRELLO_KEY') . '&token=' . env('TRELLO_TOKEN') . '&value=' . urlencode('< ' . $event->time->toDateTimeString() . " より停止中 >\n" . $updateCard['desc']);
             $result = $this->putter->put($url);
         }
     } else {
         // 新規カード追加
         $url = 'https://trello.com/1/cards/' . '?key=' . env('TRELLO_KEY') . '&token=' . env('TRELLO_TOKEN') . '&idList=' . env('TRELLO_SITES_STATUS_LIST') . '&name=' . urlencode($event->url) . '&labels=' . ($event instanceof SiteUpped ? 'green' : 'red');
         $newCard = $this->converter->convert($this->poster->post($url));
         if ($event instanceof SiteDowned) {
             // 説明文のダウン時間情報更新
             $url = 'https://trello.com/1/cards/' . $newCard['id'] . '/desc' . '?key=' . env('TRELLO_KEY') . '&token=' . env('TRELLO_TOKEN') . '&value=' . urlencode('< ' . $event->time->toDateTimeString() . " より停止中 >\n");
             $result = $this->putter->put($url);
         }
     }
 }
 public function run($url, $timeout)
 {
     $now = Carbon::now();
     // 前回のデータを取得
     // totalDownは今回使用しないが、統計情報が必要になったら使える
     // 日時取得のオーバーヘッドが大きいなら、初期時の処理をクロージャーにするなど
     // 工夫が必要かもしれない(現状文字列で渡しているため、毎回評価される)
     $lastData = $this->converter->convert($this->reader->read(storage_path() . $this->convertUrlToFileName($url), '{' . '"startedAt": "' . $now->toDateTimeString() . '",' . '"totalDown": "0",' . '"status": "down",' . '"lastChangedAt": "' . $now->toDateTimeString() . '"' . '}'));
     // curlで接続
     $curl = curl_init($url);
     // オプション指定、サイトに合わせて調節
     $options = [CURLOPT_RETURNTRANSFER => true, CURLOPT_CONNECTTIMEOUT => $timeout];
     curl_setopt_array($curl, $options);
     // 呼び出し
     $result = curl_exec($curl);
     // 接続時間や転送時間などログしておくと統計情報に利用できる情報の配列
     // 今回はステータスコード以外未使用、未保存
     $info = curl_getinfo($curl);
     curl_close($curl);
     // 状態がダウンに変わった場合
     if ($lastData['status'] === 'up' && (!$result || $info['http_code'] !== 200)) {
         $lastData['status'] = 'down';
         $lastData['lastChangedAt'] = $now->toDateTimeString();
         $siteDown = new SiteDowned();
         $siteDown->url = $url;
         $siteDown->time = $now;
         $siteDown->code = $info['http_code'];
         $this->dispatcher->fire($siteDown);
     }
     // 状態がアップに変わった場合
     if ($lastData['status'] === 'down' && $result && $info['http_code'] === 200) {
         $lastData['status'] = 'up';
         $lastData['totalDown'] += Carbon::createFromFormat('Y-m-d H:i:s', $lastData['lastChangedAt'])->diffInMinutes($now);
         $lastData['lastChangedAt'] = $now->toDateTimeString();
         $siteUp = new SiteUpped();
         $siteUp->url = $url;
         $siteUp->time = $now;
         $this->dispatcher->fire($siteUp);
     }
     // データの保存
     $this->file->put(storage_path() . $this->convertUrlToFileName($url), json_encode($lastData));
 }
 /**
  * 元のタスクへリマインダー設定されていれば
  * 日付を今日に変更し、新しく設定する
  *
  * @param array $baseTask
  * @param array $newTask
  */
 private function createRemeinderFromOriginal($baseTask, $newTask)
 {
     // ベースタスクのリマインダー取得
     $url = 'a.wunderlist.com/api/v1/reminders' . '?task_id=' . $baseTask['id'];
     $jsonReminder = $this->getter->get($url, $this->tokens);
     $reminder = $this->converter->convert($jsonReminder);
     // リマインダー設定なし
     if (empty($reminder)) {
         return;
     }
     // リマインダーはタスクに一つしか取得できないが、
     // APIがリストのリマインダー取得と共有のため、多重配列で返ってくる
     $reminderTime = Carbon::parse($reminder[0]['date']);
     // 生成したタスクに今日の日付の同時刻でリマインダー設定
     $this->createReminder($newTask, $this->todayAtSameTime($reminderTime));
 }
 private function getAllCards()
 {
     $lists = $this->getAllLists();
     $this->initializeGentlyAPICall();
     $this->myCards = [];
     foreach ($lists as $listId => $list) {
         $this->gentlyAPICall();
         $url = 'https://trello.com/1/lists/' . $listId . '/cards' . '?key=' . env('TRELLO_KEY') . '&token=' . env('TRELLO_TOKEN');
         if (false === ($result = $this->getter->get($url))) {
             continue;
         }
         $cards = $this->converter->convert($result);
         foreach ($cards as $card) {
             $this->myCards[$card['id']] = ['name' => $card['name'], 'listId' => $listId, 'listName' => $list['name'], 'boardId' => $list['boardId'], 'boardName' => $list['boardName']];
         }
     }
     return $this->myCards;
 }