Class: Restaurants::SeoDataGeneratorWorker

Inherits:
ApplicationWorker show all
Defined in:
app/workers/restaurants/seo_data_generator_worker.rb

Instance Method Summary collapse

Methods inherited from ApplicationWorker

unlimited_retry

Instance Method Details

#perform(restaurant_id) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'app/workers/restaurants/seo_data_generator_worker.rb', line 5

def perform(restaurant_id)
  I18n.with_locale(:en) do
    restaurant = Restaurant.find(restaurant_id)
    name = restaurant.name
    cuisines = restaurant.restaurant_tags.where_category(:cuisine).map(&:title_format).to_sentence
    dining_styles = restaurant.restaurant_tags.where_category(:dining_style).map(&:title_format).to_sentence

    prompt = <<~PROMPT
      Hungry Hub is an online reservation application for the best restaurant offers in Thailand.
      Many of our restaurants lack SEO data. Please act as an SEO specialist to help us
      generate SEO titles, descriptions, and keywords in English and Thai so that this page
      can potentially become one of the top three results in their name search.

      Here is the name of the place: #{name}. It is a restaurant in #{restaurant.city.name} - #{restaurant.city.country.name}.
      #{name} is known #{cuisines} cuisines#{dining_styles.present? ? " and #{dining_styles} dining style" : ''}.

      1. Google search for me and provide an overview of the #{name}, including its main features, unique selling points, and any popular dishes or dining experiences it offers.
      2. Transcribe the data into the following JSON structure:

      {
        "restaurant_id": "#{restaurant_id}",
        "meta_title_en": "meta title in English, 50-60 characters, format: #{name} | Secondary Keyword - Descriptive Phrase | The location of the restaurant, for example Bangkok",
        "meta_description_en": "meta description in English, between 120 and 158 characters, the description need to attract people to choose Hungry Hub to access this restaurant, like what low price number does Hungry Hub offer",
        "description_en": "SEO description in English, more than 100 words",
        "keywords_en": "SEO keywords in English",
        "meta_title_th": "SEO title in Thai, 50-60 characters, format: #{name} | Secondary Keyword - Descriptive Phrase | The location of the restaurant, for example Bangkok",
        "meta_description_th": "meta description in Thai, between 120 and 158 characters, the description need to attract people to choose Hungry Hub to access this restaurant, like what low price number does Hungry Hub offer",
        "description_th": "SEO description in Thai, more than 100 words",
        "keywords_th": "SEO keywords in Thai"
        "meta_title_cn": "SEO title in Chinese, 50-60 characters, format: #{name} | Secondary Keyword - Descriptive Phrase | The location of the restaurant, for example Bangkok",
        "meta_description_cn": "meta description in Chinese, between 120 and 158 characters, the description need to attract people to choose Hungry Hub to access this restaurant, like what low price number does Hungry Hub offer",
        "description_cn": "SEO description in Chinese, more than 100 words",
        "keywords_cn": "SEO keywords in Chinese"
      }

      Please ensure the output is in valid JSON format and contains no extra text or explanations
    PROMPT

    faraday = OpenrouterClient.create_connection

    response = faraday.post('/api/v1/chat/completions') do |req|
      req.body = {
        model: AdminSetting.openrouter_model,
        messages: [{ role: 'user', content: prompt }],
        response_format: { type: 'json_object' },
      }.to_json
    end

    if response.success?
      response_data = JSON.parse(response.body)
      json_string = response_data.dig('choices', 0, 'message', 'content')

      # Sanitize and validate JSON string
      json_string = json_string&.gsub("```json\n", '')&.gsub("\n```", '')

      if json_string.nil? || json_string.strip.empty?
        raise "Empty or missing JSON content for #{restaurant_id}: #{response.body}"
      end

      begin
        json_data = JSON.parse(json_string)
        save_data(restaurant, json_data)
      rescue JSON::ParserError => e
        raise "Invalid JSON response for #{restaurant_id}: #{json_string}, Error: #{e.message}"
      end
    else
      raise "HTTP error occurred: #{response.status} - #{response.body}"
    end
  end
end