├── app ├── tmp │ └── .empty ├── public │ ├── styles.css │ ├── index.php │ └── bootstrap.min.css ├── Post.php ├── config │ └── config.sample.yml ├── Utilities │ └── Locker.php ├── empleadoEstatalBot.php ├── RedditManager │ └── RedditManager.php └── NewspaperProcessor │ └── NewspaperProcessor.php ├── CODE_OF_CONDUCT.md ├── .gitignore ├── composer.json ├── LICENSE ├── README.md └── composer.lock /app/tmp/.empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | * Don't be a dick 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /vendor 3 | /app/config/config.yml 4 | /app/tmp/* 5 | !/app/tmp/.empty -------------------------------------------------------------------------------- /app/public/styles.css: -------------------------------------------------------------------------------- 1 | table th { 2 | text-align: center; 3 | } 4 | 5 | table td { 6 | padding: 1em 0.5em; 7 | } 8 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "repositories": 3 | [ 4 | { 5 | "type": "vcs", 6 | "url": "https://github.com/andreskrey/html-to-markdown" 7 | } 8 | ], 9 | "require": { 10 | "rtheunissen/oauth2-reddit": "^2.0", 11 | "league/html-to-markdown": "dev-dev-reddit-flavored-markdown as 4.2", 12 | "ext-mbstring": "*", 13 | "monolog/monolog": "^1", 14 | "andreskrey/readability.php": "~2.0", 15 | "neitanod/forceutf8": "^2.0", 16 | "illuminate/database": "^5.4", 17 | "symfony/console": "^3.3", 18 | "symfony/yaml": "^3.3" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "empleadoEstatalBot\\": "app/" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Post.php: -------------------------------------------------------------------------------- 1 | hasMany('empleadoEstatalBot\Post', 'parent_id', 'id'); 20 | } 21 | 22 | public function parent() 23 | { 24 | if (is_null($this->parent_id)) { 25 | return null; 26 | } else { 27 | return $this->hasOne('empleadoEstatalBot\Post', 'id', 'parent_id'); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /app/public/index.php: -------------------------------------------------------------------------------- 1 | 'Rejected', 8 | 1 => 'To fetch', 9 | 2 => 'To post', 10 | 3 => 'Posted', 11 | ]; 12 | ?> 13 | 14 | 15 | 16 | 17 | 18 | empleadoEstatalBot 19 | 20 | 21 | 22 | 23 |
24 |

empleadoEstatalBot

25 | 26 |

Latest ten posts

