Twilio SMS using Ruby - ruby

I've been working on a program that would read a CSV excel file and filter the information to be sent via sms. Currently, the program is only able to send one row of filtered information via sms. What should be modified to be able to send row after row seperately?
Currently the code searches for 'medium' and '2' on columns 1 and 2. It would send out columns 0 and 4. Hence the results would be "DT3/SIG, "Repair Windows"
but it wouldnt send out row 5 - "90430/RSO", "Repair Lights"
require 'rubygems'
require 'twilio-ruby'
require "csv"
def load_alarms
CSV.read 'alarms.csv', {col_sep: ';'}
end
def filter_by_event_type_and_severity(alarms, event_type, severity)
alarms.select do |alarm|
alarm[1] == event_type && alarm[2].to_i == severity.to_i
end
end
target_alarms = filter_by_event_type_and_severity(
load_alarms, 'medium', 2)
equipments = target_alarms.map { |alarm| [alarm[0], alarm[3]] }
p equipments
account_sid = 'ACCOUNT_ID'
auth_token = 'AUTH_TOKEN'
client = Twilio::REST::Client.new account_sid, auth_token
client.api.account.messages.create(
from: 'SENDER_PHONE',
to: 'TARGET_PHONE',
body: equipments
)

As i wrote in the comment, all you need to do is iterate over the equipments you got from the filter_by_event_type_and_severity method, and send them one by one with the twillo api:
require 'rubygems'
require 'twilio-ruby'
require "csv"
def load_alarms
CSV.read 'alarms.csv', {col_sep: ';'}
end
def filter_by_event_type_and_severity(alarms, event_type, severity)
alarms.select do |alarm|
alarm[1] == event_type && alarm[2].to_i == severity.to_i
end
end
target_alarms = filter_by_event_type_and_severity(load_alarms, 'medium', 2)
equipments = target_alarms.map { |alarm| [alarm[0], alarm[3]] }
account_sid = 'ACCOUNT_ID'
auth_token = 'AUTH_TOKEN'
client = Twilio::REST::Client.new account_sid, auth_token
# Here is the iteration
equipments.each do |equipment|
client.api.account.messages.create(
from: 'SENDER_PHONE',
to: 'TARGET_PHONE',
body: equipment
)
end
I removed your account_id, auth_token and phone numbers, so you need to add them back

Related

Ruby Google Drive API - 403 Forbidden on web_content_link

I can read and scan the files fine in a Google Drive, but I can't seem to access the web_content_link, no matter what I do. My Auth perms look fine. I'm at a complete loss.
I abstracted some of the Google Drive API logic to google_setup.rb.
And then in my rake file, all I want to do is access the download file. I seem to be able to scan through the files just fine, but even though, it looks to me like I should have perms to access the download link, I always get a 403 Forbidden error.
If you can be of any help, please let me know!
google_setup.rb
require 'google/apis/drive_v3'
require 'googleauth'
require 'googleauth/stores/file_token_store'
require 'fileutils'
require 'open-uri'
module GoogleSetup
OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze
def self.authorize
client_id = Google::Auth::ClientId.from_file Rails.root.join('lib', 'assets', 'credentials.json').freeze
token_store = Google::Auth::Stores::FileTokenStore.new file: 'token.yaml'
authorizer = Google::Auth::UserAuthorizer.new client_id, Google::Apis::DriveV3::AUTH_DRIVE, token_store
user_id = 'default'
credentials = authorizer.get_credentials user_id
if credentials.nil?
url = authorizer.get_authorization_url base_url: 'https://seeburg.herokuapp.com/'
puts 'Open the following URL in the browser and enter the ' \
"resulting code after authorization:\n" + url
code = ENV["GOOGLE_CODE"]
credentials = authorizer.get_and_store_credentials_from_code(
user_id: user_id, code: code, base_url: OOB_URI
)
end
drive_service = Google::Apis::DriveV3::DriveService.new
drive_service.client_options.application_name = 'Seeburg Google Drive Integration'
drive_service.authorization = credentials
drive_service
end
def self.get_files(query)
drive_service = GoogleSetup.authorize
files = []
#page_token = ''
while #page_token
begin
response = drive_service.list_files(page_size: 100, q: query, page_token: #page_token, fields: 'nextPageToken, files')
#page_token = response.next_page_token || false
if response.files.empty?
puts 'No files found'
else
files = response.files
end
sleep 0.5
rescue StandardError => e
puts e
end
end
files
end
end
test_google.rake
require 'google_setup'
require 'fileutils'
require 'open-uri'
desc 'Test Google Drive API'
task test_google: :environment do
folder_id = "1j1Ly_NveiCtfrolzSxmrbHS1DenPZagV";
query = "name contains 'MP3' and '#{folder_id}' in parents";
GoogleSetup.get_files(query).each do |file|
##If I can get this section to work, everything else I need will work
begin
puts download = URI.open(file.web_content_link)
rescue StandardError => e
puts e
end
end
end
It ended up being a timeout issue. Google only lets you take certain actions within a timeframe of authentication.

How could I handle rest-client 500 error response and keep scraping through my loop?

I need to scrape 10k URLs from this website and some of them are out of service (I think... it's an error that does not return the JSON I'm looking for, so rest-client returns 500 Internal Server error in my program)
Error syntax: `exception_with_response': 500 Internal Server Error (RestClient::InternalServerError)
To loop through the URLs, I'm using a range (1..30).each do |id|. I concatenate the URL with the current iteration of this range.
response = RestClient.get(url+id)
The problem is some times the URL I'm storing in the response variable does not exist and/or the webpage returns some error.
How could I protect my code so I can just pass through this problematic URL and keep the scraping?
Here's my current code (I put every code of the loop in a begin/rescue block, but I do not know how do write the code to do such thing):
require 'nokogiri'
require 'csv'
require 'rest-client'
require 'json'
link = "https://webfec.org.br/Utils/GetCentrobyId?cod="
CSV.open('data2.csv', 'ab') do |csv|
csv << ['Name', 'Street', 'Info', 'E-mail', 'Site']
(1..30).each do |id|
begin
response = RestClient.get(link+id.to_s)
json = JSON.parse(response)
html = json["Data"]
doc = Nokogiri::HTML.parse(html)
name = doc.xpath("/html/body/table/tbody/tr[1]").text
street = doc.xpath("/html/body/table/tbody/tr[2]").text.gsub(Regexp.union(REMOVER), " ")
info = doc.xpath("/html/body/table/tbody/tr[3]").text.gsub(Regexp.union(REMOVER), " ")
email = doc.xpath("/html/body/table/tbody/tr[4]").text.gsub(Regexp.union(REMOVER), " ")
site = doc.xpath("/html/body/table/tbody/tr[5]").text.gsub(Regexp.union(REMOVER), " ")
csv << [name, street, info, email, site]
rescue
end
end
end
You can see I put everything in the loop inside a begin block and there is the rescue block at the end but I'm kind lost on how do to such thing.
You should just rescue the exception for exmaple:
[*1..3].each{|i| RestClient.get('https://fooboton.free.beeceptor.com') rescue RestClient::InternalServerError; next}
So for your case do:
CSV.open('data2.csv', 'ab') do |csv|
csv << ['Name', 'Street', 'Info', 'E-mail', 'Site']
(1..30).each do |id|
begin
response = RestClient.get(link+id.to_s)
rescue RestClient::InternalServerError
next # skip this iteration in your loop
end
... # rest of your code

Hash/string gets escaped

This is my hyperresource client:
require 'rubygems'
require 'hyperresource'
require 'json'
api = HyperResource.new(root: 'http://127.0.0.1:9393/todos',
headers: {'Accept' => 'application/vnd.127.0.0.1:9393/todos.v1+hal+json'})
string = '{"todo":{"title":"test"}}'
hash = JSON.parse(string)
api.post(hash)
puts hash
The hash output is: {"todo"=>{"title"=>"test"}}
At my Sinatra with Roar API I have this post function:
post "/todos" do
params.to_json
puts params
#todo = Todo.new(params[:todo])
if #todo.save
#todo.extend(TodoRepresenter)
#todo.to_json
else
puts 'FAIL'
end
end
My puts 'params' over here gets: {"{\"todo\":{\"title\":\"test\"}}"=>nil}
I found out, these are 'escaped strings' but I don't know where it goes wrong.
EDIT:
I checked my api with curl and postman google extension, both work fine. It's just hyperresource I guess
You are posting JSON, ergo you either need to register a Sinatra middleware that will automatically parse incoming JSON requests, or you need to do it yourself.
require 'rubygems'
require 'hyperresource'
require 'json'
api = HyperResource.new(root: 'http://127.0.0.1:9393/todos',
headers: {'Accept' => 'application/vnd.127.0.0.1:9393/todos.v1+hal+json'})
string = '{"todo":{"title":"test"}}'
hash = JSON.parse(string)
api.post({:data => hash})
puts hash
---
post "/todos" do
p = JSON.parse(params[:data])
puts p.inspect
#todo = Todo.new(p[:todo])
if #todo.save
#todo.extend(TodoRepresenter)
#todo.to_json
else
puts 'FAIL'
end
end
Should do what you need.

Ruby gmail gem and storing credentials

I'm writing a very small program that I'd like to run on my RPI in a cron job. Every hour I want to check the status of a webpage. If the status meets a certain criteria I want it to email me.
In the past I have successfully used the gmail gem however I have always had to provide my credentials. I am nervous about storing my gmail credentials on file. Does anyone know how to accomplish this task more securely?
The end goal is I want an email in my inbox that tells me that a gate status has changed on the website I'm monitoring.
Here is what I have so far
#!/usr/bin/ruby
require 'open-uri'
require 'nokogiri'
def check_gates
doc = Nokogiri::HTML(open('http://www.summitatsnoqualmie.com/Mountains/Grooming-Report'))
gates = {}
table_rows = doc.xpath('//tr')
sections = []
sections.push({:gate => "Elevator", :data => table_rows.select { |tr| tr.inspect.include? "Lower Traverse" }.first})
sections.push({:gate => "Nash", :data => table_rows.select { |tr| tr.inspect.include? "Upper Traverse" }.first})
sections.each do |section|
status_text = section[:data].element_children.select { |child| child.inspect.include? "grooming_open_status" }.first.inspect
match = status_text.match(/background-position:\ (\d+)px\ (.\d)+px/)
gate_down = false
unless match.nil?
gate_down = match[1].to_i == 0 and match[2].to_i == 0
end
gates[section[:gate]] = gate_down ? "CLOSED" : "OPEN"
end
gates
end
Generate an application-specific password for your Google account, and store that password on the server.

Rho Mobile: Parse and create a model using JSON

I am able to parse a JSON using the following code
$httpresult = #params['body']
$jsonresult = Rho::JSON.parse($httpresult)
But I don't know how to create a model from $jsonresult.
First, using app_info you can print the result coming from the server to check if the response is valid JSON string.
Second, i think you must decode the url in order to parse it by using:
Rho::JSON.parse(Rho::RhoSupport.url_decode(#params['body']))
Once you've the data in json_result, you can put them in a pre-existing Model.
Supposing that you've already created a model with the name "Product", you can use transactions to speed up the process.
At the beginning of your module you've to require the model name:
require_source 'Product'
Then you can do this callback:
def get_callback
if #params['status'] == "ok"
json_result = Rho::JSON.parse(#params['body'])
db = ::Rho::RHO.get_src_db('Product')
db.start_transaction
Product.delete_all
begin
json_result.each do |item|
Product.create({:Brand => item["B rand"], :Name => item["Name"], :SKU => d["SKU"]})
end
db.commit
rescue Exception => e
trace_msg = e.backtrace.join("\n")
puts 'Application initialize failed: ' + e.inspect + ";Trace: #{trace_msg}"
db.rollback
end
WebView.navigate Rho::RhoConfig.start_path
else
WebView.navigate url_for :action => :show_error
end
end

Resources