Krzysztof Kotlarek e2f9b7dd6f FIX: Narrative Bot certificates are ERB templates (#8174)
There are at least two ways of rendering templates outside of the controller. The first one is Rails way enabled with Rails 5 https://evilmartians.com/chronicles/new-feature-in-rails-5-render-views-outside-of-actions
The downside of this method is that all variables need to be passed as params (I could find a way to pass the whole context)

Another way is to use instance_eval described in Erubi documentation
https://github.com/jeremyevans/erubi#usage - it works perfectly fine, however, I didn't feel very confident about using eval unless necessary.

An additional benefit of using `ApplicationController.render` is that if Rails would change the ERB engine in the future, this code should still work.

If you want to test it on your local, you need to be signed in and then that two URLs are generating certificates:
http://localhost:3000/discobot/certificate.svg?date=Oct+07+2019&type=standard&user_id=1
http://localhost:3000/discobot/certificate.svg?date=Oct+07+2019&type=advanced&user_id=1

Dev: https://dev.discourse.org/t/discourse-narrative-bot-should-not-be-storing-giant-strings/17130
2019-10-09 17:45:01 +11:00

93 lines
2.8 KiB
Ruby

# frozen_string_literal: true
module DiscourseNarrativeBot
class CertificateGenerator
def initialize(user, date)
@user = user
date =
begin
Date.parse(date)
rescue ArgumentError => e
if e.message == 'invalid date'
Date.parse(Date.today.to_s)
else
raise e
end
end
@date = I18n.l(date, format: :date_only)
@discobot_user = User.find(-2)
end
def new_user_track
width = 538.583 # Default width for the SVG
ApplicationController.render(inline: File.read(File.expand_path('../templates/new_user.svg.erb', __FILE__)),
assigns: { width: width,
discobot_user: @discobot_user,
date: @date,
avatar_url: base64_image_link(avatar_url),
logo_group: logo_group(55, width, 350),
name: name })
end
def advanced_user_track
width = 722.8 # Default width for the SVG
ApplicationController.render(inline: File.read(File.expand_path('../templates/advanced_user.svg.erb', __FILE__)),
assigns: { width: width,
discobot_user: @discobot_user,
date: @date,
avatar_url: base64_image_link(avatar_url),
logo_group: logo_group(40, width, 280),
name: name })
end
private
def name
@user.username.titleize
end
def logo_group(size, width, height)
return unless SiteSetting.site_logo_small_url.present?
begin
uri = URI(SiteSetting.site_logo_small_url)
logo_uri =
if uri.host.blank? || uri.scheme.blank?
URI("#{Discourse.base_url}/#{uri.path}")
else
uri
end
<<~URL
<g transform="translate(#{width / 2 - (size / 2)} #{height})">
<image height="#{size}px" width="#{size}px" #{base64_image_link(logo_uri)}/>
</g>
URL
rescue URI::InvalidURIError
''
end
end
def base64_image_link(url)
if image = fetch_image(url)
"xlink:href=\"data:image/png;base64,#{Base64.strict_encode64(image)}\""
else
""
end
end
def fetch_image(url)
URI(url).open('rb', redirect: true, allow_redirections: :all).read
rescue OpenURI::HTTPError
# Ignore if fetching image returns a non 200 response
end
def avatar_url
UrlHelper.absolute(Discourse.base_uri + @user.avatar_template.gsub('{size}', '250'))
end
end
end