27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | orderBy('updated_at', 'desc')->get() as $thing) { ?> 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
SubredditThing IDURLStatusTriesInfoLast update
subreddit ?>thing ?>url ?>status] ?>tries ?>info) ?>updated_at ?>
50 |
51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # empleadoEstatalBot 2 | 3 | Also known as 'the bot that steals content from other sites and posts it as a comment on reddit' 4 | 5 | ## Installation 6 | 7 | 1) \> git clone 8 | 2) \> composer install 9 | 3) Create your config.yml in app/config 10 | 4) `empleadoEstatalBot.php config:seed` 11 | 5) Add a cron for `empleadoEstatalBot.php get:start`, `empleadoEstatalBot.php fetch:start` and `empleadoEstatalBot.php post:start` 12 | 13 | ## Usage 14 | 15 | The bot has three main workers available on the CLI 16 | 17 | - `empleadoEstatalBot.php get:start`: Gets all the new posts on the monitored subreddits 18 | - `empleadoEstatalBot.php fetch:start`: Retrieves the newspaper text of the things with status TO_FETCH, converts it to markdown and signs the text. 19 | - `empleadoEstatalBot.php post:start`: Posts all comments with status TO_POST. You can do this step and the previous step with one call adding the `--pre-fetch` argument. 20 | 21 | The recommended way to monitor and post comments on a subreddit is to set a cron on odd minutes to get posts and another on even minutes to fetch and post comments. 22 | 23 | Workers will refuse to work if the same worker is already doing stuff. Let's say your post --pre-fetch worker is taking its sweet time to do its job and the next cron starts up. In this case the post worker will refuse because the previous iteration didn't finish yet. This is controlled through lock files in the tmp folder. If one worker refuses to work even if you are sure there's no other instance in memory, just delete all `.lock` files in the tmp folder. Or wait 10 minutes because locks expire after that period of time. -------------------------------------------------------------------------------- /app/config/config.sample.yml: -------------------------------------------------------------------------------- 1 | bot: 2 | # Log level. Recommended: 200 (info) 3 | log_level: 200 4 | 5 | reddit: 6 | 7 | # reddit login data 8 | client_id: 'client_id' 9 | secret_key: 'secret_key' 10 | redirect_uri: 'redirect_uri' 11 | username: 'username' 12 | password: 'password' 13 | 14 | # Should be left as "submit, read" 15 | scopes: ['submit', 'read'] 16 | 17 | # Domains you don't want the bot to take care of. Wildcards accepted. 18 | banned_domains: ['imgur.com', 19 | '*.imgur.com', 20 | 'twitter.com', 21 | 'youtube.com', 22 | 'reddit.com', 23 | '*.reddit.com', 24 | '*.redditmedia.com', 25 | 'self.*', 26 | 'youtube.com', 27 | 'youtu.be', 28 | '*.youtube.com', 29 | 'storify.com', 30 | 'buzzfeed.com', 31 | 'radiocut.fm', 32 | '*.radiocut.fm', 33 | 'vid.me' 34 | ] 35 | 36 | # Subreddits you want to monitor 37 | subreddits: ['empleadoEstatalBot'] 38 | 39 | # Subreddits you want the bot comments to be distinguished and sticked 40 | # (You HAVE to be a mod and your account MUST HAVE the 'post' permission) 41 | distinguishable: ['empleadoEstatalBot'] 42 | 43 | newspaper_processor: 44 | 45 | # URL Shorteners you want to resolve (reddit doesn't like those services) 46 | url_shorteners: ['t.co', 47 | 'goo.gl', 48 | 'bit.ly' 49 | ] 50 | 51 | # Bot signature. In HTML or markdown 52 | signature: 'signature' 53 | 54 | # Max reddit comment length. Right now is 10000. Set a conservative value like 9000. 55 | max_length: 9000 56 | 57 | database: 58 | 59 | #DB connection information 60 | host: '127.0.0.1' 61 | name: 'db' 62 | user: 'dbuser' 63 | pass: 'dbpass' 64 | -------------------------------------------------------------------------------- /app/Utilities/Locker.php: -------------------------------------------------------------------------------- 1 | addEmergency('LockerUtility: Error while trying to delete/create an old lock file. Check for errors on the log and php error log'); 39 | }; 40 | 41 | /* 42 | * Allow the worker to run 43 | */ 44 | return true; 45 | } 46 | 47 | /* 48 | * Lock exists and it's recent, stop the worker 49 | */ 50 | 51 | return false; 52 | } else { 53 | /* 54 | * No lock file, create one and allow the worker to run 55 | */ 56 | 57 | if (file_put_contents($lockFile, '') === false) { 58 | /* 59 | * Something happened while writing the lock file, log the error 60 | */ 61 | empleadoEstatal::$log->addEmergency('LockerUtility: Error while trying to create lock file.'); 62 | } 63 | 64 | return true; 65 | } 66 | } 67 | 68 | /** 69 | * releaseLock 70 | * 71 | * Releases the lock set before running 72 | * 73 | * @param $worker string Worker to release the lock 74 | * 75 | * @return bool Success or failure while releasing the lock 76 | */ 77 | static public function releaseLock($worker) 78 | { 79 | $lockFile = empleadoEstatal::TMP_DIR . $worker . '.lock'; 80 | 81 | if (unlink($lockFile) === false) { 82 | empleadoEstatal::$log->addEmergency('LockerUtility: Error while trying to delete lock file on release.'); 83 | 84 | return false; 85 | }; 86 | 87 | return true; 88 | } 89 | 90 | /** 91 | * clearLocks 92 | * 93 | * Clears all locks. 94 | * 95 | * @return true 96 | */ 97 | static public function clearLocks() 98 | { 99 | $result = true; 100 | foreach (glob(empleadoEstatal::TMP_DIR . '*.lock') as $file) { 101 | if (unlink($file) === false) { 102 | empleadoEstatal::$log->addEmergency(sprintf('LockerUtility: Error while trying to delete lock file on clear locks. File %s', $file)); 103 | $result = false; 104 | }; 105 | } 106 | 107 | return $result; 108 | } 109 | 110 | /** 111 | * clearLock 112 | * 113 | * Clears specific lock. 114 | * 115 | * @return true 116 | */ 117 | static public function clearLock($worker) 118 | { 119 | $lockFile = empleadoEstatal::TMP_DIR . $worker . '.lock'; 120 | 121 | if (unlink($lockFile) === false) { 122 | empleadoEstatal::$log->addEmergency(sprintf('LockerUtility: Error while trying to delete lock file on clear specific lock. File %s', $lockFile)); 123 | 124 | return false; 125 | }; 126 | 127 | return true; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /app/empleadoEstatalBot.php: -------------------------------------------------------------------------------- 1 | register('get:start') 26 | ->setDescription('Start the Get worker.') 27 | ->setCode(function (InputInterface $input, OutputInterface $output) { 28 | $empleado = new empleadoEstatal(); 29 | $empleado->get(); 30 | }); 31 | 32 | $console->register('fetch:start') 33 | ->setDescription('Start the Fetch worker.') 34 | ->setCode(function (InputInterface $input, OutputInterface $output) { 35 | $empleado = new empleadoEstatal(); 36 | $empleado->fetch(); 37 | }); 38 | 39 | $console->register('post:start') 40 | ->addOption('pre-fetch', 41 | null, 42 | InputOption::VALUE_NONE, 43 | 'Start the FetchWorker before and then the PostWorker') 44 | ->setDescription('Start the Post worker.') 45 | ->setCode(function (InputInterface $input, OutputInterface $output) { 46 | $empleado = new empleadoEstatal(); 47 | if ($input->getOption('pre-fetch')) { 48 | $empleado->fetch(); 49 | } 50 | $empleado->post(); 51 | }); 52 | 53 | $console->register('config:seed') 54 | ->setDescription('Seed the db.') 55 | ->setCode(function (InputInterface $input, OutputInterface $output) { 56 | $empleado = new empleadoEstatal(); 57 | $empleado->seed(); 58 | }); 59 | 60 | $console->register('config:clear-locks') 61 | ->setDescription('Clears all locks.') 62 | ->setCode(function (InputInterface $input, OutputInterface $output) { 63 | $empleado = new empleadoEstatal(); 64 | $empleado->clearLocks(); 65 | }); 66 | 67 | $console->run(); 68 | 69 | class empleadoEstatal 70 | { 71 | public static $log; 72 | public $db; 73 | protected $config; 74 | 75 | const THING_REJECTED = -1; 76 | const THING_TO_FETCH = 1; 77 | const THING_FETCHED = 2; 78 | const THING_POSTED = 3; 79 | 80 | const TMP_DIR = __DIR__ . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR; 81 | 82 | public function __construct() 83 | { 84 | try { 85 | $this->config = Yaml::parse(file_get_contents(__DIR__ . '/config/config.yml')); 86 | } catch (\Exception $e) { 87 | exit('Missing or wrong config on yml: ' . $e->getMessage()); 88 | } 89 | 90 | self::$log = new Logger('ChePibe'); 91 | self::$log->pushHandler(new RotatingFileHandler(__DIR__ . '/tmp/empleadoEstatalBot.log', 5, $this->config['bot']['log_level'])); 92 | 93 | try { 94 | $capsule = new Capsule; 95 | 96 | $capsule->addConnection([ 97 | 'driver' => 'mysql', 98 | 'host' => $this->config['database']['host'], 99 | 'database' => $this->config['database']['name'], 100 | 'username' => $this->config['database']['user'], 101 | 'password' => $this->config['database']['pass'], 102 | 'charset' => 'utf8mb4', 103 | 'collation' => 'utf8mb4_bin', 104 | 'prefix' => '', 105 | ]); 106 | 107 | $capsule->setAsGlobal(); 108 | $capsule->bootEloquent(); 109 | 110 | } catch (\Exception $e) { 111 | self::$log->addCritical('Cannot connect to database: ' . $e->getMessage()); 112 | throw $e; 113 | } 114 | } 115 | 116 | /** 117 | * Wrapper for workers. Catches any exception, logs and clears locks. 118 | * 119 | * @param $name 120 | * @param $arguments 121 | * @throws \Exception 122 | * 123 | * @return mixed 124 | */ 125 | public function __call($name, $arguments) 126 | { 127 | if (method_exists($this, $name)) { 128 | try { 129 | return call_user_func_array([$this, $name], $arguments); 130 | } catch (\Exception $e) { 131 | self::$log->addEmergency(sprintf('empleadoEstatalBot: General exception. Error no: %s. File: %s. Line: %s. Message: %s ', $e->getCode(), $e->getFile(), $e->getLine(), $e->getMessage())); 132 | 133 | // TODO: Change this to clearLock but first map the worker that was running. Maybe read the PHPdoc of the func? 134 | Locker::clearLocks(); 135 | } 136 | } else { 137 | throw new \BadMethodCallException(sprintf('Function "%s" not found.', $name)); 138 | } 139 | } 140 | 141 | protected function get() 142 | { 143 | if (Locker::checkLock('GetWorker')) { 144 | self::$log->addInfo('GetWorker: Starting...'); 145 | $reddit = new RedditManager($this->config['reddit']); 146 | $reddit->login(); 147 | $reddit->getNewPosts(); 148 | $reddit->filterPosts(); 149 | $reddit->savePosts(); 150 | self::$log->addInfo('GetWorker: End.'); 151 | Locker::releaseLock('GetWorker'); 152 | } else { 153 | self::$log->addNotice('GetWorker: Not allowed to start, lock present.'); 154 | } 155 | } 156 | 157 | protected function fetch() 158 | { 159 | if (Locker::checkLock('FetchWorker')) { 160 | self::$log->addInfo('FetchWorker: Starting...'); 161 | $news = new NewspaperProcessor($this->config['newspaper_processor']); 162 | $news->getNewspaperText(); 163 | self::$log->addInfo('FetchWorker: End.'); 164 | Locker::releaseLock('FetchWorker'); 165 | } else { 166 | self::$log->addNotice('FetchWorker: Not allowed to start, lock present.'); 167 | } 168 | } 169 | 170 | protected function post() 171 | { 172 | if (Locker::checkLock('PostWorker')) { 173 | self::$log->addInfo('PostWorker: Starting...'); 174 | $reddit = new RedditManager($this->config['reddit']); 175 | $reddit->login(); 176 | $reddit->postComments(); 177 | self::$log->addInfo('PostWorker: End.'); 178 | Locker::releaseLock('PostWorker'); 179 | } else { 180 | self::$log->addNotice('PostWorker: Not allowed to start, lock present.'); 181 | } 182 | } 183 | 184 | public function seed() 185 | { 186 | Capsule::schema()->create('posts', function ($table) { 187 | $table->increments('id'); 188 | $table->string('subreddit'); 189 | $table->string('thing'); 190 | $table->string('url'); 191 | $table->text('markdown')->nullable(); 192 | $table->tinyInteger('status')->default(1); 193 | $table->tinyInteger('tries')->unsigned()->default(0); 194 | $table->string('info')->nullable()->default(null); 195 | $table->string('comment_id')->nullable()->default(null); 196 | $table->integer('parent_id')->nullable()->default(null); 197 | $table->timestamps(); 198 | }); 199 | 200 | return 'Done.'; 201 | } 202 | 203 | public function clearLocks() 204 | { 205 | return Locker::clearLocks(); 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /app/RedditManager/RedditManager.php: -------------------------------------------------------------------------------- 1 | config = $config; 25 | } 26 | 27 | public function login() 28 | { 29 | $reddit = new Reddit([ 30 | 'clientId' => $this->config['client_id'], 31 | 'clientSecret' => $this->config['secret_key'], 32 | 'redirectUri' => $this->config['redirect_uri'], 33 | 'userAgent' => 'PHP:empleadoEstatalBot:2.0.0, (by /u/subtepass)', 34 | 'scopes' => $this->config['scopes'] 35 | ]); 36 | 37 | $tokenExists = file_exists(__DIR__ . '/../tmp/tokens.reddit'); 38 | if ($tokenExists && filemtime(__DIR__ . '/../tmp/tokens.reddit') + (60 * 50) < time()) { 39 | $tokenExists = false; 40 | unlink(__DIR__ . '/../tmp/tokens.reddit'); 41 | } 42 | 43 | if (!$tokenExists) { 44 | $accessToken = $reddit->getAccessToken('password', [ 45 | 'username' => $this->config['username'], 46 | 'password' => $this->config['password'] 47 | ]); 48 | 49 | $token = $accessToken->getToken(); 50 | file_put_contents(__DIR__ . '/../tmp/tokens.reddit', $token); 51 | } else { 52 | $token = file_get_contents(__DIR__ . '/../tmp/tokens.reddit'); 53 | } 54 | 55 | $this->client = $reddit->getHttpClient(); 56 | $this->headers = $reddit->getHeaders($token); 57 | } 58 | 59 | public function getNewPosts() 60 | { 61 | foreach ($this->config['subreddits'] as $subreddit) { 62 | try { 63 | $request = $this->client 64 | ->request('GET', sprintf('https://oauth.reddit.com/r/%s/new/.json', $subreddit), [ 65 | 'headers' => $this->headers, 66 | 'query' => [ 67 | 'limit' => 10 68 | ]]); 69 | $response = json_decode($request->getBody(), true); 70 | $this->things[$subreddit] = $response['data']['children']; 71 | } catch (Exception $e) { 72 | if ($e->getCode() === 401) { 73 | unlink(__DIR__ . '/../tmp/tokens.reddit'); 74 | } 75 | 76 | empleadoEstatal::$log->addCritical('GetWorker: Failed to get subreddit /new posts: ' . $e->getMessage()); 77 | } 78 | } 79 | 80 | return $this->things; 81 | } 82 | 83 | public function filterPosts() 84 | { 85 | foreach ($this->things as $subreddit => $things) { 86 | foreach ($things as $key => $thing) { 87 | foreach ($this->config['banned_domains'] as $banned_domain) { 88 | // Match domains and full urls (full urls are matched to discard banned extensions, like *.pdf) 89 | if (fnmatch($banned_domain, $thing['data']['domain'], FNM_CASEFOLD) || fnmatch($banned_domain, $thing['data']['url'], FNM_CASEFOLD)) { 90 | empleadoEstatal::$log->addDebug(sprintf('GetWorker: Discarded %s. Banned domain: %s. Matched rule: %s', $thing['data']['name'], $thing['data']['domain'], $banned_domain)); 91 | unset($this->things[$subreddit][$key]); 92 | } 93 | } 94 | } 95 | } 96 | } 97 | 98 | 99 | public function savePosts($posts = null) 100 | { 101 | if (!empty($posts)) { 102 | $this->things = $posts; 103 | } 104 | 105 | $saved = []; 106 | 107 | foreach ($this->things as $subreddit => $things) { 108 | foreach ($things as $key => $thing) { 109 | if (!Post::where('thing', $thing['data']['name'])->exists()) { 110 | Post::firstOrCreate([ 111 | 'subreddit' => $subreddit, 112 | 'thing' => $thing['data']['name'], 113 | 'url' => $thing['data']['url'], 114 | 'status' => empleadoEstatal::THING_TO_FETCH, 115 | 'tries' => 0 116 | ]); 117 | 118 | $saved[] = $thing['data']['name']; 119 | } 120 | } 121 | } 122 | 123 | if (count($saved)) { 124 | empleadoEstatal::$log->addInfo('GetWorker: New posts saved to db: ' . implode(', ', $saved) . '.'); 125 | } else { 126 | empleadoEstatal::$log->addInfo('GetWorker: No new posts to save.'); 127 | } 128 | 129 | return $saved; 130 | } 131 | 132 | public function postComments() 133 | { 134 | foreach (Post::where(['status' => empleadoEstatal::THING_FETCHED, ['tries', '<', 3]])->get() as $thing) { 135 | $parent_comment_id = null; 136 | 137 | /** 138 | * @var $thing Post 139 | */ 140 | try { 141 | if (count($thing->parent()) > 0) { 142 | // Is child, first check if parent already commented 143 | if (is_null($thing->parent()->get()->first()->comment_id)) { 144 | continue; 145 | } else { 146 | $parent_comment_id = $thing->parent()->get()->first()->comment_id; 147 | } 148 | } 149 | $thing->tries++; 150 | 151 | $request = $this->client->request('POST', 'https://oauth.reddit.com/api/comment', [ 152 | 'headers' => $this->headers, 153 | 'form_params' => [ 154 | 'api_type' => 'json', 155 | 'thing_id' => $parent_comment_id ?? $thing->thing, 156 | 'text' => $thing->markdown 157 | ] 158 | ]); 159 | 160 | /* 161 | * Check for errors on the response and handle them. 162 | */ 163 | $response = json_decode((string)$request->getBody(), true); 164 | if (isset($response['json']['errors']) && !empty($response['json']['errors'])) { 165 | throw new Exception(sprintf('Error from reddit: %s', json_encode($response['json']['errors']))); 166 | } 167 | 168 | $thing->status = empleadoEstatal::THING_POSTED; 169 | $thing->comment_id = $response['json']['data']['things'][0]['data']['name']; 170 | 171 | if (in_array($thing->subreddit, $this->config['distinguishable']) && count($thing->parent()) === 0) { 172 | try { 173 | $this->client->request('POST', 'https://oauth.reddit.com/api/distinguish', [ 174 | 'headers' => $this->headers, 175 | 'form_params' => [ 176 | 'api_type' => 'json', 177 | 'how' => 'yes', 178 | 'sticky' => true, 179 | 'id' => $response['json']['data']['things'][0]['data']['name'] 180 | ] 181 | ]); 182 | } catch (Exception $e) { 183 | empleadoEstatal::$log->addError(sprintf('PostWorker: Failed to distinguish %s: %s. Are you a mod?', $thing->thing, $e->getMessage())); 184 | } 185 | } 186 | 187 | empleadoEstatal::$log->addInfo(sprintf('PostWorker: posted %s.', $thing->thing)); 188 | } catch (Exception $e) { 189 | $thing->info = substr($e->getMessage(), 0, 254); 190 | empleadoEstatal::$log->addCritical(sprintf('PostWorker: Failed to post %s: %s', $thing->thing, $e->getMessage())); 191 | } finally { 192 | $thing->save(); 193 | } 194 | } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /app/NewspaperProcessor/NewspaperProcessor.php: -------------------------------------------------------------------------------- 1 | config = $config; 20 | } 21 | 22 | public function getNewspaperText() 23 | { 24 | /** 25 | * @var $client HttpClient 26 | */ 27 | $client = new HttpClient([ 28 | 'headers' => [ 29 | // Lets pretend we are the most average user 30 | 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36' 31 | ]]); 32 | 33 | 34 | foreach (Post::where(['status' => empleadoEstatal::THING_TO_FETCH, ['tries', '<', 3]])->get() as $thing) { 35 | try { 36 | /** 37 | * @var $thing Post 38 | */ 39 | $thing->tries++; 40 | 41 | $html = (string)$client->request('GET', $thing->url)->getBody(); 42 | 43 | // Por alguna razon a veces minutouno manda gzippeado y guzzle no lo descomprime 44 | // Los tres chars son los magic numbers de zip 45 | if (0 === mb_strpos($html, "\x1f" . "\x8b" . "\x08")) { 46 | $html = gzdecode($html); 47 | } 48 | 49 | 50 | $html = $this->parseHTML($html, $thing->url); 51 | 52 | // Discard failed parsings 53 | if ($html === false) { 54 | throw new \ErrorException('Readability'); 55 | } 56 | 57 | $html = $this->sanitizeHTML($html); 58 | $html = $this->signPost($html); 59 | $markdown = $this->buildMarkdown($html); 60 | 61 | /* 62 | * Some newspapers like to mix every possible encoding out there making a mess after the processing 63 | * We need to force everything into UTF8 no matter what original encoding we have. 64 | */ 65 | // Disabling for now 66 | // $markdown = Encoding::fixUTF8($markdown); 67 | 68 | $thing->markdown = $markdown; 69 | $thing->status = empleadoEstatal::THING_FETCHED; 70 | $thing->tries = 0; 71 | 72 | } catch (\ErrorException $e) { 73 | empleadoEstatal::$log->addInfo(sprintf('FetchWorker: Failed to parse in Readability. Thing: %s. URL: %s', $thing->thing, $thing->url)); 74 | $thing->info = 'Failed to parse in Readability'; 75 | $thing->status = empleadoEstatal::THING_REJECTED; 76 | } catch (\Exception $e) { 77 | empleadoEstatal::$log->addNotice(sprintf('FetchWorker: Failed to get newspaper (try no %s): %s. URL: %s', $thing->tries, $e->getMessage(), $thing->url)); 78 | $thing->info = substr($e->getMessage(), 0, 254); 79 | } finally { 80 | try { 81 | $thing->save(); 82 | $this->checkLength($thing); 83 | } catch (QueryException $e) { 84 | // Catch any query errors for really weird markdown (5 bytes unicode that MySQL doesn't like) 85 | 86 | $thing->markdown = null; 87 | $thing->status = empleadoEstatal::THING_REJECTED; 88 | $thing->info = substr($e->getMessage(), 0, 254); 89 | empleadoEstatal::$log->addEmergency(sprintf('FetchWorker: Failed to save text to db (try no %s): %s. URL: %s', $thing->tries, $e->getMessage(), $thing->url)); 90 | 91 | // Pleeeease work this time :D 92 | $thing->save(); 93 | } 94 | } 95 | } 96 | } 97 | 98 | /** 99 | * Comments cannot exceed a certain amount of characters. Longer comments must be split in chained comments 100 | * 101 | * @param Post $thing 102 | */ 103 | private function checkLength(Post $thing) 104 | { 105 | if (mb_strlen($thing->markdown) > $this->config['max_length']) { 106 | $splits = []; 107 | $text = $thing->markdown; 108 | 109 | while (true) { 110 | if (mb_strlen($text) < $this->config['max_length']) { 111 | $splits[] = $text; 112 | break; 113 | } 114 | 115 | $newLine = mb_strrpos($text, "\n", -(mb_strlen($text)) + $this->config['max_length']); 116 | 117 | if ($newLine === false) { 118 | $thing->status = empleadoEstatal::THING_REJECTED; 119 | $thing->info = sprintf('Too long, impossible to split with current limits. Limit is %s.', $this->config['max_length']); 120 | $thing->save(); 121 | empleadoEstatal::$log->addAlert(sprintf('FetchWorker: Failed to split long post. Thing: %s, limit: %s, text length: %s', $thing->thing, $this->config['max_length'], mb_strlen($thing->markdown))); 122 | return; 123 | } 124 | 125 | $splits[] = mb_substr($text, 0, $newLine + 1) . "\n" . '> ***(continues in next comment)***'; 126 | $text = mb_substr($text, $newLine + 1); 127 | } 128 | 129 | $thing->markdown = array_shift($splits); 130 | $thing->save(); 131 | 132 | $parent_id = $thing->id; 133 | 134 | foreach ($splits as $split) { 135 | $post = $thing->replicate(['markdown']); 136 | $post->parent_id = $parent_id; 137 | $post->markdown = $split; 138 | $post->info = sprintf('Multicomment. Parent is %s.', $thing->thing); 139 | $post->save(); 140 | $parent_id = $post->id; 141 | } 142 | } 143 | } 144 | 145 | private function parseHTML($html, $url) 146 | { 147 | $readability = new Readability((new Configuration()) 148 | ->setOriginalURL($url) 149 | ->setSummonCthulhu(true) 150 | ->setFixRelativeURLs(true) 151 | ); 152 | 153 | try { 154 | $readability->parse($html); 155 | 156 | if (mb_strlen($readability->getContent()) < 1000) { 157 | throw new ParseException(); 158 | } 159 | } catch (ParseException $e) { 160 | return false; 161 | } 162 | 163 | if ($readability->getImage()) { 164 | $image = sprintf('

%s



', $readability->getImage(), htmlspecialchars($readability->getTitle())); 165 | } else { 166 | $image = sprintf('

%s



', htmlspecialchars($readability->getTitle())); 167 | } 168 | 169 | return $image . $readability->getContent(); 170 | } 171 | 172 | private function signPost($html) 173 | { 174 | return $html . "


" . $this->config['signature']; 175 | } 176 | 177 | private function sanitizeHTML($html) 178 | { 179 | $html = $this->solveURLShorteners($html); 180 | 181 | // Eliminar los mails del texto asi reddit no se pone la gorra 182 | $html = preg_replace_callback('/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/i', function ($match) { 183 | return str_replace('@', ' at ', $match[0]); 184 | }, $html); 185 | 186 | // Envolviendo en blockquote el asunto para triggerear la regla css que oculta el texto 187 | $html = '
' . $html . '
' . "\n"; 188 | 189 | return $html; 190 | } 191 | 192 | private function solveURLShorteners($html) 193 | { 194 | $dom = new DOMDocument('1.0', 'utf-8'); 195 | $dom->loadHTML('' . $html); 196 | $dom->encoding = 'utf-8'; 197 | 198 | $links = $dom->getElementsByTagName('a'); 199 | 200 | foreach ($links as $i) { 201 | 202 | $link = $i->getAttribute("href"); 203 | if (in_array(parse_url($link, PHP_URL_HOST), $this->config['url_shorteners'])) { 204 | $headers = get_headers($link); 205 | 206 | $headers = array_filter($headers, function ($key) { 207 | return (strpos(strtolower($key), 'location:') !== false && strlen($key) > 10) ? true : false; 208 | }); 209 | 210 | $finalURL = substr(end($headers), 10); 211 | $i->setAttribute('href', $finalURL); 212 | $i->nodeValue = $finalURL; 213 | } 214 | } 215 | 216 | return str_ireplace('', '', $dom->C14N()); 217 | } 218 | 219 | private function buildMarkdown($html) 220 | { 221 | $converter = new HtmlConverter([ 222 | 'strip_tags' => true, 223 | 'header_style' => 'atx' 224 | ]); 225 | 226 | $markdown = $converter->convert($html); 227 | 228 | // Agregar la marca de markdown para hacer el hover de css 229 | 230 | $markdown = "##### \n\n###### \n\n#### \n\n" . $markdown; 231 | 232 | return $markdown; 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /app/public/bootstrap.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.7 (http://getbootstrap.com) 3 | * Copyright 2011-2017 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | /*! 8 | * Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=4ed1a4fc01a97503d1026e113b7703c0) 9 | * Config saved to config.json and https://gist.github.com/4ed1a4fc01a97503d1026e113b7703c0 10 | *//*! 11 | * Bootstrap v3.3.7 (http://getbootstrap.com) 12 | * Copyright 2011-2016 Twitter, Inc. 13 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 14 | *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:hover,a:focus{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover,a.text-primary:focus{color:#286090}.text-success{color:#3c763d}a.text-success:hover,a.text-success:focus{color:#2b542c}.text-info{color:#31708f}a.text-info:hover,a.text-info:focus{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover,a.text-warning:focus{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover,a.text-danger:focus{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover,a.bg-primary:focus{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover,a.bg-success:focus{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover,a.bg-info:focus{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover,a.bg-warning:focus{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover,a.bg-danger:focus{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:0.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{border:0;background-color:transparent}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:34px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:30px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:46px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0;min-height:34px}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:focus,.btn-default.focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#fff;background-color:#398439;border-color:#255625}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:focus,.btn-warning.focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#337ab7;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}} -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "b28564c1561c52e55c4cd696e0a22d05", 8 | "packages": [ 9 | { 10 | "name": "andreskrey/readability.php", 11 | "version": "v2.0.1", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/andreskrey/readability.php.git", 15 | "reference": "23f21756562adbd04c172d14995802030bf81595" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/andreskrey/readability.php/zipball/23f21756562adbd04c172d14995802030bf81595", 20 | "reference": "23f21756562adbd04c172d14995802030bf81595", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "ext-dom": "*", 25 | "ext-mbstring": "*", 26 | "ext-xml": "*", 27 | "php": ">=7.0.0", 28 | "psr/log": "^1.0" 29 | }, 30 | "require-dev": { 31 | "monolog/monolog": "^1.24", 32 | "phpunit/phpunit": "^6.5" 33 | }, 34 | "suggest": { 35 | "monolog/monolog": "Allow logging debug information" 36 | }, 37 | "type": "library", 38 | "autoload": { 39 | "psr-4": { 40 | "andreskrey\\Readability\\": "src/" 41 | } 42 | }, 43 | "notification-url": "https://packagist.org/downloads/", 44 | "license": [ 45 | "Apache-2.0" 46 | ], 47 | "authors": [ 48 | { 49 | "name": "Andres Rey", 50 | "email": "andreskrey@gmail.com", 51 | "role": "Lead Developer" 52 | } 53 | ], 54 | "description": "A PHP port of Readability.js", 55 | "homepage": "https://github.com/andreskrey/readability", 56 | "keywords": [ 57 | "html", 58 | "readability" 59 | ], 60 | "time": "2018-11-27T19:33:56+00:00" 61 | }, 62 | { 63 | "name": "doctrine/inflector", 64 | "version": "v1.1.0", 65 | "source": { 66 | "type": "git", 67 | "url": "https://github.com/doctrine/inflector.git", 68 | "reference": "90b2128806bfde671b6952ab8bea493942c1fdae" 69 | }, 70 | "dist": { 71 | "type": "zip", 72 | "url": "https://api.github.com/repos/doctrine/inflector/zipball/90b2128806bfde671b6952ab8bea493942c1fdae", 73 | "reference": "90b2128806bfde671b6952ab8bea493942c1fdae", 74 | "shasum": "" 75 | }, 76 | "require": { 77 | "php": ">=5.3.2" 78 | }, 79 | "require-dev": { 80 | "phpunit/phpunit": "4.*" 81 | }, 82 | "type": "library", 83 | "extra": { 84 | "branch-alias": { 85 | "dev-master": "1.1.x-dev" 86 | } 87 | }, 88 | "autoload": { 89 | "psr-0": { 90 | "Doctrine\\Common\\Inflector\\": "lib/" 91 | } 92 | }, 93 | "notification-url": "https://packagist.org/downloads/", 94 | "license": [ 95 | "MIT" 96 | ], 97 | "authors": [ 98 | { 99 | "name": "Roman Borschel", 100 | "email": "roman@code-factory.org" 101 | }, 102 | { 103 | "name": "Benjamin Eberlei", 104 | "email": "kontakt@beberlei.de" 105 | }, 106 | { 107 | "name": "Guilherme Blanco", 108 | "email": "guilhermeblanco@gmail.com" 109 | }, 110 | { 111 | "name": "Jonathan Wage", 112 | "email": "jonwage@gmail.com" 113 | }, 114 | { 115 | "name": "Johannes Schmitt", 116 | "email": "schmittjoh@gmail.com" 117 | } 118 | ], 119 | "description": "Common String Manipulations with regard to casing and singular/plural rules.", 120 | "homepage": "http://www.doctrine-project.org", 121 | "keywords": [ 122 | "inflection", 123 | "pluralize", 124 | "singularize", 125 | "string" 126 | ], 127 | "time": "2015-11-06T14:35:42+00:00" 128 | }, 129 | { 130 | "name": "guzzlehttp/guzzle", 131 | "version": "6.2.3", 132 | "source": { 133 | "type": "git", 134 | "url": "https://github.com/guzzle/guzzle.git", 135 | "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006" 136 | }, 137 | "dist": { 138 | "type": "zip", 139 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/8d6c6cc55186db87b7dc5009827429ba4e9dc006", 140 | "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006", 141 | "shasum": "" 142 | }, 143 | "require": { 144 | "guzzlehttp/promises": "^1.0", 145 | "guzzlehttp/psr7": "^1.4", 146 | "php": ">=5.5" 147 | }, 148 | "require-dev": { 149 | "ext-curl": "*", 150 | "phpunit/phpunit": "^4.0", 151 | "psr/log": "^1.0" 152 | }, 153 | "type": "library", 154 | "extra": { 155 | "branch-alias": { 156 | "dev-master": "6.2-dev" 157 | } 158 | }, 159 | "autoload": { 160 | "files": [ 161 | "src/functions_include.php" 162 | ], 163 | "psr-4": { 164 | "GuzzleHttp\\": "src/" 165 | } 166 | }, 167 | "notification-url": "https://packagist.org/downloads/", 168 | "license": [ 169 | "MIT" 170 | ], 171 | "authors": [ 172 | { 173 | "name": "Michael Dowling", 174 | "email": "mtdowling@gmail.com", 175 | "homepage": "https://github.com/mtdowling" 176 | } 177 | ], 178 | "description": "Guzzle is a PHP HTTP client library", 179 | "homepage": "http://guzzlephp.org/", 180 | "keywords": [ 181 | "client", 182 | "curl", 183 | "framework", 184 | "http", 185 | "http client", 186 | "rest", 187 | "web service" 188 | ], 189 | "time": "2017-02-28T22:50:30+00:00" 190 | }, 191 | { 192 | "name": "guzzlehttp/promises", 193 | "version": "v1.3.1", 194 | "source": { 195 | "type": "git", 196 | "url": "https://github.com/guzzle/promises.git", 197 | "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" 198 | }, 199 | "dist": { 200 | "type": "zip", 201 | "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", 202 | "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", 203 | "shasum": "" 204 | }, 205 | "require": { 206 | "php": ">=5.5.0" 207 | }, 208 | "require-dev": { 209 | "phpunit/phpunit": "^4.0" 210 | }, 211 | "type": "library", 212 | "extra": { 213 | "branch-alias": { 214 | "dev-master": "1.4-dev" 215 | } 216 | }, 217 | "autoload": { 218 | "psr-4": { 219 | "GuzzleHttp\\Promise\\": "src/" 220 | }, 221 | "files": [ 222 | "src/functions_include.php" 223 | ] 224 | }, 225 | "notification-url": "https://packagist.org/downloads/", 226 | "license": [ 227 | "MIT" 228 | ], 229 | "authors": [ 230 | { 231 | "name": "Michael Dowling", 232 | "email": "mtdowling@gmail.com", 233 | "homepage": "https://github.com/mtdowling" 234 | } 235 | ], 236 | "description": "Guzzle promises library", 237 | "keywords": [ 238 | "promise" 239 | ], 240 | "time": "2016-12-20T10:07:11+00:00" 241 | }, 242 | { 243 | "name": "guzzlehttp/psr7", 244 | "version": "1.4.2", 245 | "source": { 246 | "type": "git", 247 | "url": "https://github.com/guzzle/psr7.git", 248 | "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" 249 | }, 250 | "dist": { 251 | "type": "zip", 252 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", 253 | "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", 254 | "shasum": "" 255 | }, 256 | "require": { 257 | "php": ">=5.4.0", 258 | "psr/http-message": "~1.0" 259 | }, 260 | "provide": { 261 | "psr/http-message-implementation": "1.0" 262 | }, 263 | "require-dev": { 264 | "phpunit/phpunit": "~4.0" 265 | }, 266 | "type": "library", 267 | "extra": { 268 | "branch-alias": { 269 | "dev-master": "1.4-dev" 270 | } 271 | }, 272 | "autoload": { 273 | "psr-4": { 274 | "GuzzleHttp\\Psr7\\": "src/" 275 | }, 276 | "files": [ 277 | "src/functions_include.php" 278 | ] 279 | }, 280 | "notification-url": "https://packagist.org/downloads/", 281 | "license": [ 282 | "MIT" 283 | ], 284 | "authors": [ 285 | { 286 | "name": "Michael Dowling", 287 | "email": "mtdowling@gmail.com", 288 | "homepage": "https://github.com/mtdowling" 289 | }, 290 | { 291 | "name": "Tobias Schultze", 292 | "homepage": "https://github.com/Tobion" 293 | } 294 | ], 295 | "description": "PSR-7 message implementation that also provides common utility methods", 296 | "keywords": [ 297 | "http", 298 | "message", 299 | "request", 300 | "response", 301 | "stream", 302 | "uri", 303 | "url" 304 | ], 305 | "time": "2017-03-20T17:10:46+00:00" 306 | }, 307 | { 308 | "name": "illuminate/container", 309 | "version": "v5.4.19", 310 | "source": { 311 | "type": "git", 312 | "url": "https://github.com/illuminate/container.git", 313 | "reference": "50aa19491d478edd907d1f67e0928944e8b2dcb5" 314 | }, 315 | "dist": { 316 | "type": "zip", 317 | "url": "https://api.github.com/repos/illuminate/container/zipball/50aa19491d478edd907d1f67e0928944e8b2dcb5", 318 | "reference": "50aa19491d478edd907d1f67e0928944e8b2dcb5", 319 | "shasum": "" 320 | }, 321 | "require": { 322 | "illuminate/contracts": "5.4.*", 323 | "php": ">=5.6.4" 324 | }, 325 | "type": "library", 326 | "extra": { 327 | "branch-alias": { 328 | "dev-master": "5.4-dev" 329 | } 330 | }, 331 | "autoload": { 332 | "psr-4": { 333 | "Illuminate\\Container\\": "" 334 | } 335 | }, 336 | "notification-url": "https://packagist.org/downloads/", 337 | "license": [ 338 | "MIT" 339 | ], 340 | "authors": [ 341 | { 342 | "name": "Taylor Otwell", 343 | "email": "taylor@laravel.com" 344 | } 345 | ], 346 | "description": "The Illuminate Container package.", 347 | "homepage": "https://laravel.com", 348 | "time": "2017-04-16T13:32:45+00:00" 349 | }, 350 | { 351 | "name": "illuminate/contracts", 352 | "version": "v5.4.19", 353 | "source": { 354 | "type": "git", 355 | "url": "https://github.com/illuminate/contracts.git", 356 | "reference": "ab2825726bee46a67c8cc66789852189dbef74a9" 357 | }, 358 | "dist": { 359 | "type": "zip", 360 | "url": "https://api.github.com/repos/illuminate/contracts/zipball/ab2825726bee46a67c8cc66789852189dbef74a9", 361 | "reference": "ab2825726bee46a67c8cc66789852189dbef74a9", 362 | "shasum": "" 363 | }, 364 | "require": { 365 | "php": ">=5.6.4" 366 | }, 367 | "type": "library", 368 | "extra": { 369 | "branch-alias": { 370 | "dev-master": "5.4-dev" 371 | } 372 | }, 373 | "autoload": { 374 | "psr-4": { 375 | "Illuminate\\Contracts\\": "" 376 | } 377 | }, 378 | "notification-url": "https://packagist.org/downloads/", 379 | "license": [ 380 | "MIT" 381 | ], 382 | "authors": [ 383 | { 384 | "name": "Taylor Otwell", 385 | "email": "taylor@laravel.com" 386 | } 387 | ], 388 | "description": "The Illuminate Contracts package.", 389 | "homepage": "https://laravel.com", 390 | "time": "2017-03-29T13:17:47+00:00" 391 | }, 392 | { 393 | "name": "illuminate/database", 394 | "version": "v5.4.19", 395 | "source": { 396 | "type": "git", 397 | "url": "https://github.com/illuminate/database.git", 398 | "reference": "890564c6b84bcb2b45d41d3da072fabf422c07f5" 399 | }, 400 | "dist": { 401 | "type": "zip", 402 | "url": "https://api.github.com/repos/illuminate/database/zipball/890564c6b84bcb2b45d41d3da072fabf422c07f5", 403 | "reference": "890564c6b84bcb2b45d41d3da072fabf422c07f5", 404 | "shasum": "" 405 | }, 406 | "require": { 407 | "illuminate/container": "5.4.*", 408 | "illuminate/contracts": "5.4.*", 409 | "illuminate/support": "5.4.*", 410 | "nesbot/carbon": "~1.20", 411 | "php": ">=5.6.4" 412 | }, 413 | "suggest": { 414 | "doctrine/dbal": "Required to rename columns and drop SQLite columns (~2.5).", 415 | "fzaninotto/faker": "Required to use the eloquent factory builder (~1.4).", 416 | "illuminate/console": "Required to use the database commands (5.4.*).", 417 | "illuminate/events": "Required to use the observers with Eloquent (5.4.*).", 418 | "illuminate/filesystem": "Required to use the migrations (5.4.*).", 419 | "illuminate/pagination": "Required to paginate the result set (5.4.*)." 420 | }, 421 | "type": "library", 422 | "extra": { 423 | "branch-alias": { 424 | "dev-master": "5.4-dev" 425 | } 426 | }, 427 | "autoload": { 428 | "psr-4": { 429 | "Illuminate\\Database\\": "" 430 | } 431 | }, 432 | "notification-url": "https://packagist.org/downloads/", 433 | "license": [ 434 | "MIT" 435 | ], 436 | "authors": [ 437 | { 438 | "name": "Taylor Otwell", 439 | "email": "taylor@laravel.com" 440 | } 441 | ], 442 | "description": "The Illuminate Database package.", 443 | "homepage": "https://laravel.com", 444 | "keywords": [ 445 | "database", 446 | "laravel", 447 | "orm", 448 | "sql" 449 | ], 450 | "time": "2017-04-11T22:53:18+00:00" 451 | }, 452 | { 453 | "name": "illuminate/support", 454 | "version": "v5.4.19", 455 | "source": { 456 | "type": "git", 457 | "url": "https://github.com/illuminate/support.git", 458 | "reference": "b8cb37e15331c59da51c8ee5838038baa22d7955" 459 | }, 460 | "dist": { 461 | "type": "zip", 462 | "url": "https://api.github.com/repos/illuminate/support/zipball/b8cb37e15331c59da51c8ee5838038baa22d7955", 463 | "reference": "b8cb37e15331c59da51c8ee5838038baa22d7955", 464 | "shasum": "" 465 | }, 466 | "require": { 467 | "doctrine/inflector": "~1.0", 468 | "ext-mbstring": "*", 469 | "illuminate/contracts": "5.4.*", 470 | "paragonie/random_compat": "~1.4|~2.0", 471 | "php": ">=5.6.4" 472 | }, 473 | "replace": { 474 | "tightenco/collect": "self.version" 475 | }, 476 | "suggest": { 477 | "illuminate/filesystem": "Required to use the composer class (5.2.*).", 478 | "symfony/process": "Required to use the composer class (~3.2).", 479 | "symfony/var-dumper": "Required to use the dd function (~3.2)." 480 | }, 481 | "type": "library", 482 | "extra": { 483 | "branch-alias": { 484 | "dev-master": "5.4-dev" 485 | } 486 | }, 487 | "autoload": { 488 | "psr-4": { 489 | "Illuminate\\Support\\": "" 490 | }, 491 | "files": [ 492 | "helpers.php" 493 | ] 494 | }, 495 | "notification-url": "https://packagist.org/downloads/", 496 | "license": [ 497 | "MIT" 498 | ], 499 | "authors": [ 500 | { 501 | "name": "Taylor Otwell", 502 | "email": "taylor@laravel.com" 503 | } 504 | ], 505 | "description": "The Illuminate Support package.", 506 | "homepage": "https://laravel.com", 507 | "time": "2017-04-09T14:34:57+00:00" 508 | }, 509 | { 510 | "name": "league/html-to-markdown", 511 | "version": "dev-dev-reddit-flavored-markdown", 512 | "source": { 513 | "type": "git", 514 | "url": "https://github.com/andreskrey/html-to-markdown.git", 515 | "reference": "1d868cf4b96cacce6adcc54e28b925b317579f06" 516 | }, 517 | "dist": { 518 | "type": "zip", 519 | "url": "https://api.github.com/repos/andreskrey/html-to-markdown/zipball/1d868cf4b96cacce6adcc54e28b925b317579f06", 520 | "reference": "1d868cf4b96cacce6adcc54e28b925b317579f06", 521 | "shasum": "" 522 | }, 523 | "require": { 524 | "ext-dom": "*", 525 | "ext-xml": "*", 526 | "php": ">=5.3.3" 527 | }, 528 | "require-dev": { 529 | "mikehaertl/php-shellcommand": "~1.1.0", 530 | "phpunit/phpunit": "4.*", 531 | "scrutinizer/ocular": "~1.1" 532 | }, 533 | "bin": [ 534 | "bin/html-to-markdown" 535 | ], 536 | "type": "library", 537 | "extra": { 538 | "branch-alias": { 539 | "dev-master": "4.4-dev" 540 | } 541 | }, 542 | "autoload": { 543 | "psr-4": { 544 | "League\\HTMLToMarkdown\\": "src/" 545 | } 546 | }, 547 | "autoload-dev": { 548 | "psr-4": { 549 | "League\\HTMLToMarkdown\\Test\\": "tests" 550 | } 551 | }, 552 | "license": [ 553 | "MIT" 554 | ], 555 | "authors": [ 556 | { 557 | "name": "Colin O'Dell", 558 | "email": "colinodell@gmail.com", 559 | "homepage": "http://www.colinodell.com", 560 | "role": "Lead Developer" 561 | }, 562 | { 563 | "name": "Nick Cernis", 564 | "email": "nick@cern.is", 565 | "homepage": "http://modernnerd.net", 566 | "role": "Original Author" 567 | } 568 | ], 569 | "description": "An HTML-to-markdown conversion helper for PHP", 570 | "homepage": "https://github.com/thephpleague/html-to-markdown", 571 | "keywords": [ 572 | "html", 573 | "markdown" 574 | ], 575 | "support": { 576 | "source": "https://github.com/andreskrey/html-to-markdown/tree/dev-reddit-flavored-markdown" 577 | }, 578 | "time": "2018-02-22T18:49:41+00:00" 579 | }, 580 | { 581 | "name": "league/oauth2-client", 582 | "version": "2.2.1", 583 | "source": { 584 | "type": "git", 585 | "url": "https://github.com/thephpleague/oauth2-client.git", 586 | "reference": "313250eab923e673a5c0c8f463f443ee79f4383f" 587 | }, 588 | "dist": { 589 | "type": "zip", 590 | "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/313250eab923e673a5c0c8f463f443ee79f4383f", 591 | "reference": "313250eab923e673a5c0c8f463f443ee79f4383f", 592 | "shasum": "" 593 | }, 594 | "require": { 595 | "guzzlehttp/guzzle": "^6.0", 596 | "paragonie/random_compat": "^1|^2", 597 | "php": ">=5.6.0" 598 | }, 599 | "require-dev": { 600 | "eloquent/liberator": "^2.0", 601 | "eloquent/phony": "^0.14.1", 602 | "jakub-onderka/php-parallel-lint": "~0.9", 603 | "phpunit/phpunit": "^5.0", 604 | "squizlabs/php_codesniffer": "^2.0" 605 | }, 606 | "type": "library", 607 | "extra": { 608 | "branch-alias": { 609 | "dev-2.x": "2.0.x-dev" 610 | } 611 | }, 612 | "autoload": { 613 | "psr-4": { 614 | "League\\OAuth2\\Client\\": "src/" 615 | } 616 | }, 617 | "notification-url": "https://packagist.org/downloads/", 618 | "license": [ 619 | "MIT" 620 | ], 621 | "authors": [ 622 | { 623 | "name": "Alex Bilbie", 624 | "email": "hello@alexbilbie.com", 625 | "homepage": "http://www.alexbilbie.com", 626 | "role": "Developer" 627 | }, 628 | { 629 | "name": "Woody Gilk", 630 | "homepage": "https://github.com/shadowhand", 631 | "role": "Contributor" 632 | } 633 | ], 634 | "description": "OAuth 2.0 Client Library", 635 | "keywords": [ 636 | "Authentication", 637 | "SSO", 638 | "authorization", 639 | "identity", 640 | "idp", 641 | "oauth", 642 | "oauth2", 643 | "single sign on" 644 | ], 645 | "time": "2017-04-25T14:43:14+00:00" 646 | }, 647 | { 648 | "name": "monolog/monolog", 649 | "version": "1.22.1", 650 | "source": { 651 | "type": "git", 652 | "url": "https://github.com/Seldaek/monolog.git", 653 | "reference": "1e044bc4b34e91743943479f1be7a1d5eb93add0" 654 | }, 655 | "dist": { 656 | "type": "zip", 657 | "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1e044bc4b34e91743943479f1be7a1d5eb93add0", 658 | "reference": "1e044bc4b34e91743943479f1be7a1d5eb93add0", 659 | "shasum": "" 660 | }, 661 | "require": { 662 | "php": ">=5.3.0", 663 | "psr/log": "~1.0" 664 | }, 665 | "provide": { 666 | "psr/log-implementation": "1.0.0" 667 | }, 668 | "require-dev": { 669 | "aws/aws-sdk-php": "^2.4.9 || ^3.0", 670 | "doctrine/couchdb": "~1.0@dev", 671 | "graylog2/gelf-php": "~1.0", 672 | "jakub-onderka/php-parallel-lint": "0.9", 673 | "php-amqplib/php-amqplib": "~2.4", 674 | "php-console/php-console": "^3.1.3", 675 | "phpunit/phpunit": "~4.5", 676 | "phpunit/phpunit-mock-objects": "2.3.0", 677 | "ruflin/elastica": ">=0.90 <3.0", 678 | "sentry/sentry": "^0.13", 679 | "swiftmailer/swiftmailer": "~5.3" 680 | }, 681 | "suggest": { 682 | "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", 683 | "doctrine/couchdb": "Allow sending log messages to a CouchDB server", 684 | "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", 685 | "ext-mongo": "Allow sending log messages to a MongoDB server", 686 | "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", 687 | "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", 688 | "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", 689 | "php-console/php-console": "Allow sending log messages to Google Chrome", 690 | "rollbar/rollbar": "Allow sending log messages to Rollbar", 691 | "ruflin/elastica": "Allow sending log messages to an Elastic Search server", 692 | "sentry/sentry": "Allow sending log messages to a Sentry server" 693 | }, 694 | "type": "library", 695 | "extra": { 696 | "branch-alias": { 697 | "dev-master": "2.0.x-dev" 698 | } 699 | }, 700 | "autoload": { 701 | "psr-4": { 702 | "Monolog\\": "src/Monolog" 703 | } 704 | }, 705 | "notification-url": "https://packagist.org/downloads/", 706 | "license": [ 707 | "MIT" 708 | ], 709 | "authors": [ 710 | { 711 | "name": "Jordi Boggiano", 712 | "email": "j.boggiano@seld.be", 713 | "homepage": "http://seld.be" 714 | } 715 | ], 716 | "description": "Sends your logs to files, sockets, inboxes, databases and various web services", 717 | "homepage": "http://github.com/Seldaek/monolog", 718 | "keywords": [ 719 | "log", 720 | "logging", 721 | "psr-3" 722 | ], 723 | "time": "2017-03-13T07:08:03+00:00" 724 | }, 725 | { 726 | "name": "neitanod/forceutf8", 727 | "version": "v2.0.1", 728 | "source": { 729 | "type": "git", 730 | "url": "https://github.com/neitanod/forceutf8.git", 731 | "reference": "47c883ab2739e7938a8bb0bfd1c29d48c88858de" 732 | }, 733 | "dist": { 734 | "type": "zip", 735 | "url": "https://api.github.com/repos/neitanod/forceutf8/zipball/47c883ab2739e7938a8bb0bfd1c29d48c88858de", 736 | "reference": "47c883ab2739e7938a8bb0bfd1c29d48c88858de", 737 | "shasum": "" 738 | }, 739 | "require": { 740 | "php": ">=5.3.0" 741 | }, 742 | "type": "library", 743 | "autoload": { 744 | "psr-0": { 745 | "ForceUTF8\\": "src/" 746 | } 747 | }, 748 | "notification-url": "https://packagist.org/downloads/", 749 | "authors": [ 750 | { 751 | "name": "Sebastián Grignoli", 752 | "email": "grignoli@gmail.com" 753 | } 754 | ], 755 | "description": "PHP Class Encoding featuring popular Encoding::toUTF8() function --formerly known as forceUTF8()-- that fixes mixed encoded strings.", 756 | "homepage": "https://github.com/neitanod/forceutf8", 757 | "time": "2017-05-22T18:50:57+00:00" 758 | }, 759 | { 760 | "name": "nesbot/carbon", 761 | "version": "1.22.1", 762 | "source": { 763 | "type": "git", 764 | "url": "https://github.com/briannesbitt/Carbon.git", 765 | "reference": "7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc" 766 | }, 767 | "dist": { 768 | "type": "zip", 769 | "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc", 770 | "reference": "7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc", 771 | "shasum": "" 772 | }, 773 | "require": { 774 | "php": ">=5.3.0", 775 | "symfony/translation": "~2.6 || ~3.0" 776 | }, 777 | "require-dev": { 778 | "friendsofphp/php-cs-fixer": "~2", 779 | "phpunit/phpunit": "~4.0 || ~5.0" 780 | }, 781 | "type": "library", 782 | "extra": { 783 | "branch-alias": { 784 | "dev-master": "1.23-dev" 785 | } 786 | }, 787 | "autoload": { 788 | "psr-4": { 789 | "Carbon\\": "src/Carbon/" 790 | } 791 | }, 792 | "notification-url": "https://packagist.org/downloads/", 793 | "license": [ 794 | "MIT" 795 | ], 796 | "authors": [ 797 | { 798 | "name": "Brian Nesbitt", 799 | "email": "brian@nesbot.com", 800 | "homepage": "http://nesbot.com" 801 | } 802 | ], 803 | "description": "A simple API extension for DateTime.", 804 | "homepage": "http://carbon.nesbot.com", 805 | "keywords": [ 806 | "date", 807 | "datetime", 808 | "time" 809 | ], 810 | "time": "2017-01-16T07:55:07+00:00" 811 | }, 812 | { 813 | "name": "paragonie/random_compat", 814 | "version": "v2.0.10", 815 | "source": { 816 | "type": "git", 817 | "url": "https://github.com/paragonie/random_compat.git", 818 | "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d" 819 | }, 820 | "dist": { 821 | "type": "zip", 822 | "url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d", 823 | "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d", 824 | "shasum": "" 825 | }, 826 | "require": { 827 | "php": ">=5.2.0" 828 | }, 829 | "require-dev": { 830 | "phpunit/phpunit": "4.*|5.*" 831 | }, 832 | "suggest": { 833 | "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." 834 | }, 835 | "type": "library", 836 | "autoload": { 837 | "files": [ 838 | "lib/random.php" 839 | ] 840 | }, 841 | "notification-url": "https://packagist.org/downloads/", 842 | "license": [ 843 | "MIT" 844 | ], 845 | "authors": [ 846 | { 847 | "name": "Paragon Initiative Enterprises", 848 | "email": "security@paragonie.com", 849 | "homepage": "https://paragonie.com" 850 | } 851 | ], 852 | "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", 853 | "keywords": [ 854 | "csprng", 855 | "pseudorandom", 856 | "random" 857 | ], 858 | "time": "2017-03-13T16:27:32+00:00" 859 | }, 860 | { 861 | "name": "psr/http-message", 862 | "version": "1.0.1", 863 | "source": { 864 | "type": "git", 865 | "url": "https://github.com/php-fig/http-message.git", 866 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" 867 | }, 868 | "dist": { 869 | "type": "zip", 870 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", 871 | "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", 872 | "shasum": "" 873 | }, 874 | "require": { 875 | "php": ">=5.3.0" 876 | }, 877 | "type": "library", 878 | "extra": { 879 | "branch-alias": { 880 | "dev-master": "1.0.x-dev" 881 | } 882 | }, 883 | "autoload": { 884 | "psr-4": { 885 | "Psr\\Http\\Message\\": "src/" 886 | } 887 | }, 888 | "notification-url": "https://packagist.org/downloads/", 889 | "license": [ 890 | "MIT" 891 | ], 892 | "authors": [ 893 | { 894 | "name": "PHP-FIG", 895 | "homepage": "http://www.php-fig.org/" 896 | } 897 | ], 898 | "description": "Common interface for HTTP messages", 899 | "homepage": "https://github.com/php-fig/http-message", 900 | "keywords": [ 901 | "http", 902 | "http-message", 903 | "psr", 904 | "psr-7", 905 | "request", 906 | "response" 907 | ], 908 | "time": "2016-08-06T14:39:51+00:00" 909 | }, 910 | { 911 | "name": "psr/log", 912 | "version": "1.0.2", 913 | "source": { 914 | "type": "git", 915 | "url": "https://github.com/php-fig/log.git", 916 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" 917 | }, 918 | "dist": { 919 | "type": "zip", 920 | "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 921 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 922 | "shasum": "" 923 | }, 924 | "require": { 925 | "php": ">=5.3.0" 926 | }, 927 | "type": "library", 928 | "extra": { 929 | "branch-alias": { 930 | "dev-master": "1.0.x-dev" 931 | } 932 | }, 933 | "autoload": { 934 | "psr-4": { 935 | "Psr\\Log\\": "Psr/Log/" 936 | } 937 | }, 938 | "notification-url": "https://packagist.org/downloads/", 939 | "license": [ 940 | "MIT" 941 | ], 942 | "authors": [ 943 | { 944 | "name": "PHP-FIG", 945 | "homepage": "http://www.php-fig.org/" 946 | } 947 | ], 948 | "description": "Common interface for logging libraries", 949 | "homepage": "https://github.com/php-fig/log", 950 | "keywords": [ 951 | "log", 952 | "psr", 953 | "psr-3" 954 | ], 955 | "time": "2016-10-10T12:19:37+00:00" 956 | }, 957 | { 958 | "name": "rtheunissen/oauth2-reddit", 959 | "version": "v2.0.2", 960 | "source": { 961 | "type": "git", 962 | "url": "https://github.com/rtheunissen/oauth2-reddit.git", 963 | "reference": "4a2401b045d0a1853e444544001754f2595a2e9b" 964 | }, 965 | "dist": { 966 | "type": "zip", 967 | "url": "https://api.github.com/repos/rtheunissen/oauth2-reddit/zipball/4a2401b045d0a1853e444544001754f2595a2e9b", 968 | "reference": "4a2401b045d0a1853e444544001754f2595a2e9b", 969 | "shasum": "" 970 | }, 971 | "require": { 972 | "league/oauth2-client": "^2.2", 973 | "php": ">=5.6.0" 974 | }, 975 | "require-dev": { 976 | "phpunit/phpunit": "^5.0" 977 | }, 978 | "type": "library", 979 | "autoload": { 980 | "psr-4": { 981 | "Rudolf\\OAuth2\\Client\\": "src", 982 | "Rudolf\\OAuth2\\Client\\Tests\\": "tests" 983 | } 984 | }, 985 | "notification-url": "https://packagist.org/downloads/", 986 | "license": [ 987 | "MIT" 988 | ], 989 | "authors": [ 990 | { 991 | "name": "Rudi Theunissen", 992 | "email": "rudolf.theunissen@gmail.com" 993 | } 994 | ], 995 | "description": "Reddit OAuth2 provider for league/oauth2-client", 996 | "time": "2017-04-23T16:49:08+00:00" 997 | }, 998 | { 999 | "name": "symfony/console", 1000 | "version": "v3.3.0", 1001 | "source": { 1002 | "type": "git", 1003 | "url": "https://github.com/symfony/console.git", 1004 | "reference": "c80e63f3f5e3a331bfc25e6e9332b10422eb9b05" 1005 | }, 1006 | "dist": { 1007 | "type": "zip", 1008 | "url": "https://api.github.com/repos/symfony/console/zipball/c80e63f3f5e3a331bfc25e6e9332b10422eb9b05", 1009 | "reference": "c80e63f3f5e3a331bfc25e6e9332b10422eb9b05", 1010 | "shasum": "" 1011 | }, 1012 | "require": { 1013 | "php": ">=5.5.9", 1014 | "symfony/debug": "~2.8|~3.0", 1015 | "symfony/polyfill-mbstring": "~1.0" 1016 | }, 1017 | "conflict": { 1018 | "symfony/dependency-injection": "<3.3" 1019 | }, 1020 | "require-dev": { 1021 | "psr/log": "~1.0", 1022 | "symfony/dependency-injection": "~3.3", 1023 | "symfony/event-dispatcher": "~2.8|~3.0", 1024 | "symfony/filesystem": "~2.8|~3.0", 1025 | "symfony/http-kernel": "~2.8|~3.0", 1026 | "symfony/process": "~2.8|~3.0" 1027 | }, 1028 | "suggest": { 1029 | "psr/log": "For using the console logger", 1030 | "symfony/event-dispatcher": "", 1031 | "symfony/filesystem": "", 1032 | "symfony/process": "" 1033 | }, 1034 | "type": "library", 1035 | "extra": { 1036 | "branch-alias": { 1037 | "dev-master": "3.3-dev" 1038 | } 1039 | }, 1040 | "autoload": { 1041 | "psr-4": { 1042 | "Symfony\\Component\\Console\\": "" 1043 | }, 1044 | "exclude-from-classmap": [ 1045 | "/Tests/" 1046 | ] 1047 | }, 1048 | "notification-url": "https://packagist.org/downloads/", 1049 | "license": [ 1050 | "MIT" 1051 | ], 1052 | "authors": [ 1053 | { 1054 | "name": "Fabien Potencier", 1055 | "email": "fabien@symfony.com" 1056 | }, 1057 | { 1058 | "name": "Symfony Community", 1059 | "homepage": "https://symfony.com/contributors" 1060 | } 1061 | ], 1062 | "description": "Symfony Console Component", 1063 | "homepage": "https://symfony.com", 1064 | "time": "2017-05-28T14:08:56+00:00" 1065 | }, 1066 | { 1067 | "name": "symfony/debug", 1068 | "version": "v3.3.0", 1069 | "source": { 1070 | "type": "git", 1071 | "url": "https://github.com/symfony/debug.git", 1072 | "reference": "ef5f19a7a68075a0bd05969a329ead3b0776fb7a" 1073 | }, 1074 | "dist": { 1075 | "type": "zip", 1076 | "url": "https://api.github.com/repos/symfony/debug/zipball/ef5f19a7a68075a0bd05969a329ead3b0776fb7a", 1077 | "reference": "ef5f19a7a68075a0bd05969a329ead3b0776fb7a", 1078 | "shasum": "" 1079 | }, 1080 | "require": { 1081 | "php": ">=5.5.9", 1082 | "psr/log": "~1.0" 1083 | }, 1084 | "conflict": { 1085 | "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" 1086 | }, 1087 | "require-dev": { 1088 | "symfony/http-kernel": "~2.8|~3.0" 1089 | }, 1090 | "type": "library", 1091 | "extra": { 1092 | "branch-alias": { 1093 | "dev-master": "3.3-dev" 1094 | } 1095 | }, 1096 | "autoload": { 1097 | "psr-4": { 1098 | "Symfony\\Component\\Debug\\": "" 1099 | }, 1100 | "exclude-from-classmap": [ 1101 | "/Tests/" 1102 | ] 1103 | }, 1104 | "notification-url": "https://packagist.org/downloads/", 1105 | "license": [ 1106 | "MIT" 1107 | ], 1108 | "authors": [ 1109 | { 1110 | "name": "Fabien Potencier", 1111 | "email": "fabien@symfony.com" 1112 | }, 1113 | { 1114 | "name": "Symfony Community", 1115 | "homepage": "https://symfony.com/contributors" 1116 | } 1117 | ], 1118 | "description": "Symfony Debug Component", 1119 | "homepage": "https://symfony.com", 1120 | "time": "2017-05-27T16:02:27+00:00" 1121 | }, 1122 | { 1123 | "name": "symfony/polyfill-mbstring", 1124 | "version": "v1.3.0", 1125 | "source": { 1126 | "type": "git", 1127 | "url": "https://github.com/symfony/polyfill-mbstring.git", 1128 | "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" 1129 | }, 1130 | "dist": { 1131 | "type": "zip", 1132 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", 1133 | "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", 1134 | "shasum": "" 1135 | }, 1136 | "require": { 1137 | "php": ">=5.3.3" 1138 | }, 1139 | "suggest": { 1140 | "ext-mbstring": "For best performance" 1141 | }, 1142 | "type": "library", 1143 | "extra": { 1144 | "branch-alias": { 1145 | "dev-master": "1.3-dev" 1146 | } 1147 | }, 1148 | "autoload": { 1149 | "psr-4": { 1150 | "Symfony\\Polyfill\\Mbstring\\": "" 1151 | }, 1152 | "files": [ 1153 | "bootstrap.php" 1154 | ] 1155 | }, 1156 | "notification-url": "https://packagist.org/downloads/", 1157 | "license": [ 1158 | "MIT" 1159 | ], 1160 | "authors": [ 1161 | { 1162 | "name": "Nicolas Grekas", 1163 | "email": "p@tchwork.com" 1164 | }, 1165 | { 1166 | "name": "Symfony Community", 1167 | "homepage": "https://symfony.com/contributors" 1168 | } 1169 | ], 1170 | "description": "Symfony polyfill for the Mbstring extension", 1171 | "homepage": "https://symfony.com", 1172 | "keywords": [ 1173 | "compatibility", 1174 | "mbstring", 1175 | "polyfill", 1176 | "portable", 1177 | "shim" 1178 | ], 1179 | "time": "2016-11-14T01:06:16+00:00" 1180 | }, 1181 | { 1182 | "name": "symfony/translation", 1183 | "version": "v3.3.0", 1184 | "source": { 1185 | "type": "git", 1186 | "url": "https://github.com/symfony/translation.git", 1187 | "reference": "dc3b2a0c6cfff60327ba1c043a82092735397543" 1188 | }, 1189 | "dist": { 1190 | "type": "zip", 1191 | "url": "https://api.github.com/repos/symfony/translation/zipball/dc3b2a0c6cfff60327ba1c043a82092735397543", 1192 | "reference": "dc3b2a0c6cfff60327ba1c043a82092735397543", 1193 | "shasum": "" 1194 | }, 1195 | "require": { 1196 | "php": ">=5.5.9", 1197 | "symfony/polyfill-mbstring": "~1.0" 1198 | }, 1199 | "conflict": { 1200 | "symfony/config": "<2.8", 1201 | "symfony/yaml": "<3.3" 1202 | }, 1203 | "require-dev": { 1204 | "psr/log": "~1.0", 1205 | "symfony/config": "~2.8|~3.0", 1206 | "symfony/intl": "^2.8.18|^3.2.5", 1207 | "symfony/yaml": "~3.3" 1208 | }, 1209 | "suggest": { 1210 | "psr/log": "To use logging capability in translator", 1211 | "symfony/config": "", 1212 | "symfony/yaml": "" 1213 | }, 1214 | "type": "library", 1215 | "extra": { 1216 | "branch-alias": { 1217 | "dev-master": "3.3-dev" 1218 | } 1219 | }, 1220 | "autoload": { 1221 | "psr-4": { 1222 | "Symfony\\Component\\Translation\\": "" 1223 | }, 1224 | "exclude-from-classmap": [ 1225 | "/Tests/" 1226 | ] 1227 | }, 1228 | "notification-url": "https://packagist.org/downloads/", 1229 | "license": [ 1230 | "MIT" 1231 | ], 1232 | "authors": [ 1233 | { 1234 | "name": "Fabien Potencier", 1235 | "email": "fabien@symfony.com" 1236 | }, 1237 | { 1238 | "name": "Symfony Community", 1239 | "homepage": "https://symfony.com/contributors" 1240 | } 1241 | ], 1242 | "description": "Symfony Translation Component", 1243 | "homepage": "https://symfony.com", 1244 | "time": "2017-05-22T07:42:36+00:00" 1245 | }, 1246 | { 1247 | "name": "symfony/yaml", 1248 | "version": "v3.3.0", 1249 | "source": { 1250 | "type": "git", 1251 | "url": "https://github.com/symfony/yaml.git", 1252 | "reference": "885db865f6b2b918404a1fae28f9ac640f71f994" 1253 | }, 1254 | "dist": { 1255 | "type": "zip", 1256 | "url": "https://api.github.com/repos/symfony/yaml/zipball/885db865f6b2b918404a1fae28f9ac640f71f994", 1257 | "reference": "885db865f6b2b918404a1fae28f9ac640f71f994", 1258 | "shasum": "" 1259 | }, 1260 | "require": { 1261 | "php": ">=5.5.9" 1262 | }, 1263 | "require-dev": { 1264 | "symfony/console": "~2.8|~3.0" 1265 | }, 1266 | "suggest": { 1267 | "symfony/console": "For validating YAML files using the lint command" 1268 | }, 1269 | "type": "library", 1270 | "extra": { 1271 | "branch-alias": { 1272 | "dev-master": "3.3-dev" 1273 | } 1274 | }, 1275 | "autoload": { 1276 | "psr-4": { 1277 | "Symfony\\Component\\Yaml\\": "" 1278 | }, 1279 | "exclude-from-classmap": [ 1280 | "/Tests/" 1281 | ] 1282 | }, 1283 | "notification-url": "https://packagist.org/downloads/", 1284 | "license": [ 1285 | "MIT" 1286 | ], 1287 | "authors": [ 1288 | { 1289 | "name": "Fabien Potencier", 1290 | "email": "fabien@symfony.com" 1291 | }, 1292 | { 1293 | "name": "Symfony Community", 1294 | "homepage": "https://symfony.com/contributors" 1295 | } 1296 | ], 1297 | "description": "Symfony Yaml Component", 1298 | "homepage": "https://symfony.com", 1299 | "time": "2017-05-28T10:56:20+00:00" 1300 | } 1301 | ], 1302 | "packages-dev": [], 1303 | "aliases": [ 1304 | { 1305 | "alias": "4.2", 1306 | "alias_normalized": "4.2.0.0", 1307 | "version": "dev-dev-reddit-flavored-markdown", 1308 | "package": "league/html-to-markdown" 1309 | } 1310 | ], 1311 | "minimum-stability": "stable", 1312 | "stability-flags": { 1313 | "league/html-to-markdown": 20 1314 | }, 1315 | "prefer-stable": false, 1316 | "prefer-lowest": false, 1317 | "platform": { 1318 | "ext-mbstring": "*" 1319 | }, 1320 | "platform-dev": [] 1321 | } 1322 | --------------------------------------------------------------------------------