diff --git a/app/Http/Controllers/SmsController.php b/app/Http/Controllers/SmsController.php
new file mode 100644
index 0000000..cb80579
--- /dev/null
+++ b/app/Http/Controllers/SmsController.php
@@ -0,0 +1,114 @@
+middleware('auth');
+ }
+
+ private function max_message_length($numbers) {
+ $max_name_length = 0;
+ foreach($numbers as $n) {
+ if(strlen($n->name) > $max_name_length) {
+ $max_name_length = strlen($n->name);
+ }
+ }
+ return 160 - $max_name_length - 1;
+ }
+
+ public function index() {
+ $this->authorize('admin');
+
+ $numbers = PhoneNumber::orderBy('name')->get();
+ $maxlen = $this->max_message_length($numbers);
+
+ return view('sms', [
+ 'numbers' => $numbers,
+ 'maxlen' => $maxlen
+ ]);
+ }
+
+ public function save(Request $request) {
+ $this->authorize('admin');
+
+ if(preg_match_all('/(.+)\s+([0-9\-]+)/', $request->input('input'), $matches)) {
+
+ $contacts = [];
+ $errors = [];
+ foreach($matches[1] as $i=>$name) {
+ if(preg_match('/^1?(\d{3})-?(\d{3})-?(\d{4})$/', $matches[2][$i], $pm)) {
+ $contacts[] = [trim($name), $pm[1].'-'.$pm[2].'-'.$pm[3]];
+ } else {
+ $errors[] = $matches[0][$i];
+ }
+ }
+
+ if(count($errors)) {
+ $request->session()->flash('status', 'danger');
+ $request->session()->flash('status-message', 'There was a problem with some of your entries. No numbers were changed. The lines below had errors:
'.implode('
', array_map('htmlspecialchars', $errors)));
+
+ } else {
+ DB::table('phone_numbers')->delete();
+ foreach($contacts as $c) {
+ $p = new PhoneNumber;
+ $p->name = $c[0];
+ $p->phone = $c[1];
+ $p->save();
+ }
+
+ $request->session()->flash('status', 'success');
+ $request->session()->flash('status-message', 'Phone numbers saved!');
+ }
+
+
+ } else {
+ $request->session()->flash('status', 'danger');
+ $request->session()->flash('status-message', 'Invalid input, phone numbers were not modified');
+ }
+
+ return redirect('sms');
+ }
+
+ public function send(Request $request) {
+ $this->authorize('admin');
+
+ $numbers = PhoneNumber::orderBy('name')->get();
+ $maxlen = $this->max_message_length($numbers);
+
+ if(strlen($request->input('text')) <= $maxlen) {
+
+ $client = new \Twilio\Rest\Client(env('TWILIO_SID'), env('TWILIO_TOKEN'));
+ foreach($numbers as $number) {
+ $text = $request->input('text');
+ $text = str_replace('{name}', $number->name, $text);
+ $message = $client->messages->create(
+ '+1'.str_replace('-','',$number->phone),
+ array(
+ 'from' => env('TWILIO_NUMBER'),
+ 'body' => $text
+ )
+ );
+ }
+
+ $request->session()->flash('status', 'success');
+ $request->session()->flash('status-message', 'Message was sent! It will take about 1 second per number to deliver all the messages!');
+ } else {
+ $request->session()->flash('status', 'danger');
+ $request->session()->flash('status-message', 'Your message was too long!');
+ }
+
+ return redirect('sms');
+ }
+
+}
diff --git a/app/PhoneNumber.php b/app/PhoneNumber.php
new file mode 100644
index 0000000..8ec586a
--- /dev/null
+++ b/app/PhoneNumber.php
@@ -0,0 +1,12 @@
+belongsTo('\App\User');
+ }
+}
diff --git a/composer.json b/composer.json
index 68a2542..4b58740 100644
--- a/composer.json
+++ b/composer.json
@@ -12,7 +12,8 @@
"mnabialek/laravel-sql-logger": "^1.1",
"predis/predis": "^1.1",
"pusher/pusher-php-server": "^2.6",
- "thujohn/twitter": "^2.2"
+ "thujohn/twitter": "^2.2",
+ "twilio/sdk": "^5.11"
},
"require-dev": {
"fzaninotto/faker": "~1.4",
diff --git a/composer.lock b/composer.lock
index 7024619..60908a8 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "content-hash": "5681db78f7fa8c08618795173764986e",
+ "content-hash": "41238565556ee0b0f7094b70d9cae03e",
"packages": [
{
"name": "dnoegel/php-xdg-base-dir",
@@ -2461,6 +2461,52 @@
"homepage": "https://github.com/tijsverkoyen/CssToInlineStyles",
"time": "2016-09-20T12:50:39+00:00"
},
+ {
+ "name": "twilio/sdk",
+ "version": "5.11.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/twilio/twilio-php.git",
+ "reference": "6887cc761df5b011bce5460ad643e846ad8a5548"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/twilio/twilio-php/zipball/6887cc761df5b011bce5460ad643e846ad8a5548",
+ "reference": "6887cc761df5b011bce5460ad643e846ad8a5548",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "apigen/apigen": "^4.1",
+ "phpunit/phpunit": "4.5.*"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Twilio\\": "Twilio/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Twilio API Team",
+ "email": "api@twilio.com"
+ }
+ ],
+ "description": "A PHP wrapper for Twilio's API",
+ "homepage": "http://github.com/twilio/twilio-php",
+ "keywords": [
+ "api",
+ "sms",
+ "twilio"
+ ],
+ "time": "2017-06-16T20:19:46+00:00"
+ },
{
"name": "vlucas/phpdotenv",
"version": "v2.4.0",
diff --git a/database/migrations/2017_07_08_032850_BulkSMS.php b/database/migrations/2017_07_08_032850_BulkSMS.php
new file mode 100644
index 0000000..5369007
--- /dev/null
+++ b/database/migrations/2017_07_08_032850_BulkSMS.php
@@ -0,0 +1,33 @@
+increments('id');
+ $table->timestamps();
+ $table->string('name', 255);
+ $table->string('phone', 255);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('phone_numbers');
+ }
+}
diff --git a/database/migrations/2017_07_08_033123_sms_log.php b/database/migrations/2017_07_08_033123_sms_log.php
new file mode 100644
index 0000000..360e2ea
--- /dev/null
+++ b/database/migrations/2017_07_08_033123_sms_log.php
@@ -0,0 +1,33 @@
+increments('id');
+ $table->timestamps();
+ $table->text('text');
+ $table->integer('user_id');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('sent_messages');
+ }
+}
diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php
index e6ab758..e14d723 100644
--- a/resources/views/layouts/app.blade.php
+++ b/resources/views/layouts/app.blade.php
@@ -39,8 +39,9 @@
@if(!Auth::guest())