diff --git a/app/models/user.rb b/app/models/user.rb index a98a9ee..a2beb0a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -16,6 +16,7 @@ class User < ApplicationRecord validates :full_name, presence: true validate :ensure_username_presence validates :avatar_border, inclusion: { in: ['white', 'black', 'none', 'rainbow', 'rainbow-overlay'] } + validates :avatar, format: { with: /\A(https?:\/\/).*\z/i, message: "must be a valid URL" }, allow_blank: true after_save :generate_open_graph_image, unless: -> { Rails.env.test? } after_save :download_and_store_avatar @@ -39,27 +40,29 @@ def generate_open_graph_image end def download_and_store_avatar - return if avatar.blank? || !avatar.start_with?('http') - + return if avatar.blank? + require 'open-uri' require 'fileutils' - + begin avatar_dir = Rails.root.join('public', 'avatars') FileUtils.mkdir_p(avatar_dir) unless File.directory?(avatar_dir) - + file = URI.open(avatar) - + filename = "#{username}_avatar#{File.extname(avatar)}" filepath = File.join(avatar_dir, filename) - + File.open(filepath, 'wb') do |local_file| local_file.write(file.read) end - + Rails.logger.info "Avatar downloaded for user #{username}" rescue StandardError => e Rails.logger.error "Failed to download avatar for user #{username}: #{e.message}" + self.avatar = 'greg.jpg' # Set to default avatar instead of nil + save(validate: false) # Save without triggering validations end end diff --git a/app/services/open_graph_image_generator.rb b/app/services/open_graph_image_generator.rb index 29aae56..5006a89 100644 --- a/app/services/open_graph_image_generator.rb +++ b/app/services/open_graph_image_generator.rb @@ -1,3 +1,4 @@ +# app/services/open_graph_image_generator.rb class OpenGraphImageGenerator IMAGE_WIDTH = 1200 IMAGE_HEIGHT = 630 @@ -12,7 +13,8 @@ def generate template_path = Rails.root.join('app', 'assets', 'images', 'og_template.png') output_path = Rails.root.join('public', 'uploads', 'og_images', "#{@user.username}_og.png") image = MiniMagick::Image.open(template_path) - avatar = download_image(@user.avatar) + + avatar = @user.avatar.present? ? download_image(@user.avatar) : default_avatar # Resize avatar and add a white square border avatar.resize "#{AVATAR_SIZE}x#{AVATAR_SIZE}" @@ -60,11 +62,46 @@ def download_image(url) end rescue OpenURI::HTTPError, Errno::ENOENT, SocketError => e Rails.logger.error("Failed to download image from URL: #{url}. Error: #{e.message}. Using default image.") - # Use a default image if the download fails - default_image_path = Rails.root.join('app', 'assets', 'images', 'greg.jpg') - tempfile.write(File.read(default_image_path)) + tempfile.write(File.read(default_avatar_path)) end tempfile.rewind MiniMagick::Image.open(tempfile.path) end + + def default_avatar + MiniMagick::Image.open(default_avatar_path) + end + + def default_avatar_path + Rails.root.join('app', 'assets', 'images', 'greg.jpg') + end end + +# Console script to fix avatars and update open graph images +def fix_avatars_and_update_og_images + User.where("avatar IS NOT NULL AND avatar != ''").each do |user| + puts "Processing user: #{user.username}" + + if !user.avatar.start_with?('http://', 'https://') + puts " Invalid avatar URL, resetting to greg.jpg" + user.update_column(:avatar, 'greg.jpg') + end + + begin + puts " Downloading and storing avatar" + user.download_and_store_avatar + + puts " Generating open graph image" + OpenGraphImageGenerator.new(user).generate + + puts " Successfully processed user: #{user.username}" + rescue => e + puts " Error processing user #{user.username}: #{e.message}" + end + + puts "\n" # Add a newline for readability between users + end +end + +# Run the fix +fix_avatars_and_update_og_images \ No newline at end of file