OneSignal Hacker News Web Push Notifications. OneSignal+Algolia
This file contains 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
# This script runs every 5 minutes to send out Web Push | |
# notifications to subscribers about trending stories on Hacker News | |
# Technologies used: | |
# HTML5 Push API (http://w3c.github.io/push-api/) | |
# OneSignal (Web Push Notification delivery and SDK) | |
# Algolia (Provider of an excellent hacker news Search API) | |
# Ruby, Redis, Sidekiq, Sidetiq | |
require 'redis' | |
require 'json' | |
require 'rest-client' | |
class DemoNotifications | |
sidekiq_options :retry => false | |
# We use a Sidekiq (A background worker service) with Sidetiq (A sidekiq plugin for scheduling jobs) to run this every 5 minutes | |
include Sidekiq::Worker | |
include Sidetiq::Schedulable | |
recurrence { hourly.minute_of_hour(0,5,10,15,20,25,30,35,40,45,50,55) } | |
def perform(last_occurrence, current_occurrence) | |
return unless Rails.env == 'production' | |
# We use redis to store and check if we've already delivered this story to subscribers | |
redis = Redis.new | |
# Fetch stories created within the last 24 hours with at least 250 points | |
url = "https://hn.algolia.com/api/v1/search_by_date?numericFilters=points>=250,created_at_i>=#{Time.now.to_i - 60*60*24}" | |
puts "Fetching new story @ `#{url}`." | |
response = JSON.parse(RestClient.get(url)) | |
# Sort stories by how many points they have | |
hits = response['hits'].sort_by { |h| h['points'] } | |
count = 0 | |
hits.each do |hit| | |
unless redis.exists('hnstory:'+hit['objectID']) # Don't send the story to subscribers if we've already sent it | |
redis.setex('hnstory:'+hit['objectID'], 60*60*24*3, true) # Expire the data after a few days so we don't store it unnecessarily | |
puts "New top story: `#{hit['title']}`." | |
url = hit['url'] | |
url = "https://news.ycombinator.com/item?id=#{hit['objectID']}" if url.blank? # url is blank if it's a self post | |
create_notification( | |
hit['title'], | |
"#{unixTimestampToRelativeTime(hit['created_at_i'])}, #{hit['points']} points, #{hit['num_comments']} comments", | |
'https://onesignal.com/assets/demos/notification_ycombinator_logo.png', | |
url | |
) | |
count +=1 | |
end | |
end | |
if (count == 0) | |
puts 'No new top stories.' | |
end | |
end | |
def create_notification(title, body, icon, url) | |
params = { | |
'app_id' => 'e3b80c8e-3b06-11e5-a05d-df3641e92340', # Our OneSignal App ID that visitors have subscribed to | |
'contents' => {'en'=> body}, | |
'headings' => {'en'=> title}, | |
'isChromeWeb' => true, | |
'included_segments' => ['All'], | |
'chrome_web_icon' => icon, | |
'url' => url | |
} | |
headers = { | |
'Content-Type' => 'application/json', | |
'Authorization' => 'Basic [secret]', # OneSiganel Rest API secret key | |
} | |
begin | |
# Use the OneSignal API to send the story to all subscribers! | |
response = RestClient::Request.execute( | |
method: :post, | |
url: 'https://onesignal.com/api/v1/notifications', | |
payload: params, | |
headers: headers | |
) | |
puts "Send successful! \n\t #{response}" | |
rescue => e | |
puts e.inspect | |
end | |
end | |
def unixTimestampToRelativeTime(timestamp) | |
a = (Time.now-timestamp).to_i | |
case a | |
when 0 then | |
'just now' | |
when 1 then | |
'a second ago' | |
when 2..59 then | |
a.to_s+' seconds ago' | |
when 60..119 then | |
'a minute ago' #120 = 2 minutes | |
when 120..3540 then | |
(a/60).to_i.to_s+' minutes ago' | |
when 3541..7100 then | |
'an hour ago' # 3600 = 1 hour | |
when 7101..82800 then | |
((a+99)/3600).to_i.to_s+' hours ago' | |
when 82801..172000 then | |
'a day ago' # 86400 = 1 day | |
when 172001..518400 then | |
((a+800)/(60*60*24)).to_i.to_s+' days ago' | |
when 518400..1036800 then | |
'a week ago' | |
else | |
((a+180000)/(60*60*24*7)).to_i.to_s+' weeks ago' | |
end | |
end | |
end |
This file contains 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
<head> | |
<script src="https://onesignal.com/sdks/OneSignalSDK.js" async></script> | |
<link rel="manifest" href="manifest.json"> | |
<script> | |
var OneSignal = OneSignal || []; | |
OneSignal.push(["init", {path: '/', appId: "[OneSignal App]", autoRegister: true}]); | |
</script> | |
</head> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment