├── .gitignore ├── README.md ├── android-app ├── .gitignore ├── .idea │ ├── .name │ ├── compiler.xml │ ├── copyright │ │ └── profiles_settings.xml │ ├── gradle.xml │ ├── misc.xml │ ├── modules.xml │ └── vcs.xml ├── android-app.iml ├── app │ ├── .gitignore │ ├── app.iml │ ├── build.gradle │ ├── libs │ │ ├── aws-android-sdk-core-2.2.1.jar │ │ ├── aws-android-sdk-ddb-2.2.1.jar │ │ ├── aws-android-sdk-ddb-mapper-2.2.1.jar │ │ └── aws-android-sdk-sqs-2.2.1.jar │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── rocks │ │ │ └── pocha │ │ │ └── sampleapp │ │ │ └── ApplicationTest.java │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── rocks │ │ │ └── pocha │ │ │ └── sampleapp │ │ │ ├── AwsCredentials.java.example │ │ │ ├── BaseActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── MessageService.java │ │ │ └── WakeUpReceiver.java │ │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── menu │ │ ├── menu_base.xml │ │ ├── menu_main.xml │ │ └── menu_message.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── aws_credentials.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── images ├── gcm-sent.png ├── message-pending.png ├── new-message-delivered.png ├── new-message-in-queue.png └── new-queue.png └── server-rails ├── .gitignore ├── Gemfile ├── Gemfile.lock ├── README.md ├── Rakefile ├── app ├── assets │ ├── images │ │ └── .keep │ ├── javascripts │ │ ├── application.js │ │ ├── apps.coffee │ │ ├── endpoints.coffee │ │ └── messages.coffee │ └── stylesheets │ │ ├── application.css │ │ ├── apps.scss │ │ ├── endpoints.scss │ │ ├── messages.scss │ │ └── scaffolds.scss ├── controllers │ ├── application_controller.rb │ ├── apps_controller.rb │ ├── concerns │ │ └── .keep │ ├── endpoints_controller.rb │ └── messages_controller.rb ├── helpers │ ├── application_helper.rb │ ├── apps_helper.rb │ ├── endpoints_helper.rb │ └── messages_helper.rb ├── mailers │ └── .keep ├── models │ ├── .keep │ ├── app.rb │ ├── concerns │ │ └── .keep │ └── message.rb └── views │ ├── apps │ ├── _form.html.erb │ ├── edit.html.erb │ ├── index.html.erb │ ├── index.json.jbuilder │ ├── new.html.erb │ ├── show.html.erb │ └── show.json.jbuilder │ ├── endpoints │ ├── deliver.html.erb │ └── register.html.erb │ ├── layouts │ └── application.html.erb │ └── messages │ ├── _form.html.erb │ ├── edit.html.erb │ ├── index.html.erb │ ├── index.json.jbuilder │ ├── new.html.erb │ ├── show.html.erb │ └── show.json.jbuilder ├── bin ├── bundle ├── rails ├── rake ├── setup └── spring ├── config.ru ├── config ├── app_environment_variables.rb.example ├── application.rb ├── boot.rb ├── daemons.yml ├── database.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── assets.rb │ ├── backtrace_silencers.rb │ ├── cookies_serializer.rb │ ├── filter_parameter_logging.rb │ ├── inflections.rb │ ├── mime_types.rb │ ├── session_store.rb │ └── wrap_parameters.rb ├── locales │ └── en.yml ├── routes.rb └── secrets.yml ├── db ├── migrate │ ├── 20150706135627_create_messages.rb │ └── 20150707073837_create_apps.rb ├── schema.rb └── seeds.rb ├── lib ├── assets │ └── .keep ├── daemons │ ├── daemons │ ├── monitor_queue.rb │ └── monitor_queue_ctl └── tasks │ └── .keep ├── log └── .keep ├── public ├── 404.html ├── 422.html ├── 500.html ├── favicon.ico └── robots.txt └── vendor └── assets ├── javascripts └── .keep └── stylesheets └── .keep /.gitignore: -------------------------------------------------------------------------------- 1 | credentials.csv 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Commu-SQS 2 | 3 | This project is to demonstrate how to use Amazon SQS for a guaranteed & fastest server -> (Android) client communication. Usually, people use GCM for such cases but GCM message tend to get delayed. 4 | 5 | Here, one queue per Android client is created on Amazon SQS. Server inserts data to the queue. On Android, there is a persistent background service that keeps listening for data on the queue. On getting data, it generates a notification. 6 | 7 | In the event of user force closing the app, the background service will get killed. A daemon as part of the server (located in `libs/daemones/monitor_queue.rb`) keeps scanning all the queues. On finding pending data that has not been fetched, the daemon sends a **wake up GCM push** to the device. The push is received by the broadcast receiver, which in turn brings the killed background service to life. 8 | 9 | Note - no data is being passed in the GCM push as it would only increase the *data-duplication-check* overhead at the Android app. 10 | 11 | On top of the wake up push, in the Android client, a `BaseActivity` is created which checks if the service is running & starts it. Ideally, all your Activities should extend BaseActivity so that the service status is checked whenever any Activity is loaded (lets say from a different GCM push). 12 | 13 | ### TO-DO 14 | 15 | I had plans to extend the service for upstream purpose (sending data from Android to server) but I am still in two-minds if this is the right approach. Ideally, `SyncAdapter` takes care of data transmission from client to server as it has inbuilt mechanism of checking when network connection is available etc. Comments on this are welcome. 16 | 17 | ### Setup 18 | 19 | #### Rails server 20 | 21 | Copy `config/app_environment_variables.rb.example` to `config/app_environment_variables.rb` & fill in the appropriate details. 22 | 23 | Deploy the rails app. Start the monitor\_queue as `rake daemon:monitor_queue:start`. Do `tail -f logs/*` to see all the logs. If the app is deployed on heroku, do `heroku logs -t`. 24 | 25 | For testing purpose, you may simply start the daemon as `ruby libs/daemon/monitor_queue.rb`. That way, you would know if the daemon is dying. There is a corner case when daemon dies when there are no queues. So start daemon once you have deployed the app. 26 | 27 | The server creates queues with prefix **test-** in development & **live-** in production environment. `Message.delete_queues` will delete all your queues. This is handy when you are resetting things to scratch in development environment. 28 | 29 | #### Android App 30 | 31 | 1. Import `android-app` directory in Android Studio. 32 | 2. Copy `AwsCredentials.java.example` as `AwsCredentials.java` & fill in the required details like AWS & GCM credentials. 33 | 3. Modify line 31 in MainActivity.java 34 | 35 | private static String SERVER_URL= "http://192.168.1.5:3000/"; 36 | 37 | 3. Deploy maadi (thats Kannada for *do it*) 38 | 39 | #### Seeing it in action 40 | 41 | On opening the app, you would see the app generating a random app id & gcm id. The same is being sent to the server. Refresh the server to see a new queue being created. 42 | 43 | ![New Queue on Server](images/new-queue.png) 44 | 45 | Now push a message to the queue, the message should immediately come to the app with a notification. 46 | 47 | 48 | 49 | 50 | 51 | 52 |
53 | 54 | Try force closing the app, create a new message & keep checking the daemon logs. There should be a GCM message that would be sent from the server to Android app, which will wake up the app & starts the background service. The app will then register the new message. 55 | 56 | 57 | ![Message pending to be sent on the server](images/message-pending.png) 58 | ![Logs showing GCM sent](images/gcm-sent.png) 59 | 60 | 61 | #### For your app 62 | 63 | You do not need to incorporate all of the server parts. Your own server could push the data to SQS. You can use my server as daemon that scans for data in your SQS queues that are unfetched & then sends GCM. 64 | 65 | The `app/controllers/endpoint_controllers.rb` & `lib/daemons/monitor_queue.rb` is important. The other Messages controller is just for the purpose of showing the whole stuff in action. 66 | 67 | From the app side, make sure you do a http call to my server when the app registers app & gcm id. The server stores it & uses the gcm id to send the GCM push. 68 | 69 | ## Attribution 70 | 71 | A large part of MessageService.java code in the Android app is taken from the Localoye Android app. I did this project while I was trying to evaluate to work with them. 72 | 73 | Let me know how you like it by dropping me a word at [@pocha](http://twitter.com/pocha) :-) 74 | -------------------------------------------------------------------------------- /android-app/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | /captures 8 | **/AwsCredentials.java 9 | -------------------------------------------------------------------------------- /android-app/.idea/.name: -------------------------------------------------------------------------------- 1 | android-app -------------------------------------------------------------------------------- /android-app/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | -------------------------------------------------------------------------------- /android-app/.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /android-app/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /android-app/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | Android API 19 Platform 27 | 28 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /android-app/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android-app/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android-app/android-app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /android-app/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /android-app/app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /android-app/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "21.1.2" 6 | 7 | defaultConfig { 8 | applicationId "rocks.pocha.sampleapp" 9 | minSdkVersion 9 10 | targetSdkVersion 22 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile 'com.android.support:appcompat-v7:22.2.0' 25 | compile 'com.pixplicity.easyprefs:library:1.5' 26 | compile 'com.jakewharton:butterknife:7.0.1' 27 | compile 'com.google.android.gms:play-services:3.1.+' 28 | compile 'com.android.support:cardview-v7:21.+' 29 | compile 'com.squareup.okhttp:okhttp:2.4.0' 30 | compile files('libs/aws-android-sdk-core-2.2.1.jar') 31 | compile files('libs/aws-android-sdk-ddb-2.2.1.jar') 32 | compile files('libs/aws-android-sdk-ddb-mapper-2.2.1.jar') 33 | compile files('libs/aws-android-sdk-sqs-2.2.1.jar') 34 | 35 | } 36 | -------------------------------------------------------------------------------- /android-app/app/libs/aws-android-sdk-core-2.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/android-app/app/libs/aws-android-sdk-core-2.2.1.jar -------------------------------------------------------------------------------- /android-app/app/libs/aws-android-sdk-ddb-2.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/android-app/app/libs/aws-android-sdk-ddb-2.2.1.jar -------------------------------------------------------------------------------- /android-app/app/libs/aws-android-sdk-ddb-mapper-2.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/android-app/app/libs/aws-android-sdk-ddb-mapper-2.2.1.jar -------------------------------------------------------------------------------- /android-app/app/libs/aws-android-sdk-sqs-2.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/android-app/app/libs/aws-android-sdk-sqs-2.2.1.jar -------------------------------------------------------------------------------- /android-app/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /opt/android-sdk-macosx/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /android-app/app/src/androidTest/java/rocks/pocha/sampleapp/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package rocks.pocha.sampleapp; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /android-app/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /android-app/app/src/main/java/rocks/pocha/sampleapp/AwsCredentials.java.example: -------------------------------------------------------------------------------- 1 | package rocks.pocha.sampleapp; 2 | 3 | /** 4 | * Created by pocha on 12/07/15. 5 | */ 6 | public class AwsCredentials { 7 | public final static String AWS_ACCESS_KEY = "xxxx"; 8 | public final static String AWS_SECRET_KEY = "xxxx"; 9 | public final static String AWS_REGION = "us-west-2"; 10 | public final static String GCM_REGISTRATION_ID = "xxx"; 11 | } 12 | -------------------------------------------------------------------------------- /android-app/app/src/main/java/rocks/pocha/sampleapp/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package rocks.pocha.sampleapp; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.ContextWrapper; 6 | import android.content.Intent; 7 | import android.os.Bundle; 8 | 9 | import com.pixplicity.easyprefs.library.Prefs; 10 | 11 | 12 | public class BaseActivity extends Activity { 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | new Prefs.Builder() 18 | .setContext(this) 19 | .setMode(ContextWrapper.MODE_PRIVATE) 20 | .setPrefsName(getPackageName()) 21 | .setUseDefaultSharedPreference(true) 22 | .build(); 23 | } 24 | 25 | @Override 26 | protected void onStart(){ 27 | super.onStart(); 28 | Context context = getApplicationContext(); 29 | context.startService(new Intent(context.getApplicationContext(), MessageService.class)); 30 | //check if service is alive, else start it 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /android-app/app/src/main/java/rocks/pocha/sampleapp/MainActivity.java: -------------------------------------------------------------------------------- 1 | package rocks.pocha.sampleapp; 2 | 3 | import android.app.ProgressDialog; 4 | import android.os.AsyncTask; 5 | import android.os.Bundle; 6 | import android.util.Log; 7 | import android.view.Menu; 8 | import android.view.MenuItem; 9 | import android.widget.TextView; 10 | 11 | import com.google.android.gms.gcm.GoogleCloudMessaging; 12 | import com.pixplicity.easyprefs.library.Prefs; 13 | import com.squareup.okhttp.OkHttpClient; 14 | import com.squareup.okhttp.Request; 15 | 16 | import java.util.Random; 17 | 18 | import butterknife.Bind; 19 | import butterknife.ButterKnife; 20 | 21 | public class MainActivity extends BaseActivity { 22 | @Bind(R.id.app_id) 23 | TextView appId; 24 | @Bind(R.id.gcm_id) 25 | TextView gcmId; 26 | @Bind(R.id.last_message) 27 | TextView lastMessage; 28 | 29 | String _appId, _gcmId; 30 | ProgressDialog progress; 31 | private static String SERVER_URL= "https://commu-sqs.herokuapp.com/"; 32 | private static String TAG="MainActivity"; 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | setContentView(R.layout.activity_main); 38 | ButterKnife.bind(this); 39 | Log.d(TAG, "app Id " + Prefs.getString("app_id", null)); 40 | Log.d(TAG, "gcm Id " + Prefs.getString("gcm_id", null)); 41 | 42 | _appId = Prefs.getString("app_id",null); 43 | _gcmId = Prefs.getString("gcm_id", null); 44 | 45 | if (_appId == null || _gcmId == null) { 46 | progress = ProgressDialog.show(MainActivity.this, "", "Initializing ..", true, false); 47 | new AsyncTask() { 48 | @Override 49 | protected Boolean doInBackground(Void... params) { 50 | 51 | if (_appId == null) { 52 | //generate app_id 53 | _appId = String.valueOf(new Random().nextInt(10000)); 54 | Prefs.putString("app_id", _appId); 55 | } 56 | 57 | 58 | if (_gcmId == null) { 59 | //register with gcm & get id 60 | Log.d(TAG, "GCM id null"); 61 | GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(getApplicationContext()); 62 | try { 63 | _gcmId = gcm.register(AwsCredentials.GCM_REGISTRATION_ID); 64 | Prefs.putString("gcm_id", _gcmId); 65 | 66 | String url = SERVER_URL + "/endpoints/register/" + _appId + "/" + _gcmId; 67 | OkHttpClient client = new OkHttpClient(); 68 | try { 69 | Request request = new Request.Builder() 70 | .url(url) 71 | .build(); 72 | 73 | client.newCall(request).execute(); 74 | 75 | } catch (Exception e) { 76 | Log.e("MainActivity", e.getMessage()); 77 | } 78 | 79 | } catch (Exception e) { 80 | _gcmId = "Error registering device for GCM"; 81 | Log.e("MainActivity", "Error while getting gcm id - " + e.getMessage()); 82 | } 83 | } 84 | return null; 85 | } 86 | 87 | @Override 88 | protected void onPostExecute(Boolean result) { 89 | progress.dismiss(); 90 | appId.setText(_appId); 91 | gcmId.setText(_gcmId); 92 | } 93 | }.execute(); 94 | } 95 | else { 96 | appId.setText(_appId); 97 | gcmId.setText(_gcmId); 98 | } 99 | 100 | if (getIntent().getStringExtra("message") != null) { 101 | String message = getIntent().getStringExtra("message"); 102 | lastMessage.setText(message); 103 | Prefs.putString("last_message", message); 104 | } 105 | else { 106 | lastMessage.setText(Prefs.getString("last_message","no last message found")); 107 | } 108 | 109 | } 110 | 111 | @Override 112 | public boolean onCreateOptionsMenu(Menu menu) { 113 | // Inflate the menu; this adds items to the action bar if it is present. 114 | getMenuInflater().inflate(R.menu.menu_main, menu); 115 | return true; 116 | } 117 | 118 | @Override 119 | public boolean onOptionsItemSelected(MenuItem item) { 120 | // Handle action bar item clicks here. The action bar will 121 | // automatically handle clicks on the Home/Up button, so long 122 | // as you specify a parent activity in AndroidManifest.xml. 123 | int id = item.getItemId(); 124 | 125 | //noinspection SimplifiableIfStatement 126 | if (id == R.id.action_settings) { 127 | return true; 128 | } 129 | 130 | return super.onOptionsItemSelected(item); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /android-app/app/src/main/java/rocks/pocha/sampleapp/MessageService.java: -------------------------------------------------------------------------------- 1 | package rocks.pocha.sampleapp; 2 | 3 | import android.app.NotificationManager; 4 | import android.app.PendingIntent; 5 | import android.app.Service; 6 | import android.content.Context; 7 | import android.content.ContextWrapper; 8 | import android.content.Intent; 9 | import android.media.RingtoneManager; 10 | import android.net.Uri; 11 | import android.os.AsyncTask; 12 | import android.os.IBinder; 13 | import android.support.v4.app.NotificationCompat; 14 | import android.util.Log; 15 | import android.widget.Toast; 16 | 17 | import com.amazonaws.ClientConfiguration; 18 | import com.amazonaws.auth.AWSCredentials; 19 | import com.amazonaws.auth.AWSCredentialsProvider; 20 | import com.amazonaws.auth.BasicAWSCredentials; 21 | import com.amazonaws.regions.Region; 22 | import com.amazonaws.regions.Regions; 23 | import com.amazonaws.services.sqs.AmazonSQSAsyncClient; 24 | import com.amazonaws.services.sqs.model.CreateQueueRequest; 25 | import com.amazonaws.services.sqs.model.CreateQueueResult; 26 | import com.amazonaws.services.sqs.model.DeleteMessageRequest; 27 | import com.amazonaws.services.sqs.model.GetQueueUrlResult; 28 | import com.amazonaws.services.sqs.model.Message; 29 | import com.amazonaws.services.sqs.model.QueueDoesNotExistException; 30 | import com.amazonaws.services.sqs.model.ReceiveMessageRequest; 31 | import com.amazonaws.services.sqs.model.ReceiveMessageResult; 32 | import com.pixplicity.easyprefs.library.Prefs; 33 | 34 | public class MessageService extends Service { 35 | private static boolean isServiceRunning = false; 36 | 37 | private final static String TAG = "AwsSqsManager"; 38 | 39 | private static BasicAWSCredentials credentials; 40 | private static ClientConfiguration config; 41 | private static AmazonSQSAsyncClient sqs; 42 | private static String queueUrl; 43 | 44 | public static final int NOTIFICATION_ID = 1; 45 | private NotificationManager mNotificationManager; 46 | 47 | public MessageService() { 48 | 49 | } 50 | 51 | public void onCreate(){ 52 | super.onCreate(); 53 | new Prefs.Builder() 54 | .setContext(this) 55 | .setMode(ContextWrapper.MODE_PRIVATE) 56 | .setPrefsName(getPackageName()) 57 | .setUseDefaultSharedPreference(true) 58 | .build(); 59 | 60 | } 61 | @Override 62 | public void onDestroy(){ 63 | super.onDestroy(); 64 | Log.d(TAG,"I am being destroyed. sob sob :-(. I will come back with venegance"); 65 | } 66 | 67 | @Override 68 | public IBinder onBind(Intent intent) { 69 | return null; 70 | } 71 | @Override 72 | public int onStartCommand(Intent intent, int flags, int startId) { 73 | try { 74 | Log.d("MessageService", "onStartCommand isServiceRunning = " + isServiceRunning); 75 | 76 | if (isServiceRunning == true) 77 | return START_STICKY; 78 | isServiceRunning = true; 79 | 80 | 81 | //start listening to the queue 82 | new AsyncTask() { //creating queue in background as it is not allowed in the main thread 83 | @Override 84 | protected Void doInBackground(Void... params) { 85 | 86 | credentials = new BasicAWSCredentials(AwsCredentials.AWS_ACCESS_KEY, AwsCredentials.AWS_SECRET_KEY); 87 | config = new ClientConfiguration(); 88 | config.setConnectionTimeout(60000); 89 | config.setSocketTimeout(60000); 90 | AWSCredentialsProvider acp = new AWSCredentialsProvider() { 91 | @Override 92 | public AWSCredentials getCredentials() { 93 | return credentials; 94 | } 95 | 96 | @Override 97 | public void refresh() { 98 | } 99 | }; 100 | sqs = new AmazonSQSAsyncClient(acp, config); 101 | sqs.setEndpoint("http://sqs." + AwsCredentials.AWS_REGION + ".amazonaws.com"); 102 | sqs.setRegion(Region.getRegion(Regions.fromName(AwsCredentials.AWS_REGION))); 103 | 104 | String appId = Prefs.getString("app_id", null); 105 | //This helps if AWS IP changes. JVM caches the IP address. 106 | java.security.Security.setProperty("networkaddress.cache.ttl", "60"); 107 | 108 | try { 109 | GetQueueUrlResult getQueueUrlResult = sqs.getQueueUrl("test-" + appId); 110 | queueUrl = getQueueUrlResult.getQueueUrl(); 111 | } 112 | catch (QueueDoesNotExistException e) { 113 | CreateQueueRequest createQueueRequest = new CreateQueueRequest(); 114 | createQueueRequest.addAttributesEntry("ReceiveMessageWaitTimeSeconds", "20"); 115 | createQueueRequest.addAttributesEntry("VisibilityTimeout", "10"); 116 | createQueueRequest.setQueueName("test-" + appId); 117 | CreateQueueResult result = sqs.createQueue(createQueueRequest); 118 | queueUrl = result.getQueueUrl(); 119 | } 120 | Log.d(TAG,"Queue url found - " + queueUrl ); 121 | 122 | 123 | ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(); 124 | receiveMessageRequest.setQueueUrl(queueUrl); 125 | receiveMessageRequest.setMaxNumberOfMessages(1); //get only one message 126 | 127 | try { 128 | while (true) { 129 | ReceiveMessageResult message = sqs.receiveMessage(receiveMessageRequest); 130 | for (Message m : message.getMessages()) { 131 | Log.d(TAG,"message received " + m.getBody()); 132 | showNotification(m.getBody()); 133 | DeleteMessageRequest request = new DeleteMessageRequest(queueUrl, m.getReceiptHandle()); 134 | sqs.deleteMessage(request); 135 | } 136 | Thread.sleep(1000); 137 | } 138 | }catch (Exception e){ 139 | //start this activity again 140 | e.printStackTrace(); 141 | //Log.e(TAG,"Error while fetching from SQS " + e.printStackTrace()); 142 | isServiceRunning = false; 143 | } 144 | return null; 145 | } 146 | @Override 147 | protected void onPostExecute(Void aVoid){ 148 | // do nothing 149 | } 150 | }.execute(); 151 | 152 | } catch (Exception e) { 153 | Toast.makeText(getApplicationContext(),"Probably wrong credentials in AwsCredentials.java", Toast.LENGTH_LONG); 154 | Log.d(TAG, e.getMessage()); 155 | } finally { 156 | return START_STICKY; 157 | } 158 | 159 | } 160 | 161 | private void showNotification(String message){ 162 | Log.d(TAG, "inside showNotification with message - " + message); 163 | Intent intent = new Intent(this, MainActivity.class); 164 | intent.putExtra("message",message); 165 | PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT); 166 | Uri uri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); 167 | long[] vibrate = {0,100,200,300}; 168 | NotificationCompat.Builder mBuilder = 169 | new NotificationCompat.Builder(this) 170 | .setSmallIcon(android.R.drawable.sym_def_app_icon) 171 | .setContentTitle("Hey You") 172 | .setStyle(new NotificationCompat.BigTextStyle().bigText(message)) 173 | .setContentText(message) 174 | .setContentIntent(contentIntent) 175 | .setAutoCancel(true) 176 | .setSound(uri) 177 | .setVibrate(vibrate); 178 | 179 | mNotificationManager = (NotificationManager) getApplicationContext().getSystemService 180 | (Context.NOTIFICATION_SERVICE); 181 | mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /android-app/app/src/main/java/rocks/pocha/sampleapp/WakeUpReceiver.java: -------------------------------------------------------------------------------- 1 | package rocks.pocha.sampleapp; 2 | 3 | import android.content.ComponentName; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.support.v4.content.WakefulBroadcastReceiver; 7 | import android.util.Log; 8 | 9 | public class WakeUpReceiver extends WakefulBroadcastReceiver { 10 | public WakeUpReceiver() { 11 | } 12 | 13 | @Override 14 | public void onReceive(Context context, Intent intent) { 15 | Log.d("WakeUpReceiver","dude, I am going to wake you up now"); 16 | ComponentName comp = new ComponentName(context.getPackageName(), MessageService.class.getName()); 17 | startWakefulService(context, (intent.setComponent(comp))); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /android-app/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 18 | 23 | 27 | 29 | 31 | 32 | 36 | 38 | 40 | 41 | 42 | 43 | 44 | 45 | 52 | 57 | 61 | 63 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /android-app/app/src/main/res/menu/menu_base.xml: -------------------------------------------------------------------------------- 1 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /android-app/app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /android-app/app/src/main/res/menu/menu_message.xml: -------------------------------------------------------------------------------- 1 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /android-app/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/android-app/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android-app/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/android-app/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android-app/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/android-app/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android-app/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/android-app/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android-app/app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /android-app/app/src/main/res/values/aws_credentials.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android-app/app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /android-app/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Commu-SQS 3 | 4 | Hello world! 5 | Settings 6 | BaseActivity 7 | MessageActivity 8 | 9 | -------------------------------------------------------------------------------- /android-app/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android-app/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.1.0' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /android-app/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /android-app/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/android-app/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android-app/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Apr 10 15:27:10 PDT 2013 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip 7 | -------------------------------------------------------------------------------- /android-app/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /android-app/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /android-app/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /images/gcm-sent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/images/gcm-sent.png -------------------------------------------------------------------------------- /images/message-pending.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/images/message-pending.png -------------------------------------------------------------------------------- /images/new-message-delivered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/images/new-message-delivered.png -------------------------------------------------------------------------------- /images/new-message-in-queue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/images/new-message-in-queue.png -------------------------------------------------------------------------------- /images/new-queue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/images/new-queue.png -------------------------------------------------------------------------------- /server-rails/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore the default SQLite database. 11 | /db/*.sqlite3 12 | /db/*.sqlite3-journal 13 | 14 | # Ignore all logfiles and tempfiles. 15 | /log/* 16 | !/log/.keep 17 | /tmp 18 | /config/app_environment_variables.rb 19 | -------------------------------------------------------------------------------- /server-rails/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'logging' 4 | gem 'gcm' 5 | gem 'aws-sdk', '~> 2' 6 | gem 'daemons-rails' 7 | 8 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 9 | gem 'rails', '4.2.1' 10 | # Use sqlite3 as the database for Active Record 11 | gem 'sqlite3' 12 | # Use SCSS for stylesheets 13 | gem 'sass-rails', '~> 5.0' 14 | # Use Uglifier as compressor for JavaScript assets 15 | gem 'uglifier', '>= 1.3.0' 16 | # Use CoffeeScript for .coffee assets and views 17 | gem 'coffee-rails', '~> 4.1.0' 18 | # See https://github.com/rails/execjs#readme for more supported runtimes 19 | # gem 'therubyracer', platforms: :ruby 20 | 21 | # Use jquery as the JavaScript library 22 | gem 'jquery-rails' 23 | # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks 24 | gem 'turbolinks' 25 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder 26 | gem 'jbuilder', '~> 2.0' 27 | # bundle exec rake doc:rails generates the API under doc/api. 28 | gem 'sdoc', '~> 0.4.0', group: :doc 29 | 30 | # Use ActiveModel has_secure_password 31 | # gem 'bcrypt', '~> 3.1.7' 32 | 33 | # Use Unicorn as the app server 34 | # gem 'unicorn' 35 | 36 | # Use Capistrano for deployment 37 | # gem 'capistrano-rails', group: :development 38 | 39 | group :development, :test do 40 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console 41 | gem 'byebug' 42 | 43 | # Access an IRB console on exception pages or by using <%= console %> in views 44 | gem 'web-console', '~> 2.0' 45 | 46 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring 47 | gem 'spring' 48 | end 49 | 50 | -------------------------------------------------------------------------------- /server-rails/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | actionmailer (4.2.1) 5 | actionpack (= 4.2.1) 6 | actionview (= 4.2.1) 7 | activejob (= 4.2.1) 8 | mail (~> 2.5, >= 2.5.4) 9 | rails-dom-testing (~> 1.0, >= 1.0.5) 10 | actionpack (4.2.1) 11 | actionview (= 4.2.1) 12 | activesupport (= 4.2.1) 13 | rack (~> 1.6) 14 | rack-test (~> 0.6.2) 15 | rails-dom-testing (~> 1.0, >= 1.0.5) 16 | rails-html-sanitizer (~> 1.0, >= 1.0.1) 17 | actionview (4.2.1) 18 | activesupport (= 4.2.1) 19 | builder (~> 3.1) 20 | erubis (~> 2.7.0) 21 | rails-dom-testing (~> 1.0, >= 1.0.5) 22 | rails-html-sanitizer (~> 1.0, >= 1.0.1) 23 | activejob (4.2.1) 24 | activesupport (= 4.2.1) 25 | globalid (>= 0.3.0) 26 | activemodel (4.2.1) 27 | activesupport (= 4.2.1) 28 | builder (~> 3.1) 29 | activerecord (4.2.1) 30 | activemodel (= 4.2.1) 31 | activesupport (= 4.2.1) 32 | arel (~> 6.0) 33 | activesupport (4.2.1) 34 | i18n (~> 0.7) 35 | json (~> 1.7, >= 1.7.7) 36 | minitest (~> 5.1) 37 | thread_safe (~> 0.3, >= 0.3.4) 38 | tzinfo (~> 1.1) 39 | arel (6.0.0) 40 | aws-sdk (2.1.2) 41 | aws-sdk-resources (= 2.1.2) 42 | aws-sdk-core (2.1.2) 43 | jmespath (~> 1.0) 44 | aws-sdk-resources (2.1.2) 45 | aws-sdk-core (= 2.1.2) 46 | binding_of_caller (0.7.2) 47 | debug_inspector (>= 0.0.1) 48 | builder (3.2.2) 49 | byebug (5.0.0) 50 | columnize (= 0.9.0) 51 | coffee-rails (4.1.0) 52 | coffee-script (>= 2.2.0) 53 | railties (>= 4.0.0, < 5.0) 54 | coffee-script (2.4.1) 55 | coffee-script-source 56 | execjs 57 | coffee-script-source (1.9.1.1) 58 | columnize (0.9.0) 59 | daemons (1.2.3) 60 | daemons-rails (1.2.1) 61 | daemons 62 | multi_json (~> 1.0) 63 | debug_inspector (0.0.2) 64 | erubis (2.7.0) 65 | execjs (2.5.2) 66 | gcm (0.1.0) 67 | httparty 68 | json 69 | globalid (0.3.5) 70 | activesupport (>= 4.1.0) 71 | httparty (0.13.5) 72 | json (~> 1.8) 73 | multi_xml (>= 0.5.2) 74 | i18n (0.7.0) 75 | jbuilder (2.3.1) 76 | activesupport (>= 3.0.0, < 5) 77 | multi_json (~> 1.2) 78 | jmespath (1.0.2) 79 | multi_json (~> 1.0) 80 | jquery-rails (4.0.4) 81 | rails-dom-testing (~> 1.0) 82 | railties (>= 4.2.0) 83 | thor (>= 0.14, < 2.0) 84 | json (1.8.3) 85 | little-plugger (1.1.3) 86 | logging (2.0.0) 87 | little-plugger (~> 1.1) 88 | multi_json (~> 1.10) 89 | loofah (2.0.2) 90 | nokogiri (>= 1.5.9) 91 | mail (2.6.3) 92 | mime-types (>= 1.16, < 3) 93 | mime-types (2.6.1) 94 | mini_portile (0.6.2) 95 | minitest (5.7.0) 96 | multi_json (1.11.2) 97 | multi_xml (0.5.5) 98 | nokogiri (1.6.6.2) 99 | mini_portile (~> 0.6.0) 100 | rack (1.6.4) 101 | rack-test (0.6.3) 102 | rack (>= 1.0) 103 | rails (4.2.1) 104 | actionmailer (= 4.2.1) 105 | actionpack (= 4.2.1) 106 | actionview (= 4.2.1) 107 | activejob (= 4.2.1) 108 | activemodel (= 4.2.1) 109 | activerecord (= 4.2.1) 110 | activesupport (= 4.2.1) 111 | bundler (>= 1.3.0, < 2.0) 112 | railties (= 4.2.1) 113 | sprockets-rails 114 | rails-deprecated_sanitizer (1.0.3) 115 | activesupport (>= 4.2.0.alpha) 116 | rails-dom-testing (1.0.6) 117 | activesupport (>= 4.2.0.beta, < 5.0) 118 | nokogiri (~> 1.6.0) 119 | rails-deprecated_sanitizer (>= 1.0.1) 120 | rails-html-sanitizer (1.0.2) 121 | loofah (~> 2.0) 122 | railties (4.2.1) 123 | actionpack (= 4.2.1) 124 | activesupport (= 4.2.1) 125 | rake (>= 0.8.7) 126 | thor (>= 0.18.1, < 2.0) 127 | rake (10.4.2) 128 | rdoc (4.2.0) 129 | json (~> 1.4) 130 | sass (3.4.15) 131 | sass-rails (5.0.3) 132 | railties (>= 4.0.0, < 5.0) 133 | sass (~> 3.1) 134 | sprockets (>= 2.8, < 4.0) 135 | sprockets-rails (>= 2.0, < 4.0) 136 | tilt (~> 1.1) 137 | sdoc (0.4.1) 138 | json (~> 1.7, >= 1.7.7) 139 | rdoc (~> 4.0) 140 | spring (1.3.6) 141 | sprockets (3.2.0) 142 | rack (~> 1.0) 143 | sprockets-rails (2.3.2) 144 | actionpack (>= 3.0) 145 | activesupport (>= 3.0) 146 | sprockets (>= 2.8, < 4.0) 147 | sqlite3 (1.3.10) 148 | thor (0.19.1) 149 | thread_safe (0.3.5) 150 | tilt (1.4.1) 151 | turbolinks (2.5.3) 152 | coffee-rails 153 | tzinfo (1.2.2) 154 | thread_safe (~> 0.1) 155 | uglifier (2.7.1) 156 | execjs (>= 0.3.0) 157 | json (>= 1.8.0) 158 | web-console (2.1.3) 159 | activemodel (>= 4.0) 160 | binding_of_caller (>= 0.7.2) 161 | railties (>= 4.0) 162 | sprockets-rails (>= 2.0, < 4.0) 163 | 164 | PLATFORMS 165 | ruby 166 | 167 | DEPENDENCIES 168 | aws-sdk (~> 2) 169 | byebug 170 | coffee-rails (~> 4.1.0) 171 | daemons-rails 172 | gcm 173 | jbuilder (~> 2.0) 174 | jquery-rails 175 | logging 176 | rails (= 4.2.1) 177 | sass-rails (~> 5.0) 178 | sdoc (~> 0.4.0) 179 | spring 180 | sqlite3 181 | turbolinks 182 | uglifier (>= 1.3.0) 183 | web-console (~> 2.0) 184 | -------------------------------------------------------------------------------- /server-rails/README.md: -------------------------------------------------------------------------------- 1 | `rake daemon:monitor_queue:start` is going to start queue processing. 2 | 3 | To start in production, attach `RAILS_ENV=production` before the command. 4 | -------------------------------------------------------------------------------- /server-rails/Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('../config/application', __FILE__) 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /server-rails/app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/server-rails/app/assets/images/.keep -------------------------------------------------------------------------------- /server-rails/app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. 9 | // 10 | // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require jquery 14 | //= require jquery_ujs 15 | //= require turbolinks 16 | //= require_tree . 17 | -------------------------------------------------------------------------------- /server-rails/app/assets/javascripts/apps.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://coffeescript.org/ 4 | -------------------------------------------------------------------------------- /server-rails/app/assets/javascripts/endpoints.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://coffeescript.org/ 4 | -------------------------------------------------------------------------------- /server-rails/app/assets/javascripts/messages.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://coffeescript.org/ 4 | -------------------------------------------------------------------------------- /server-rails/app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, 6 | * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any styles 10 | * defined in the other CSS/SCSS files in this directory. It is generally better to create a new 11 | * file per style scope. 12 | * 13 | *= require_tree . 14 | *= require_self 15 | */ 16 | -------------------------------------------------------------------------------- /server-rails/app/assets/stylesheets/apps.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the Apps controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /server-rails/app/assets/stylesheets/endpoints.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the Endpoints controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /server-rails/app/assets/stylesheets/messages.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the Messages controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /server-rails/app/assets/stylesheets/scaffolds.scss: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #fff; 3 | color: #333; 4 | font-family: verdana, arial, helvetica, sans-serif; 5 | font-size: 13px; 6 | line-height: 18px; 7 | } 8 | 9 | p, ol, ul, td { 10 | font-family: verdana, arial, helvetica, sans-serif; 11 | font-size: 13px; 12 | line-height: 18px; 13 | } 14 | 15 | pre { 16 | background-color: #eee; 17 | padding: 10px; 18 | font-size: 11px; 19 | } 20 | 21 | a { 22 | color: #000; 23 | &:visited { 24 | color: #666; 25 | } 26 | &:hover { 27 | color: #fff; 28 | background-color: #000; 29 | } 30 | } 31 | 32 | div { 33 | &.field, &.actions { 34 | margin-bottom: 10px; 35 | } 36 | } 37 | 38 | #notice { 39 | color: green; 40 | } 41 | 42 | .field_with_errors { 43 | padding: 2px; 44 | background-color: red; 45 | display: table; 46 | } 47 | 48 | #error_explanation { 49 | width: 450px; 50 | border: 2px solid red; 51 | padding: 7px; 52 | padding-bottom: 0; 53 | margin-bottom: 20px; 54 | background-color: #f0f0f0; 55 | h2 { 56 | text-align: left; 57 | font-weight: bold; 58 | padding: 5px 5px 5px 15px; 59 | font-size: 12px; 60 | margin: -7px; 61 | margin-bottom: 0px; 62 | background-color: #c00; 63 | color: #fff; 64 | } 65 | ul li { 66 | font-size: 12px; 67 | list-style: square; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /server-rails/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | # Prevent CSRF attacks by raising an exception. 3 | # For APIs, you may want to use :null_session instead. 4 | protect_from_forgery with: :exception 5 | end 6 | -------------------------------------------------------------------------------- /server-rails/app/controllers/apps_controller.rb: -------------------------------------------------------------------------------- 1 | class AppsController < ApplicationController 2 | before_action :set_app, only: [:show, :edit, :update, :destroy] 3 | 4 | # GET /apps 5 | # GET /apps.json 6 | def index 7 | @apps = App.all 8 | end 9 | 10 | # GET /apps/1 11 | # GET /apps/1.json 12 | def show 13 | end 14 | 15 | # GET /apps/new 16 | def new 17 | @app = App.new 18 | end 19 | 20 | # GET /apps/1/edit 21 | def edit 22 | end 23 | 24 | # POST /apps 25 | # POST /apps.json 26 | def create 27 | @app = App.new(app_params) 28 | 29 | respond_to do |format| 30 | if @app.save 31 | format.html { redirect_to @app, notice: 'App was successfully created.' } 32 | format.json { render :show, status: :created, location: @app } 33 | else 34 | format.html { render :new } 35 | format.json { render json: @app.errors, status: :unprocessable_entity } 36 | end 37 | end 38 | end 39 | 40 | # PATCH/PUT /apps/1 41 | # PATCH/PUT /apps/1.json 42 | def update 43 | respond_to do |format| 44 | if @app.update(app_params) 45 | format.html { redirect_to @app, notice: 'App was successfully updated.' } 46 | format.json { render :show, status: :ok, location: @app } 47 | else 48 | format.html { render :edit } 49 | format.json { render json: @app.errors, status: :unprocessable_entity } 50 | end 51 | end 52 | end 53 | 54 | # DELETE /apps/1 55 | # DELETE /apps/1.json 56 | def destroy 57 | @app.destroy 58 | respond_to do |format| 59 | format.html { redirect_to apps_url, notice: 'App was successfully destroyed.' } 60 | format.json { head :no_content } 61 | end 62 | end 63 | 64 | private 65 | # Use callbacks to share common setup or constraints between actions. 66 | def set_app 67 | @app = App.find(params[:id]) 68 | end 69 | 70 | # Never trust parameters from the scary internet, only allow the white list through. 71 | def app_params 72 | params.require(:app).permit(:app_id, :gcm) 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /server-rails/app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/server-rails/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /server-rails/app/controllers/endpoints_controller.rb: -------------------------------------------------------------------------------- 1 | class EndpointsController < ApplicationController 2 | def deliver 3 | sqs = Aws::SQS::Client.new(region: ENV["AWS_region"]) 4 | queue_name = QUEUE_NAME_PREFIX + params[:app_id] 5 | queue_url = sqs.get_queue_url(queue_name: queue_name).queue_url 6 | sqs.send_message( 7 | queue_url: queue_url, 8 | message_body: params[:json] 9 | ) 10 | redirect_to root_path, notice: "message successfully pushed to queue #{queue_name}" 11 | end 12 | 13 | def register 14 | app = App.find_or_create_by(app_id: params[:app_id]) 15 | app.update_attributes(gcm_id: params[:gcm_id]) 16 | #create new queue with app_id as name 17 | sqs = Aws::SQS::Client.new(region: ENV["AWS_region"]) 18 | queue_name = QUEUE_NAME_PREFIX + params[:app_id] 19 | queue = sqs.create_queue(queue_name: queue_name) 20 | end 21 | 22 | end 23 | -------------------------------------------------------------------------------- /server-rails/app/controllers/messages_controller.rb: -------------------------------------------------------------------------------- 1 | class MessagesController < ApplicationController 2 | before_action :set_message, only: [:show, :edit, :update, :destroy] 3 | 4 | # GET /messages 5 | # GET /messages.json 6 | def index 7 | #@messages = Message.all 8 | sqs = Aws::SQS::Client.new(region: ENV["AWS_region"]) 9 | queue_urls = sqs.list_queues(queue_name_prefix: QUEUE_NAME_PREFIX).queue_urls.each 10 | @queues = [] 11 | queue_urls.each do |queue_url| 12 | puts queue_url 13 | queue = {} 14 | queue[:queue_url] = queue_url 15 | queue[:message_count] = sqs.get_queue_attributes({ queue_url: queue_url, attribute_names: ["ApproximateNumberOfMessages"]}).attributes["ApproximateNumberOfMessages"] 16 | queue[:last_message] = sqs.receive_message({ queue_url: queue_url, max_number_of_messages: 1}).messages 17 | queue[:last_message] = queue[:last_message][0].nil? ? "-" : queue[:last_message][0].body 18 | @queues << queue 19 | end 20 | end 21 | 22 | # GET /messages/1 23 | # GET /messages/1.json 24 | def show 25 | end 26 | 27 | # GET /messages/new 28 | def new 29 | @message = Message.new 30 | end 31 | 32 | # GET /messages/1/edit 33 | def edit 34 | end 35 | 36 | # POST /messages 37 | # POST /messages.json 38 | def create 39 | 40 | @message = Message.new(message_params) 41 | 42 | if @message.save 43 | #format.html { redirect_to @message, notice: 'Message was successfully created.' } 44 | #format.json { render :show, status: :created, location: @message } 45 | #puts message_params 46 | redirect_to deliver_path(app_id: message_params[:app_id], json: message_params[:json]), notice: 'Message is successfully created' 47 | else 48 | respond_to do |format| 49 | format.html { render :new } 50 | format.json { render json: @message.errors, status: :unprocessable_entity } 51 | end 52 | end 53 | end 54 | 55 | # PATCH/PUT /messages/1 56 | # PATCH/PUT /messages/1.json 57 | def update 58 | respond_to do |format| 59 | if @message.update(message_params) 60 | format.html { redirect_to @message, notice: 'Message was successfully updated.' } 61 | format.json { render :show, status: :ok, location: @message } 62 | else 63 | format.html { render :edit } 64 | format.json { render json: @message.errors, status: :unprocessable_entity } 65 | end 66 | end 67 | end 68 | 69 | # DELETE /messages/1 70 | # DELETE /messages/1.json 71 | def destroy 72 | @message.destroy 73 | respond_to do |format| 74 | format.html { redirect_to messages_url, notice: 'Message was successfully destroyed.' } 75 | format.json { head :no_content } 76 | end 77 | end 78 | 79 | private 80 | # Use callbacks to share common setup or constraints between actions. 81 | def set_message 82 | @message = Message.find(params[:id]) 83 | end 84 | 85 | # Never trust parameters from the scary internet, only allow the white list through. 86 | def message_params 87 | params.require(:message).permit(:app_id, :json) 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /server-rails/app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /server-rails/app/helpers/apps_helper.rb: -------------------------------------------------------------------------------- 1 | module AppsHelper 2 | end 3 | -------------------------------------------------------------------------------- /server-rails/app/helpers/endpoints_helper.rb: -------------------------------------------------------------------------------- 1 | module EndpointsHelper 2 | end 3 | -------------------------------------------------------------------------------- /server-rails/app/helpers/messages_helper.rb: -------------------------------------------------------------------------------- 1 | module MessagesHelper 2 | end 3 | -------------------------------------------------------------------------------- /server-rails/app/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/server-rails/app/mailers/.keep -------------------------------------------------------------------------------- /server-rails/app/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/server-rails/app/models/.keep -------------------------------------------------------------------------------- /server-rails/app/models/app.rb: -------------------------------------------------------------------------------- 1 | class App < ActiveRecord::Base 2 | end 3 | -------------------------------------------------------------------------------- /server-rails/app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/server-rails/app/models/concerns/.keep -------------------------------------------------------------------------------- /server-rails/app/models/message.rb: -------------------------------------------------------------------------------- 1 | class Message < ActiveRecord::Base 2 | def self.delete_queues 3 | sqs = Aws::SQS::Client.new(region: ENV["AWS_region"]) 4 | queue_urls = sqs.list_queues(queue_name_prefix: QUEUE_NAME_PREFIX).queue_urls 5 | queue_urls.each do |queue_url| 6 | sqs.delete_queue( 7 | queue_url: queue_url 8 | ) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /server-rails/app/views/apps/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for(@app) do |f| %> 2 | <% if @app.errors.any? %> 3 |
4 |

<%= pluralize(@app.errors.count, "error") %> prohibited this app from being saved:

5 | 6 |
    7 | <% @app.errors.full_messages.each do |message| %> 8 |
  • <%= message %>
  • 9 | <% end %> 10 |
11 |
12 | <% end %> 13 | 14 |
15 | <%= f.label :app_id %>
16 | <%= f.text_field :app_id %> 17 |
18 |
19 | <%= f.label :gcm_id %>
20 | <%= f.text_area :gcm_id %> 21 |
22 |
23 | <%= f.submit %> 24 |
25 | <% end %> 26 | -------------------------------------------------------------------------------- /server-rails/app/views/apps/edit.html.erb: -------------------------------------------------------------------------------- 1 |

Editing App

2 | 3 | <%= render 'form' %> 4 | 5 | <%= link_to 'Show', @app %> | 6 | <%= link_to 'Back', apps_path %> 7 | -------------------------------------------------------------------------------- /server-rails/app/views/apps/index.html.erb: -------------------------------------------------------------------------------- 1 |

<%= notice %>

2 | 3 |

Listing Apps

4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | <% @apps.each do |app| %> 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | <% end %> 24 | 25 |
App IdGcm Id
<%= app.app_id %><%= app.gcm_id %><%= link_to 'Show', app %><%= link_to 'Edit', edit_app_path(app) %><%= link_to 'Destroy', app, method: :delete, data: { confirm: 'Are you sure?' } %>
26 | 27 |
28 | 29 | <%= link_to 'New App', new_app_path %> 30 | -------------------------------------------------------------------------------- /server-rails/app/views/apps/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.array!(@apps) do |app| 2 | json.extract! app, :id, :app_id, :gcm 3 | json.url app_url(app, format: :json) 4 | end 5 | -------------------------------------------------------------------------------- /server-rails/app/views/apps/new.html.erb: -------------------------------------------------------------------------------- 1 |

New App

2 | 3 | <%= render 'form' %> 4 | 5 | <%= link_to 'Back', apps_path %> 6 | -------------------------------------------------------------------------------- /server-rails/app/views/apps/show.html.erb: -------------------------------------------------------------------------------- 1 |

<%= notice %>

2 | 3 |

4 | App: 5 | <%= @app.app_id %> 6 |

7 | 8 |

9 | Gcm: 10 | <%= @app.gcm_id %> 11 |

12 | 13 | <%= link_to 'Edit', edit_app_path(@app) %> | 14 | <%= link_to 'Back', apps_path %> 15 | -------------------------------------------------------------------------------- /server-rails/app/views/apps/show.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.extract! @app, :id, :app_id, :gcm, :created_at, :updated_at 2 | -------------------------------------------------------------------------------- /server-rails/app/views/endpoints/deliver.html.erb: -------------------------------------------------------------------------------- 1 |

Endpoints#deliver

2 |

Find me in app/views/endpoints/deliver.html.erb

3 | -------------------------------------------------------------------------------- /server-rails/app/views/endpoints/register.html.erb: -------------------------------------------------------------------------------- 1 |

Endpoints#register

2 |

Find me in app/views/endpoints/register.html.erb

3 | -------------------------------------------------------------------------------- /server-rails/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | LocalOyeDeliveryServer 5 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> 6 | <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> 7 | <%= csrf_meta_tags %> 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /server-rails/app/views/messages/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for(@message) do |f| %> 2 | <% if @message.errors.any? %> 3 |
4 |

<%= pluralize(@message.errors.count, "error") %> prohibited this message from being saved:

5 | 6 |
    7 | <% @message.errors.full_messages.each do |message| %> 8 |
  • <%= message %>
  • 9 | <% end %> 10 |
11 |
12 | <% end %> 13 | 14 |
15 | <%= f.label :app_id %>
16 | <%= f.text_field :app_id %> 17 |
18 |
19 | <%= f.label :json %>
20 | <%= f.text_field :json %> 21 |
22 |
23 | <%= f.submit %> 24 |
25 | <% end %> 26 | -------------------------------------------------------------------------------- /server-rails/app/views/messages/edit.html.erb: -------------------------------------------------------------------------------- 1 |

Editing Message

2 | 3 | <%= render 'form' %> 4 | 5 | <%= link_to 'Show', @message %> | 6 | <%= link_to 'Back', messages_path %> 7 | -------------------------------------------------------------------------------- /server-rails/app/views/messages/index.html.erb: -------------------------------------------------------------------------------- 1 |

<%= notice %>

2 | 3 |

Listing Messages in queue

4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | <% @queues.each do |queue| %> 16 | 17 | 18 | 19 | 20 | 21 | <% end %> 22 | 23 |
Queue | Messages in Queue | Next message to be fetched
<%= queue[:queue_url] %><%= queue[:message_count] %><%= queue[:last_message] %>
24 | 25 |
26 | 27 | <%= link_to 'View Apps', apps_path %> 28 | <%= link_to 'Put New Message in Queue', new_message_path %> 29 | -------------------------------------------------------------------------------- /server-rails/app/views/messages/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.array!(@messages) do |message| 2 | json.extract! message, :id, :app_id, :json 3 | json.url message_url(message, format: :json) 4 | end 5 | -------------------------------------------------------------------------------- /server-rails/app/views/messages/new.html.erb: -------------------------------------------------------------------------------- 1 |

New Message

2 | 3 | <%= render 'form' %> 4 | 5 | <%= link_to 'Back', messages_path %> 6 | -------------------------------------------------------------------------------- /server-rails/app/views/messages/show.html.erb: -------------------------------------------------------------------------------- 1 |

<%= notice %>

2 | 3 |

4 | App: 5 | <%= @message.app_id %> 6 |

7 | 8 |

9 | Json: 10 | <%= @message.json %> 11 |

12 | 13 | <%= link_to 'Edit', edit_message_path(@message) %> | 14 | <%= link_to 'Back', messages_path %> 15 | -------------------------------------------------------------------------------- /server-rails/app/views/messages/show.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.extract! @message, :id, :app_id, :json, :created_at, :updated_at 2 | -------------------------------------------------------------------------------- /server-rails/bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /server-rails/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path("../spring", __FILE__) 4 | rescue LoadError 5 | end 6 | APP_PATH = File.expand_path('../../config/application', __FILE__) 7 | require_relative '../config/boot' 8 | require 'rails/commands' 9 | -------------------------------------------------------------------------------- /server-rails/bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path("../spring", __FILE__) 4 | rescue LoadError 5 | end 6 | require_relative '../config/boot' 7 | require 'rake' 8 | Rake.application.run 9 | -------------------------------------------------------------------------------- /server-rails/bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'pathname' 3 | 4 | # path to your application root. 5 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) 6 | 7 | Dir.chdir APP_ROOT do 8 | # This script is a starting point to setup your application. 9 | # Add necessary setup steps to this file: 10 | 11 | puts "== Installing dependencies ==" 12 | system "gem install bundler --conservative" 13 | system "bundle check || bundle install" 14 | 15 | # puts "\n== Copying sample files ==" 16 | # unless File.exist?("config/database.yml") 17 | # system "cp config/database.yml.sample config/database.yml" 18 | # end 19 | 20 | puts "\n== Preparing database ==" 21 | system "bin/rake db:setup" 22 | 23 | puts "\n== Removing old logs and tempfiles ==" 24 | system "rm -f log/*" 25 | system "rm -rf tmp/cache" 26 | 27 | puts "\n== Restarting application server ==" 28 | system "touch tmp/restart.txt" 29 | end 30 | -------------------------------------------------------------------------------- /server-rails/bin/spring: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # This file loads spring without using Bundler, in order to be fast. 4 | # It gets overwritten when you run the `spring binstub` command. 5 | 6 | unless defined?(Spring) 7 | require "rubygems" 8 | require "bundler" 9 | 10 | if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m) 11 | Gem.paths = { "GEM_PATH" => [Bundler.bundle_path.to_s, *Gem.path].uniq } 12 | gem "spring", match[1] 13 | require "spring/binstub" 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /server-rails/config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run Rails.application 5 | -------------------------------------------------------------------------------- /server-rails/config/app_environment_variables.rb.example: -------------------------------------------------------------------------------- 1 | ENV["AWS_ACCESS_KEY"] = "xxxx" 2 | ENV["AWS_SECRET_KEY"] = "xxxx" 3 | ENV["AWS_region"] = "us-west-2" 4 | ENV["GCM"] = "xxxx" 5 | QUEUE_NAME_PREFIX = ENV["RAILS_ENV"] == "production" ? "live-" : "test-" 6 | 7 | -------------------------------------------------------------------------------- /server-rails/config/application.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../boot', __FILE__) 2 | 3 | require "rails" 4 | # Pick the frameworks you want: 5 | require "active_model/railtie" 6 | require "active_job/railtie" 7 | require "active_record/railtie" 8 | require "action_controller/railtie" 9 | require "action_mailer/railtie" 10 | require "action_view/railtie" 11 | require "sprockets/railtie" 12 | # require "rails/test_unit/railtie" 13 | 14 | # Require the gems listed in Gemfile, including any gems 15 | # you've limited to :test, :development, or :production. 16 | Bundler.require(*Rails.groups) 17 | 18 | module LocalOyeDeliveryServer 19 | class Application < Rails::Application 20 | # Settings in config/environments/* take precedence over those specified here. 21 | # Application configuration should go into files in config/initializers 22 | # -- all .rb files in that directory are automatically loaded. 23 | 24 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. 25 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. 26 | # config.time_zone = 'Central Time (US & Canada)' 27 | 28 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. 29 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] 30 | # config.i18n.default_locale = :de 31 | 32 | # Do not swallow errors in after_commit/after_rollback callbacks. 33 | config.active_record.raise_in_transactional_callbacks = true 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /server-rails/config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 2 | 3 | require 'bundler/setup' # Set up gems listed in the Gemfile. 4 | -------------------------------------------------------------------------------- /server-rails/config/daemons.yml: -------------------------------------------------------------------------------- 1 | dir_mode: script 2 | dir: ../../log 3 | multiple: false 4 | backtrace: true 5 | monitor: false 6 | ontop: false -------------------------------------------------------------------------------- /server-rails/config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite version 3.x 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem 'sqlite3' 6 | # 7 | default: &default 8 | adapter: sqlite3 9 | pool: 5 10 | timeout: 5000 11 | 12 | development: 13 | <<: *default 14 | database: db/development.sqlite3 15 | 16 | # Warning: The database defined as "test" will be erased and 17 | # re-generated from your development database when you run "rake". 18 | # Do not set this db to the same as development or production. 19 | test: 20 | <<: *default 21 | database: db/test.sqlite3 22 | 23 | production: 24 | <<: *default 25 | database: db/production.sqlite3 26 | -------------------------------------------------------------------------------- /server-rails/config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require File.expand_path('../application', __FILE__) 3 | 4 | # Load the app's custom environment variables here, so that they are loaded before environments/*.rb 5 | app_environment_variables = File.join(Rails.root, 'config', 'app_environment_variables.rb') 6 | if File.exists?(app_environment_variables) 7 | load(app_environment_variables) 8 | else 9 | raise "No config/app_environment_variables.rb found." 10 | end 11 | # Initialize the Rails application. 12 | Rails.application.initialize! 13 | -------------------------------------------------------------------------------- /server-rails/config/environments/development.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # In the development environment your application's code is reloaded on 5 | # every request. This slows down response time but is perfect for development 6 | # since you don't have to restart the web server when you make code changes. 7 | config.cache_classes = false 8 | 9 | # Do not eager load code on boot. 10 | config.eager_load = false 11 | 12 | # Show full error reports and disable caching. 13 | config.consider_all_requests_local = true 14 | config.action_controller.perform_caching = false 15 | 16 | # Don't care if the mailer can't send. 17 | config.action_mailer.raise_delivery_errors = false 18 | 19 | # Print deprecation notices to the Rails logger. 20 | config.active_support.deprecation = :log 21 | 22 | # Raise an error on page load if there are pending migrations. 23 | config.active_record.migration_error = :page_load 24 | 25 | # Debug mode disables concatenation and preprocessing of assets. 26 | # This option may cause significant delays in view rendering with a large 27 | # number of complex assets. 28 | config.assets.debug = true 29 | 30 | # Asset digests allow you to set far-future HTTP expiration dates on all assets, 31 | # yet still be able to expire them through the digest params. 32 | config.assets.digest = true 33 | 34 | # Adds additional error checking when serving assets at runtime. 35 | # Checks for improperly declared sprockets dependencies. 36 | # Raises helpful error messages. 37 | config.assets.raise_runtime_errors = true 38 | 39 | # Raises error for missing translations 40 | # config.action_view.raise_on_missing_translations = true 41 | end 42 | -------------------------------------------------------------------------------- /server-rails/config/environments/production.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # Code is not reloaded between requests. 5 | config.cache_classes = true 6 | 7 | # Eager load code on boot. This eager loads most of Rails and 8 | # your application in memory, allowing both threaded web servers 9 | # and those relying on copy on write to perform better. 10 | # Rake tasks automatically ignore this option for performance. 11 | config.eager_load = true 12 | 13 | # Full error reports are disabled and caching is turned on. 14 | config.consider_all_requests_local = false 15 | config.action_controller.perform_caching = true 16 | 17 | # Enable Rack::Cache to put a simple HTTP cache in front of your application 18 | # Add `rack-cache` to your Gemfile before enabling this. 19 | # For large-scale production use, consider using a caching reverse proxy like 20 | # NGINX, varnish or squid. 21 | # config.action_dispatch.rack_cache = true 22 | 23 | # Disable serving static files from the `/public` folder by default since 24 | # Apache or NGINX already handles this. 25 | config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present? 26 | 27 | # Compress JavaScripts and CSS. 28 | config.assets.js_compressor = :uglifier 29 | # config.assets.css_compressor = :sass 30 | 31 | # Do not fallback to assets pipeline if a precompiled asset is missed. 32 | config.assets.compile = false 33 | 34 | # Asset digests allow you to set far-future HTTP expiration dates on all assets, 35 | # yet still be able to expire them through the digest params. 36 | config.assets.digest = true 37 | 38 | # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb 39 | 40 | # Specifies the header that your server uses for sending files. 41 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache 42 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX 43 | 44 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 45 | # config.force_ssl = true 46 | 47 | # Use the lowest log level to ensure availability of diagnostic information 48 | # when problems arise. 49 | config.log_level = :debug 50 | 51 | # Prepend all log lines with the following tags. 52 | # config.log_tags = [ :subdomain, :uuid ] 53 | 54 | # Use a different logger for distributed setups. 55 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) 56 | 57 | # Use a different cache store in production. 58 | # config.cache_store = :mem_cache_store 59 | 60 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 61 | # config.action_controller.asset_host = 'http://assets.example.com' 62 | 63 | # Ignore bad email addresses and do not raise email delivery errors. 64 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 65 | # config.action_mailer.raise_delivery_errors = false 66 | 67 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 68 | # the I18n.default_locale when a translation cannot be found). 69 | config.i18n.fallbacks = true 70 | 71 | # Send deprecation notices to registered listeners. 72 | config.active_support.deprecation = :notify 73 | 74 | # Use default logging formatter so that PID and timestamp are not suppressed. 75 | config.log_formatter = ::Logger::Formatter.new 76 | 77 | # Do not dump schema after migrations. 78 | config.active_record.dump_schema_after_migration = false 79 | end 80 | -------------------------------------------------------------------------------- /server-rails/config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # The test environment is used exclusively to run your application's 5 | # test suite. You never need to work with it otherwise. Remember that 6 | # your test database is "scratch space" for the test suite and is wiped 7 | # and recreated between test runs. Don't rely on the data there! 8 | config.cache_classes = true 9 | 10 | # Do not eager load code on boot. This avoids loading your whole application 11 | # just for the purpose of running a single test. If you are using a tool that 12 | # preloads Rails for running tests, you may have to set it to true. 13 | config.eager_load = false 14 | 15 | # Configure static file server for tests with Cache-Control for performance. 16 | config.serve_static_files = true 17 | config.static_cache_control = 'public, max-age=3600' 18 | 19 | # Show full error reports and disable caching. 20 | config.consider_all_requests_local = true 21 | config.action_controller.perform_caching = false 22 | 23 | # Raise exceptions instead of rendering exception templates. 24 | config.action_dispatch.show_exceptions = false 25 | 26 | # Disable request forgery protection in test environment. 27 | config.action_controller.allow_forgery_protection = false 28 | 29 | # Tell Action Mailer not to deliver emails to the real world. 30 | # The :test delivery method accumulates sent emails in the 31 | # ActionMailer::Base.deliveries array. 32 | config.action_mailer.delivery_method = :test 33 | 34 | # Randomize the order test cases are executed. 35 | config.active_support.test_order = :random 36 | 37 | # Print deprecation notices to the stderr. 38 | config.active_support.deprecation = :stderr 39 | 40 | # Raises error for missing translations 41 | # config.action_view.raise_on_missing_translations = true 42 | end 43 | -------------------------------------------------------------------------------- /server-rails/config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = '1.0' 5 | 6 | # Add additional assets to the asset load path 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | 9 | # Precompile additional assets. 10 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. 11 | # Rails.application.config.assets.precompile += %w( search.js ) 12 | -------------------------------------------------------------------------------- /server-rails/config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /server-rails/config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.action_dispatch.cookies_serializer = :json 4 | -------------------------------------------------------------------------------- /server-rails/config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /server-rails/config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /server-rails/config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /server-rails/config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.session_store :cookie_store, key: '_LocalOye-delivery-server_session' 4 | -------------------------------------------------------------------------------- /server-rails/config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters) 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /server-rails/config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # To learn more, please read the Rails Internationalization guide 20 | # available at http://guides.rubyonrails.org/i18n.html. 21 | 22 | en: 23 | hello: "Hello world" 24 | -------------------------------------------------------------------------------- /server-rails/config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | resources :apps 3 | root 'messages#index' 4 | resources :messages 5 | get 'endpoints/deliver/:app_id/:json' => "endpoints#deliver", as: :deliver 6 | get 'endpoints/register/:app_id/:gcm_id' => "endpoints#register", as: :register 7 | 8 | # The priority is based upon order of creation: first created -> highest priority. 9 | # See how all your routes lay out with "rake routes". 10 | 11 | # You can have the root of your site routed with "root" 12 | # root 'welcome#index' 13 | 14 | # Example of regular route: 15 | # get 'products/:id' => 'catalog#view' 16 | 17 | # Example of named route that can be invoked with purchase_url(id: product.id) 18 | # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase 19 | 20 | # Example resource route (maps HTTP verbs to controller actions automatically): 21 | # resources :products 22 | 23 | # Example resource route with options: 24 | # resources :products do 25 | # member do 26 | # get 'short' 27 | # post 'toggle' 28 | # end 29 | # 30 | # collection do 31 | # get 'sold' 32 | # end 33 | # end 34 | 35 | # Example resource route with sub-resources: 36 | # resources :products do 37 | # resources :comments, :sales 38 | # resource :seller 39 | # end 40 | 41 | # Example resource route with more complex sub-resources: 42 | # resources :products do 43 | # resources :comments 44 | # resources :sales do 45 | # get 'recent', on: :collection 46 | # end 47 | # end 48 | 49 | # Example resource route with concerns: 50 | # concern :toggleable do 51 | # post 'toggle' 52 | # end 53 | # resources :posts, concerns: :toggleable 54 | # resources :photos, concerns: :toggleable 55 | 56 | # Example resource route within a namespace: 57 | # namespace :admin do 58 | # # Directs /admin/products/* to Admin::ProductsController 59 | # # (app/controllers/admin/products_controller.rb) 60 | # resources :products 61 | # end 62 | end 63 | -------------------------------------------------------------------------------- /server-rails/config/secrets.yml: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key is used for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | 6 | # Make sure the secret is at least 30 characters and all random, 7 | # no regular words or you'll be exposed to dictionary attacks. 8 | # You can use `rake secret` to generate a secure secret key. 9 | 10 | # Make sure the secrets in this file are kept private 11 | # if you're sharing your code publicly. 12 | 13 | development: 14 | secret_key_base: cf5fb47702066bc7a560aa9221b8776ea54147c1b5da50a15e432d1b228745505204bbcbaba5a45706579e3aafc3049c95e8f189f3ee5286eb56dd471c5568c3 15 | 16 | test: 17 | secret_key_base: f57b95b134012e491cfe31124768939ce9729786c3a92fcfb304615fbfc045ef4043a2fba4f91bb7b3377089c8669f80749bad74505c4bb8df5ff89d42ceb122 18 | 19 | # Do not keep production secrets in the repository, 20 | # instead read values from the environment. 21 | production: 22 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> 23 | -------------------------------------------------------------------------------- /server-rails/db/migrate/20150706135627_create_messages.rb: -------------------------------------------------------------------------------- 1 | class CreateMessages < ActiveRecord::Migration 2 | def change 3 | create_table :messages do |t| 4 | t.string :app_id 5 | t.string :json 6 | 7 | t.timestamps null: false 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /server-rails/db/migrate/20150707073837_create_apps.rb: -------------------------------------------------------------------------------- 1 | class CreateApps < ActiveRecord::Migration 2 | def change 3 | create_table :apps do |t| 4 | t.string :app_id 5 | t.text :gcm_id 6 | 7 | t.timestamps null: false 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /server-rails/db/schema.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | # This file is auto-generated from the current state of the database. Instead 3 | # of editing this file, please use the migrations feature of Active Record to 4 | # incrementally modify your database, and then regenerate this schema definition. 5 | # 6 | # Note that this schema.rb definition is the authoritative source for your 7 | # database schema. If you need to create the application database on another 8 | # system, you should be using db:schema:load, not running all the migrations 9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations 10 | # you'll amass, the slower it'll run and the greater likelihood for issues). 11 | # 12 | # It's strongly recommended that you check this file into your version control system. 13 | 14 | ActiveRecord::Schema.define(version: 20150707073837) do 15 | 16 | create_table "apps", force: :cascade do |t| 17 | t.string "app_id" 18 | t.text "gcm_id" 19 | t.datetime "created_at", null: false 20 | t.datetime "updated_at", null: false 21 | end 22 | 23 | create_table "messages", force: :cascade do |t| 24 | t.string "app_id" 25 | t.string "json" 26 | t.datetime "created_at", null: false 27 | t.datetime "updated_at", null: false 28 | end 29 | 30 | end 31 | -------------------------------------------------------------------------------- /server-rails/db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). 3 | # 4 | # Examples: 5 | # 6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) 7 | # Mayor.create(name: 'Emanuel', city: cities.first) 8 | -------------------------------------------------------------------------------- /server-rails/lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/server-rails/lib/assets/.keep -------------------------------------------------------------------------------- /server-rails/lib/daemons/daemons: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | results = [] 3 | Dir[File.dirname(__FILE__) + "/*_ctl"].each {|f| results << `ruby #{f} #{ARGV.first}`} 4 | results.delete_if { |result| result.nil? || result.empty? } 5 | puts results.join unless results.empty? -------------------------------------------------------------------------------- /server-rails/lib/daemons/monitor_queue.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # You might want to change this 4 | ENV["RAILS_ENV"] = "development" 5 | 6 | root = File.expand_path(File.dirname(__FILE__)) 7 | root = File.dirname(root) until File.exists?(File.join(root, 'config')) 8 | Dir.chdir(root) 9 | 10 | require File.join(root, "config", "environment") 11 | # Load the app's custom environment variables here, so that they are loaded before environments/*.rb 12 | app_environment_variables = File.join(root, 'config', 'app_environment_variables.rb') 13 | load(app_environment_variables) if File.exists?(app_environment_variables) 14 | 15 | $sqs = Aws::SQS::Client.new(region: ENV["AWS_region"]) 16 | require 'gcm' 17 | $gcm = GCM.new(ENV["GCM"]) 18 | 19 | #require 'logging' 20 | 21 | #$logger = Logging.logger(STDOUT) 22 | #$logger.level = :info 23 | 24 | $running = true 25 | Signal.trap("TERM") do 26 | $running = false 27 | end 28 | 29 | while($running) do 30 | sleep 1 31 | Rails.logger.info "This daemon is still running at #{Time.now}.\n" 32 | begin 33 | queue_urls = $sqs.list_queues(queue_name_prefix: QUEUE_NAME_PREFIX).queue_urls 34 | rescue 35 | next 36 | end 37 | gcm_ids = [] 38 | queue_urls.each do |queue_url| 39 | Rails.logger.info "processing queue #{queue_url}" 40 | message_count = $sqs.get_queue_attributes({ queue_url: queue_url, attribute_names: ["ApproximateNumberOfMessages"]}).attributes["ApproximateNumberOfMessages"].to_i 41 | Rails.logger.info "message count for queue #{message_count}" 42 | if message_count > 0 43 | Rails.logger.info "message count #{message_count} hence sending gcm" 44 | #send GCM to this app 45 | app_id = queue_url.split("/")[-1] 46 | app_id.slice! QUEUE_NAME_PREFIX 47 | gcm_ids << App.find_by(app_id: app_id).gcm_id 48 | end 49 | end 50 | if !gcm_ids.empty? 51 | Rails.logger.info "sending gcm for gcm_ids #{gcm_ids}" 52 | response = $gcm.send(gcm_ids, {data: {dude: "get your ass off & start processing messages"}, collapse_key: "updated_score"}) 53 | Rails.logger.info "response from gcm #{response}" 54 | end 55 | # Replace this with your code 56 | #Rails.logger.auto_flushing = true 57 | #$logger.error "This daemon is still running at #{Time.now}.\n" 58 | end 59 | -------------------------------------------------------------------------------- /server-rails/lib/daemons/monitor_queue_ctl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'rubygems' 3 | require 'daemons/rails/config' 4 | 5 | config = Daemons::Rails::Config.for_controller(File.expand_path(__FILE__)) 6 | Daemons::Rails.run config[:script], config.to_hash -------------------------------------------------------------------------------- /server-rails/lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/server-rails/lib/tasks/.keep -------------------------------------------------------------------------------- /server-rails/log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/server-rails/log/.keep -------------------------------------------------------------------------------- /server-rails/public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The page you were looking for doesn't exist.

62 |

You may have mistyped the address or the page may have moved.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /server-rails/public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The change you wanted was rejected.

62 |

Maybe you tried to change something you didn't have access to.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /server-rails/public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

We're sorry, but something went wrong.

62 |
63 |

If you are the application owner check the logs for more information.

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /server-rails/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/server-rails/public/favicon.ico -------------------------------------------------------------------------------- /server-rails/public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /server-rails/vendor/assets/javascripts/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/server-rails/vendor/assets/javascripts/.keep -------------------------------------------------------------------------------- /server-rails/vendor/assets/stylesheets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocha/commu-sqs/0a241f87476223b49ac479055e8ca64c7f5c573a/server-rails/vendor/assets/stylesheets/.keep --------------------------------------------------------------------------------