151 lines
4.2 KiB
Ruby
151 lines
4.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# CountryHelper - Service for country display utilities
|
|
#
|
|
# Provides methods to convert ISO country codes to display names,
|
|
# generate country flags, and format country data for UI components.
|
|
class CountryHelper
|
|
# Convert ISO code to display name
|
|
def self.display_name(iso_code)
|
|
return iso_code if iso_code.blank?
|
|
|
|
country = ISO3166::Country[iso_code]
|
|
country.local_name
|
|
rescue
|
|
iso_code
|
|
end
|
|
|
|
# Convert ISO code to flag emoji
|
|
def self.flag_emoji(iso_code)
|
|
return "" if iso_code.blank? || iso_code.length != 2
|
|
|
|
# Convert each letter to regional indicator symbol (A + 0x1F1E5)
|
|
iso_code.upcase.codepoints.map { |code| (code + 0x1F1E5).chr }.join
|
|
rescue
|
|
""
|
|
end
|
|
|
|
# Display name with flag
|
|
def self.display_with_flag(iso_code)
|
|
return iso_code if iso_code.blank?
|
|
|
|
"#{display_name(iso_code)} (#{iso_code})"
|
|
end
|
|
|
|
# Check if ISO code is valid
|
|
def self.valid_iso_code?(iso_code)
|
|
return false if iso_code.blank?
|
|
|
|
ISO3166::Country[iso_code].present?
|
|
rescue
|
|
false
|
|
end
|
|
|
|
# Get all countries for select dropdowns
|
|
# Returns array of [display_name, iso_code] pairs
|
|
def self.all_for_select
|
|
ISO3166::Country.all.map do |country|
|
|
# Try different name sources in order of preference
|
|
# Use the proper countries gem methods
|
|
name = country.local_name.presence ||
|
|
country.iso_short_name.presence ||
|
|
country.common_name.presence ||
|
|
country.alpha2
|
|
display_name = "#{name} (#{country.alpha2})"
|
|
[display_name, country.alpha2]
|
|
end.sort_by { |name, _| name }
|
|
rescue => e
|
|
puts "Error in CountryHelper.all_for_select: #{e.message}"
|
|
puts e.backtrace
|
|
[]
|
|
end
|
|
|
|
|
|
# Get countries by common regions for quick selection
|
|
def self.by_region
|
|
{
|
|
'Americas' => [
|
|
'US', 'CA', 'MX', 'BR', 'AR', 'CL', 'CO', 'PE', 'VE'
|
|
],
|
|
'Europe' => [
|
|
'GB', 'DE', 'FR', 'IT', 'ES', 'NL', 'BE', 'CH', 'AT', 'SE',
|
|
'NO', 'DK', 'FI', 'PL', 'CZ', 'HU', 'RO', 'GR', 'PT'
|
|
],
|
|
'Asia Pacific' => [
|
|
'CN', 'JP', 'KR', 'IN', 'SG', 'AU', 'NZ', 'TH', 'MY', 'ID',
|
|
'PH', 'VN', 'HK', 'TW'
|
|
],
|
|
'Middle East & Africa' => [
|
|
'ZA', 'EG', 'NG', 'KE', 'SA', 'AE', 'IL', 'TR', 'IR'
|
|
]
|
|
}
|
|
rescue
|
|
{}
|
|
end
|
|
|
|
# Get countries for specific region with display names
|
|
def self.countries_for_region(region_name)
|
|
country_codes = by_region[region_name] || []
|
|
|
|
country_codes.map do |code|
|
|
{
|
|
code: code,
|
|
name: display_name(code),
|
|
display: display_with_flag(code)
|
|
}
|
|
end
|
|
end
|
|
|
|
# Format multiple country targets for display
|
|
def self.format_targets(targets)
|
|
return [] if targets.blank?
|
|
|
|
targets.map do |target|
|
|
{
|
|
code: target,
|
|
name: display_name(target),
|
|
display: display_with_flag(target)
|
|
}
|
|
end
|
|
end
|
|
|
|
# Get popular countries for quick blocking (common threat sources)
|
|
def self.popular_for_blocking
|
|
[
|
|
{ code: 'CN', name: 'China', display: '🇨🇳 China', reason: 'High bot/scanner activity' },
|
|
{ code: 'RU', name: 'Russia', display: '🇷🇺 Russia', reason: 'State-sponsored attacks' },
|
|
{ code: 'IN', name: 'India', display: '🇮🇳 India', reason: 'High spam volume' },
|
|
{ code: 'BR', name: 'Brazil', display: '🇧🇷 Brazil', reason: 'Scanner activity' },
|
|
{ code: 'IR', name: 'Iran', display: '🇮🇷 Iran', reason: 'Attacks on critical infrastructure' },
|
|
{ code: 'KP', name: 'North Korea', display: '🇰🇵 North Korea', reason: 'State-sponsored hacking' }
|
|
]
|
|
end
|
|
|
|
# Search countries by name or code
|
|
def self.search(query)
|
|
return [] if query.blank?
|
|
|
|
query = query.downcase
|
|
ISO3166::Country.all.select do |country|
|
|
country.alpha2.downcase.include?(query) ||
|
|
country.local_name.downcase.include?(query)
|
|
end.first(20).map { |c| [display_with_flag(c.alpha2), c.alpha2] }
|
|
rescue
|
|
[]
|
|
end
|
|
|
|
# Country statistics for analytics
|
|
def self.usage_statistics(country_codes)
|
|
return {} if country_codes.blank?
|
|
|
|
stats = {}
|
|
country_codes.each do |code|
|
|
stats[code] = {
|
|
name: display_name(code),
|
|
flag: flag_emoji(code),
|
|
display: display_with_flag(code)
|
|
}
|
|
end
|
|
stats
|
|
end
|
|
end |