Browse Source

adds a method to import a tweet on demand

master
Aaron Parecki 7 years ago
parent
commit
378db7ffe4
No known key found for this signature in database GPG Key ID: 276C2817346D6056
12 changed files with 10766 additions and 10311 deletions
  1. +2
    -0
      app/Events/NewTweetEvent.php
  2. +1
    -2
      app/Http/Controllers/DashboardController.php
  3. +116
    -0
      app/Http/Controllers/ImportController.php
  4. +2
    -2
      public/css/app.css
  5. +10521
    -10295
      public/js/app.js
  6. +1
    -0
      resources/assets/js/app.js
  7. +99
    -0
      resources/assets/js/components/ImportTweet.vue
  8. +0
    -0
      resources/assets/js/components/Mission1.vue
  9. +13
    -11
      resources/assets/sass/app.scss
  10. +5
    -0
      resources/views/import.blade.php
  11. +1
    -1
      resources/views/team-tweets.blade.php
  12. +5
    -0
      routes/web.php

+ 2
- 0
app/Events/NewTweetEvent.php View File

@ -26,6 +26,7 @@ class NewTweetEvent implements ShouldBroadcast
public $photos; public $photos;
public $mission; public $mission;
public $mission_id; public $mission_id;
public $twitter_id;
/** /**
* Create a new event instance. * Create a new event instance.
@ -44,6 +45,7 @@ class NewTweetEvent implements ShouldBroadcast
$this->photos = json_decode($tweet->photo); $this->photos = json_decode($tweet->photo);
$this->mission = ($tweet->mission ? $tweet->mission->hashtag : null); $this->mission = ($tweet->mission ? $tweet->mission->hashtag : null);
$this->mission_id = $tweet->mission_id; $this->mission_id = $tweet->mission_id;
$this->twitter_id = $tweet->tweet_id;
} }
/** /**

+ 1
- 2
app/Http/Controllers/DashboardController.php View File

@ -27,8 +27,7 @@ class DashboardController extends Controller
*/ */
public function index() public function index()
{ {
return view('dashboard', [
]);
return view('dashboard', []);
} }
public function queue() { public function queue() {

+ 116
- 0
app/Http/Controllers/ImportController.php View File

@ -0,0 +1,116 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller as BaseController;
use Log;
use App\Player, App\Team, App\Tweet, App\TransitCenter, App\TransitLine, App\Document, App\Mission;
use App\Events\NewTweetEvent;
use Twitter;
class ImportController extends BaseController
{
public function __construct() {
$this->middleware('auth');
}
public function index(Request $request) {
return view('import', []);
}
public function preview(Request $request) {
$url = $request->input('url');
if(preg_match('/twitter\.com\/.+\/status(?:es)?\/(\d+)/', $url, $match)) {
$tweetID = $match[1];
} else {
return response()->json(['error'=>'Invalid URL']);
}
try {
$data = Twitter::getTweet($tweetID);
} catch(\Exception $e) {
return response()->json(['error'=>'Could not fetch tweet']);
}
$player = Player::where('twitter_user_id', $data->user->id_str)->first();
if(!$player) {
return response()->json(['error'=>'Couldn\'t find the player for this tweet. Check that they are added to a team.']);
}
$tweet = self::buildTweetFromTwitterObject($player, $data);
$event = new NewTweetEvent($tweet);
unset($event->socket);
return response()->json($event);
}
public function save(Request $request) {
$tweetID = $request->input('tweet_id');
try {
$data = Twitter::getTweet($tweetID);
} catch(\Exception $e) {
return response()->json(['error'=>'Could not fetch tweet']);
}
$player = Player::where('twitter_user_id', $data->user->id_str)->first();
if(!$player) {
return response()->json(['error'=>'Couldn\'t find the player for this tweet. Check that they are added to a team.']);
}
$tweet = self::buildTweetFromTwitterObject($player, $data);
$tweet->save();
if($tweet->mission_id && $tweet->team_id) {
event(new NewTweetEvent($tweet));
}
return response()->json(['result'=>'ok']);
}
private static function buildTweetFromTwitterObject($player, $data) {
if(isset($data->extended_tweet->full_text))
$text = $data->extended_tweet->full_text;
else
$text = $data->text;
// Unshorten URLs
if(isset($data->entities->urls)) {
foreach($data->entities->urls as $url) {
$text = str_replace($url->url, $url->expanded_url, $text);
}
}
// Remove media URLs from tweet text
$photos = [];
if(isset($data->extended_entities->media)) {
foreach($data->extended_entities->media as $media) {
$text = str_replace($media->url, '', $text);
$photos[] = $media->media_url_https;
}
$text = trim($text);
}
$mission_id = 0;
foreach(Mission::all() as $mission) {
if(strpos($text, $mission->hashtag) !== false) {
$mission_id = $mission->id;
}
}
$tweet = new Tweet;
$tweet->tweet_id = $data->id_str;
$tweet->player_id = $player ? $player->id : 0;
$tweet->team_id = $player ? $player->team->id : 0;
$tweet->text = $text;
$tweet->photo = json_encode($photos, JSON_UNESCAPED_SLASHES);
$tweet->mission_id = $mission_id;
$tweet->tweet_date = date('Y-m-d H:i:s', strtotime($data->created_at));
return $tweet;
}
}

+ 2
- 2
public/css/app.css View File

@ -8762,14 +8762,14 @@ button.close {
margin-right: 4px; margin-right: 4px;
} }
.tweet {
.tweet-list .tweet {
border: 1px #d3e0e9 solid; border: 1px #d3e0e9 solid;
border-radius: 4px; border-radius: 4px;
padding: 6px; padding: 6px;
margin-bottom: 6px; margin-bottom: 6px;
} }
.tweet .text {
.tweet-list .tweet .text {
white-space: pre-wrap; white-space: pre-wrap;
font-size: 1.5em; font-size: 1.5em;
margin: 8px 0; margin: 8px 0;

+ 10521
- 10295
public/js/app.js
File diff suppressed because it is too large
View File


+ 1
- 0
resources/assets/js/app.js View File

@ -22,6 +22,7 @@ window.Vue = require('vue');
*/ */
Vue.component('tweet-queue', require('./components/TweetQueue.vue')); Vue.component('tweet-queue', require('./components/TweetQueue.vue'));
Vue.component('import-tweet', require('./components/ImportTweet.vue'));
Vue.component('scorecard', require('./components/Scorecard.vue')); Vue.component('scorecard', require('./components/Scorecard.vue'));
var data = { var data = {

+ 99
- 0
resources/assets/js/components/ImportTweet.vue View File

@ -0,0 +1,99 @@
<template>
<div class="container">
<div class="row">
<div class="col-xs-8 col-md-8 panel scorecard">
<div class="panel-body">
<div v-if="previewTweet">
<div class="profile">
<img :src="tweet.player_photo" :style="'border-color: #'+tweet.team_color">
<span><a :href="'https://twitter.com/'+tweet.player_username">@{{ tweet.player_username }}</a></span>
</div>
<div class="tweet">
<div class="text">{{ tweet.text }}</div>
<div v-if="tweet.photos">
<div :class="'multi-photo photos-'+tweet.photos.length" v-if="tweet.photos">
<div v-for="img in tweet.photos" class="photo" :style="'background-image:url('+img+')'" :data-featherlight="img">
<img :src="img">
</div>
</div>
<div class="multi-photo-clear"></div>
</div>
</div>
<div class="tweet-actions">
<button type="button" class="btn btn-success" v-on:click="importTweet">Import</button>
</div>
</div>
<div v-else>
<div v-if="error">
<div class="alert alert-danger" role="alert">{{ error }}</div>
</div>
<form v-on:submit.prevent>
<div class="form-group">
<label for="">Tweet URL</label>
<input type="url" class="form-control" placeholder="https://twitter.com/..." v-on:keyup.enter="loadTweet">
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
module.exports = {
props: [],
data () {
return {
error: false,
tweet: null,
tweetID: null,
previewTweet: false
}
},
methods: {
loadTweet(e) {
var tweetURL = $(e.target).val();
$.post("/import/preview", {
url: tweetURL
}, function(response){
if(response.error) {
this.tweet = null;
this.tweetID = null,
this.previewTweet = false;
this.error = response.error;
} else {
console.log(response);
this.tweet = response;
this.tweetID = response.twitter_id;
this.previewTweet = true;
this.error = false;
}
}.bind(this));
},
importTweet() {
$.post("/import/save", {
tweet_id: this.tweetID
}, function(response) {
if(response.error) {
this.tweet = null;
this.tweetID = null,
this.previewTweet = false;
this.error = response.error;
} else {
this.tweet = null;
this.tweetID = null;
this.previewTweet = false;
this.error = false;
}
}.bind(this));
}
}
}
</script>

+ 0
- 0
resources/assets/js/components/Mission1.vue View File


+ 13
- 11
resources/assets/sass/app.scss View File

@ -259,17 +259,19 @@
} }
.tweet {
border: 1px $laravel-border-color solid;
border-radius: 4px;
padding: 6px;
margin-bottom: 6px;
.text {
white-space: pre-wrap;
font-size: 1.5em;
margin: 8px 0;
}
.tweet-list {
.tweet {
border: 1px $laravel-border-color solid;
border-radius: 4px;
padding: 6px;
margin-bottom: 6px;
.text {
white-space: pre-wrap;
font-size: 1.5em;
margin: 8px 0;
}
}
} }

+ 5
- 0
resources/views/import.blade.php View File

@ -0,0 +1,5 @@
@extends('layouts.app')
@section('content')
<import-tweet></import-tweet>
@endsection

+ 1
- 1
resources/views/team-tweets.blade.php View File

@ -3,7 +3,7 @@
@section('content') @section('content')
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="col-md-6 col-md-offset-3 tweet-list">
<h2>Team {{ $team->name }}</h2> <h2>Team {{ $team->name }}</h2>

+ 5
- 0
routes/web.php View File

@ -26,6 +26,11 @@ Route::post('/dashboard/reject-tweet', 'DashboardController@reject_tweet');
Route::post('/dashboard/score-tweet', 'DashboardController@score_tweet'); Route::post('/dashboard/score-tweet', 'DashboardController@score_tweet');
Route::post('/dashboard/reply', 'DashboardController@reply_to_tweet'); Route::post('/dashboard/reply', 'DashboardController@reply_to_tweet');
Route::get('/import', 'ImportController@index')->name('import');
Route::post('/import/preview', 'ImportController@preview');
Route::get('/import/preview', 'ImportController@preview');
Route::post('/import/save', 'ImportController@save');
Route::get('/slideshow', 'SlideshowController@slideshow')->name('slideshow'); Route::get('/slideshow', 'SlideshowController@slideshow')->name('slideshow');
Route::get('/teams', 'TeamController@index')->name('teams'); Route::get('/teams', 'TeamController@index')->name('teams');

Loading…
Cancel
Save