Skip to content

Instantly share code, notes, and snippets.

@alex-alex2006hw
Forked from t2-support-gists/README
Created January 5, 2016 17:59
Show Gist options
  • Save alex-alex2006hw/33f5f3b04719e5379788 to your computer and use it in GitHub Desktop.
Save alex-alex2006hw/33f5f3b04719e5379788 to your computer and use it in GitHub Desktop.
SMS Ruby RESTFul App 1
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.
# 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 developer.support@att.com
# 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
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
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
#!/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