# Terminal
bundle add cupsffi
bundle add dotenv-rails
bundle add rufus-scheduler
WORKER=true bin/rails s
rails g model tweet tweet_id:integer:index tweeted_at:datetime username content:text printed:boolean
# irb
CupsPPD.new("Brother_QL_810W", nil).options
# .env
USER_ID=your-id-here
BEARER_TOKEN=your-token-here
# config/application.rb
Dotenv::Railtie.load
# config/initializers/cron.rb
require 'rufus/scheduler'
scheduler = Rufus::Scheduler.new
scheduler.every '1m' do
Twitter.fetch if ENV['WORKER']
end
# models/printer.rb
require 'cupsffi'
class Printer
def self.print(id)
new(id).print
end
def initialize(id)
@id = id
end
def print
job = printer.print_data(text, "text/plain", options)
loop do
puts job.status
break unless [:pending, :processing].include?(job.status)
sleep 1
end
tweet.update(printed: true) if job.status == :completed
end
private
def tweet
@tweet ||= Tweet.find(@id)
end
def message
[tweet.username, "said on", tweet.tweeted_at, ":", tweet.content].join(" ")
end
def printer
# printers = CupsPrinter.get_all_printer_names
# Brother_QL_810W
@printer ||= CupsPrinter.new("Brother_QL_810W")
end
def options
{
'cupsPrintQuality': 'High',
'MediaType': 'roll',
'PageSize': "Custom.#{width}x#{height}mm"
}
end
def width
62
end
def height
(text_array.size * 7).to_i
end
def text_array
message.scan(/(.{1,22})(?:\s|$)/m)
end
def text
"\r\n #{text_array.join("\r\n ")}".encode(
"ascii",
invalid: :replace,
undef: :replace,
replace: ''
)
end
end
# models/twitter.rb
require 'net/http'
class Twitter
USER_ID = ENV["USER_ID"]
BEARER_TOKEN = ENV["BEARER_TOKEN"]
def self.fetch
new.fetch
end
def fetch
Rails.logger.info "Fetching tweets #{Time.current}"
return if tweets['data'].nil?
tweets['data'].reverse.each do |tweet|
user = tweets.dig('includes', 'users').find { |u| u['id'] == tweet['author_id'] }
record = Tweet.find_or_create_by(
tweet_id: tweet['id'],
tweeted_at: tweet['created_at'],
username: user['name'],
content: tweet['text']
)
next if record.printed?
Printer.new(record.id).print
end
end
private
def tweets
@tweets ||= begin
uri = URI(url)
request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer #{BEARER_TOKEN}"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
JSON.parse(response.body)
end
end
def url
params = []
params << "tweet.fields=created_at"
params << "expansions=author_id"
params << "since_id=#{last_tweet_id}" if last_tweet_id
"https://api.twitter.com/2/users/#{USER_ID}/mentions?#{params.join("&")}"
end
def last_tweet_id
@last_tweet_id ||= Tweet.order(tweet_id: :desc).first&.tweet_id
end
end