Last active
April 17, 2019 03:09
-
-
Save t2-support-gists/3125651 to your computer and use it in GitHub Desktop.
SMS Ruby RESTFul App 1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
AT&T API Platform Sample Apps | |
-------------------------------------- | |
This file describes how to set up, configure and run the Ruby sample | |
applications using the AT&T API Platform services. It covers all steps | |
required to register the applications on DevConnect as well as running the | |
sample applications locally. | |
1. Configuration | |
2. Installation | |
3. Parameters | |
4. Running the application | |
1. Configuration | |
Configuration consists of a few steps necessary to get an application | |
registered with the proper services and | |
endpoints, depending on the type of client-side application | |
(autonomous/non-autonomous). | |
To register an application, go to https://developer.att.com/developer/mvc/auth/login and login | |
with your valid username and password. | |
Next, choose "My Apps" from the bar at the top of the page and click the | |
"Setup a New Application" button. | |
Fill in the form, in particular all fields marked as "required". | |
Having your application registered, you will get back an important pair of | |
data: an API key and Secret key. They are | |
necessary to get your applications working with the AT&T API Platform. See | |
'Adjusting parameters' below to learn how to use | |
these keys. | |
Initially your newly registered application is restricted to the "Sandbox" | |
environment only. To move it to production, | |
you may promote it by clicking the "Promote to production" button. Notice | |
that you will get a different API key and secret, | |
so these values in your application should be adjusted accordingly. | |
Depending on the kind of authentication used, an application may be based on | |
either the Autonomous Client or the Web-Server | |
Client OAuth flow (see https://developer.att.com/apis/oauth-2/docs). | |
2. Installation | |
** Requirements | |
To run the examples you will need ruby 1.9.3+ and a few ruby gems that the | |
applications are built upon: | |
- sinatra: (http://www.sinatrarb.com/) used to construct a simple web | |
application and manage URLs within. | |
- sinatra-contrib: additional set of useful helpers, including ones used to | |
read settings from external files. | |
- rest-client: library for making restful calls | |
- json: used for encoding and decoding requests/responses | |
- att-codekit: library developed around the att cloud services (see below | |
to install) | |
- rake: compiling tool used to make att-codekit | |
- yard: documentation tool used by att-codekit | |
The easiest way to install the required gems is to use bundler. | |
First make sure you have bundler installed: | |
gem install bundler | |
Then inside the directory which this README resides run: | |
bundle install | |
On a *nix based system you may need to raise your access privliges, such as | |
prefixing the command with sudo or logging in as root by running su. | |
** Installing the att-codekit library | |
Note: this is only required if you are **not** using bundler and are using ruby 1.9+ | |
The code kit library can be installed by using our hosted gem file. | |
gem sources --add http://lprod.code-api-att.com:8808 | |
gem install att-codekit | |
Note that the codekit is under heavy development and is using a semantic | |
versioning scheme. Non-backwards compatible changes **will** increase the | |
major version number. | |
** Setting up on a different port number | |
In the case multiple applications need to be run at the same time, you need | |
to use different port numbers. | |
By default sinatra uses port number 4567; however only one running | |
application may use this port. In the case that you want to run more than one | |
sinatra-based application, you will need to update each applications' port | |
number (located in config.yml). | |
eg. application 1 - port: 4567, application 2 - port: 4568 | |
The alternative is to set up your webserver to use a tool such as phusion | |
passenger. Setting up a webserver, however, is beyond the scope of this | |
article. | |
3. Parameters | |
Each application contains a config.yml file. It holds configurable parameters | |
described in the easy to read format YAML. You are free to adjust these to | |
your needs. If you introduce a change make sure to restart the application | |
for it to take effect. | |
The following are short descriptions of commonly used parameters: | |
REQUIRED - | |
1) FQDN : The main server handling requests, ex: https://api.att.com | |
2) api_key : set the value as per your registered application 'API | |
key' field value | |
3) secret_key : set the value as per your registered application | |
'Secret key' field value | |
OPTIONAL - | |
4) port : The port number which the application will run standalone | |
5) tokens_file : The path where the oauth token will be saved. This option | |
is only usable in client credential style authentication. | |
Must have write permissions. | |
Note: If your application is promoted from the Sandbox environment to | |
Production environment and you decide to use production application settings, | |
you must update api_key and secret_key as per production application details. | |
4. Running the application | |
To run the application, open up a terminal window in the application's | |
directory and type: | |
ruby (app name).rb | |
Where (app name) is replaced with the current directories app name. | |
Your application by default is accessible in a web browser at the url: | |
http://localhost:4567/ | |
You may interrupt the application at any time by pressing ctrl-C. | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Licensed by AT&T under 'Software Development Kit Tools Agreement.' 2013 | |
# TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION: http://developer.att.com/sdk_agreement/ | |
# Copyright 2013 AT&T Intellectual Property. All rights reserved. http://developer.att.com | |
# For more information contact [email protected] | |
# Tries to parse supplied address using one of known formats. Returns false on failure. | |
def parse_address(address) | |
address.strip! | |
if (address.match('^\d{10}$')) | |
elsif (m = address.match('^1(\d{10})$')) | |
address = m[1].to_s | |
elsif (m = address.match('^\+1(\d{10})$')) | |
address = m[1].to_s | |
elsif (m = address.match('^tel:(\d{10})$')) | |
address = m[1].to_s | |
elsif (address.match('^\d{3}-\d{3}-\d{4}$')) | |
address.gsub! '-', '' | |
end | |
address | |
end | |
# Makes sure that valid access_token is stored in the session. Retrieves new tokens if needed. | |
def obtain_tokens(fqdn, client_id, client_secret, scope, tokens_file) | |
read_tokens(tokens_file) | |
response = RestClient.post "#{fqdn}/oauth/access_token", :grant_type => 'client_credentials', :client_id => client_id, :client_secret => client_secret, :scope => scope | |
from_json = JSON.parse(response.to_str) | |
@access_token = from_json['access_token'] | |
@refresh_token = from_json['refresh_token'] | |
write_tokens(tokens_file) | |
end | |
def write_tokens(tokens_file) | |
File.open(tokens_file, 'w+') { |f| f.puts @access_token, @refresh_token } | |
end | |
def read_tokens(tokens_file) | |
@access_token, @refresh_token, refresh_expiration = File.foreach(tokens_file).first(2).map! &:strip! | |
rescue | |
return | |
end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'bundler' | |
#make sure all gems are installed | |
Bundler.require | |
begin | |
#require the file for ruby 1.9+ | |
require_relative './sms' | |
rescue NoMethodError | |
#if error then we're in ruby 1.8 | |
require './sms' | |
end | |
run Sinatra::Application |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
port: 51000 | |
proxy: | |
phone_number: 49501005 | |
api_key: p2hbpzs4sxwoq3oefahmcugqlehbi7gr | |
secret_key: xlvmmjtymypqmh8lpbitmeqhou2axbo5 | |
short_code_1: 48507147 | |
short_code_2: 44627812 | |
tokens_file: tokens | |
FQDN: https://api.att.com | |
registration_id: 29156137 | |
listener_url: http://lprod.code-api-att.com:51100/smslistener | |
listener_limit: 5 | |
listener_url: https://lprod.code-api-att.com/APIPlatform/2/2/0/PROD/Ruby-RESTful/SMS/app1/smslistener | |
source_link: https://gist.github.com/3125651 | |
download_link: https://github.com/attdevsupport/ATT_APIPlatform_SampleApps/tree/master/RESTFul/SMS/Ruby/app1 | |
help_link: https://raw.github.com/attdevsupport/ATT_APIPlatform_SampleApps/master/RESTFul/SMS/Ruby/app1/README | |
status_file: status_file | |
message_file: message_file | |
mosms_file_dir: MoSmsData | |
votes_file: MoSmsData/vote_data |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# Copyright 2014 AT&T | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
require 'sinatra' | |
require 'sinatra/config_file' | |
# require as a gem file load relative if fails | |
begin | |
require 'att/codekit' | |
rescue LoadError | |
# try relative, fall back to ruby 1.8 method if fails | |
begin | |
require_relative 'codekit/lib/att/codekit' | |
rescue NoMethodError | |
require File.join(File.dirname(__FILE__), 'codekit/lib/att/codekit') | |
end | |
end | |
include Att::Codekit | |
enable :sessions | |
config_file 'config.yml' | |
set :port, settings.port | |
set :protection, :except => :frame_options | |
SCOPE = "SMS" | |
RestClient.proxy = settings.proxy | |
configure do | |
FILE_SUPPORT = (settings.tokens_file && !settings.tokens_file.strip.empty?) | |
FILE_EXISTS = FILE_SUPPORT && File.file?(settings.tokens_file) | |
OAuth = Auth::ClientCred.new(settings.FQDN, | |
settings.api_key, | |
settings.secret_key) | |
@@token = nil | |
end | |
helpers do | |
def h(html) | |
Rack::Utils.escape_html(html) | |
end | |
end | |
#update listeners data before every request | |
before do | |
begin | |
@status_listener = load_file "#{settings.status_file}" | |
@message_listener = load_file "#{settings.message_file}" | |
#check if token exists and create if necessary | |
if @@token.nil? | |
if FILE_EXISTS | |
@@token = Auth::OAuthToken.load(settings.tokens_file) | |
else | |
@@token = OAuth.createToken(SCOPE) | |
end | |
Auth::OAuthToken.save(settings.tokens_file, @@token) if FILE_SUPPORT | |
end | |
if @@token.expired? | |
@@token = OAuth.refreshToken(@@token) | |
Auth::OAuthToken.save(settings.tokens_file, @@token) if FILE_SUPPORT | |
end | |
rescue Exception => e | |
@send_error = e.message | |
end | |
end | |
get '/' do | |
session[:sms_id] = nil | |
if !File.directory? settings.mosms_file_dir then | |
Dir.mkdir settings.mosms_file_dir | |
end | |
erb :sms | |
end | |
post '/sendSms' do | |
begin | |
service = Service::SMSService.new(settings.FQDN, @@token) | |
session[:sms1_address] = params[:address] | |
#set true if we're sending a notification | |
if params[:chkGetOnlineStatus].nil? | |
notify = false | |
else | |
notify = true | |
end | |
@send = service.sendSms(session[:sms1_address], params[:message], notify) | |
session[:sms_id] = @send.id unless notify | |
rescue Exception => e | |
@send_error = e.message | |
end | |
erb :sms | |
end | |
post '/getDeliveryStatus' do | |
session[:sms_id] = params["messageId"] | |
service = Service::SMSService.new(settings.FQDN, @@token) | |
begin | |
@status = service.getDeliveryStatus(session[:sms_id]) | |
@status_resource_url = service.getResourceUrl(session[:sms_id]) | |
rescue Exception => e | |
@delivery_error = e.message | |
end | |
erb :sms | |
end | |
post '/getReceivedSms' do | |
begin | |
service = Service::SMSService.new(settings.FQDN, @@token) | |
@messages = service.getReceivedMessages(settings.short_code_1) | |
rescue Exception => e | |
@received_error = e.message | |
end | |
erb :sms | |
end | |
post '/statusListener' do | |
handle_inbound "#{settings.status_file}" | |
end | |
post '/messageListener' do | |
handle_inbound "#{settings.message_file}" | |
end | |
get '/refreshStatus' do | |
erb :sms | |
end | |
get '/receiveMessages' do | |
erb :sms | |
end | |
# use this URL to clear files | |
get '/clear' do | |
File.delete settings.tokens_file if File.exists? settings.tokens_file | |
File.delete settings.status_file if File.exists? settings.status_file | |
File.delete settings.message_file if File.exists? settings.message_file | |
redirect '/' | |
end | |
def load_file(file) | |
data = Array.new | |
if File.exists? file then | |
File.open(file, 'r') do |f| | |
begin | |
f.flock(File::LOCK_EX) | |
f.each_line {|line| data << JSON.parse(line)} | |
ensure | |
f.flock(File::LOCK_UN) | |
end | |
end | |
end | |
data | |
end | |
def handle_inbound(file) | |
input = request.env["rack.input"].read | |
if !File.exists? file | |
File.new(file, 'w') | |
end | |
contents = File.readlines(file) | |
File.open(file, 'w') do |f| | |
begin | |
f.flock(File::LOCK_EX) | |
#remove the first line if we're over limit | |
if contents.size > settings.listener_limit - 1 | |
offset = 1 | |
else | |
offset = 0 | |
end | |
f.puts contents[offset, contents.size] | |
f.puts JSON.parse(input).to_json | |
ensure | |
f.flock(File::LOCK_UN) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment