nblog_duo 111.119.999 → 111.120.002

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nblog_duo.rb +374 -209
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d42f64c6be0d3a05373c4e4980a9a4db2696859954fbd88233e6bfd2144f378
4
- data.tar.gz: 878cab8fd8782e887b6af6424d4882a8c1a17ced7e17027e852f020789adb089
3
+ metadata.gz: 92d60eb5158a9850b865e0f0610181c13e6a90968e27e8ab32667a3bcbcd51ae
4
+ data.tar.gz: 68ca780336905933aeb6584b78944eb437524209d48fa65508fe0e966f599981
5
5
  SHA512:
6
- metadata.gz: 9871f2ac734659c19736ff7eca3839970e7a14562140354fc0554b6c3da6723dc9fa1827e0a16efee14d4384f2b12f0693bb7abb6d93801c5ec0a5cab693c3f2
7
- data.tar.gz: b467c9de33de09999a3e8718204b6a3070146935eaf99fb044a5f3aa10ad6c5e1c27d43d3ce9b528e876a570ec7325b7b8a2eeb3dfa5f01d2c3eb3b2c925b260
6
+ metadata.gz: 654a707ff0466ecdd152c4983dbcc8a31e2ad073fe1839b2a8d89574161b2189676f8908fda768bb667d87fe814734851ed03be1bfd0589d5abdba8eb72d738f
7
+ data.tar.gz: 9a539dfd8d82121f8eb79c313be8d1d5f54ffc86cc436fbcc26f420aaf955d532e555c095d8dcb55cd8dc68e721764b67da959ef4f67c459b0b9c9907e3cfd4a
data/lib/nblog_duo.rb CHANGED
@@ -24,13 +24,14 @@ using Rainbow
24
24
  include Glimmer
25
25
 
26
26
  class Chat
27
- def initialize(api_key, gpt_keyword_prompt)
27
+ def initialize(api_key, gpt_keyword_prompt, model)
28
28
  @api_key = api_key
29
29
  @gpt_keyword_prompt = gpt_keyword_prompt
30
+ @model = model # 모델을 인자로 받도록 수정
30
31
  end
31
32
 
32
33
  def message(keyword)
33
- puts 'Sending request to GPT...(키워드 기반 글 생성 중...)'
34
+ puts 'Sending request to GPT...(키워드 기반 글 생성 중...)'.cyan
34
35
 
35
36
  # "키워드 기반 글 생성 중..." 메시지 출력 스레드
36
37
  thread = Thread.new do
@@ -54,7 +55,7 @@ class Chat
54
55
 
55
56
  # 요청 데이터 설정
56
57
  data = {
57
- 'model' => 'gpt-4',
58
+ 'model' => @model,
58
59
  'messages' => [
59
60
  {
60
61
  "role" => "assistant",
@@ -64,9 +65,10 @@ class Chat
64
65
  'max_tokens' => max_response_tokens # 최대 응답 토큰 설정
65
66
  }
66
67
 
67
-
68
-
69
68
  answer = ''
69
+ retry_count = 0
70
+ max_retries = 5 # 최대 재시도 횟수
71
+
70
72
  begin
71
73
  req = HTTP.headers(headers).post(url, :json => data)
72
74
 
@@ -77,7 +79,6 @@ class Chat
77
79
 
78
80
  # 응답 내용 출력 (디버깅용)
79
81
  response = JSON.parse(req.to_s)
80
-
81
82
 
82
83
  # 응답 데이터에서 안전하게 값 추출
83
84
  if response['choices'] && response['choices'][0] && response['choices'][0]['message']
@@ -88,14 +89,21 @@ class Chat
88
89
  rescue => e
89
90
  # 오류 메시지 출력
90
91
  puts "Error occurred: #{e.message}"
91
- answer = "오류가 발생했습니다."
92
+ if e.message.include?('502') && retry_count < max_retries
93
+ retry_count += 1
94
+ puts "Retrying... Attempt ##{retry_count}"
95
+ sleep(5) # 잠시 대기 후 재시도
96
+ retry
97
+ else
98
+ answer = "오류가 발생했습니다."
99
+ end
92
100
  end
93
101
 
94
102
  # "생성 중..." 메시지 출력 종료
95
103
  thread.kill
96
104
 
97
105
  # 결과 로그 출력
98
- puts "Final API response ==> #{answer}"
106
+ puts "Final API response ==> #{answer}".cyan
99
107
  return answer
100
108
  end
101
109
 
@@ -108,16 +116,16 @@ end
108
116
 
109
117
 
110
118
 
111
-
112
-
113
119
  class Chat_title
114
- def initialize(api_key, gpt_title_prompt)
120
+ def initialize(api_key, gpt_title_prompt, model)
115
121
  @api_key = api_key
116
122
  @gpt_title_prompt = gpt_title_prompt
123
+ @model = model # 모델을 인자로 받도록 수정
117
124
  end
118
125
 
119
126
  def message(title)
120
- puts 'Sending request to GPT...(제목 생성 중...)'
127
+ puts 'Sending request to GPT...(제목 생성 중...)'.cyan
128
+
121
129
  # "키워드 기반 글 생성 중..." 메시지를 별도 스레드로 처리
122
130
  thread = Thread.new do
123
131
  while true
@@ -125,13 +133,15 @@ class Chat_title
125
133
  sleep(3)
126
134
  end
127
135
  end
136
+
128
137
  url = 'https://api.openai.com/v1/chat/completions'
129
138
  headers = {
130
139
  'Content-Type' => 'application/json',
131
140
  'Authorization' => 'Bearer ' + @api_key
132
141
  }
142
+
133
143
  data = {
134
- 'model' => 'gpt-4',
144
+ 'model' => @model,
135
145
  'messages' => [{
136
146
  "role" => "system",
137
147
  "content" => "너는 매우 친절하고 성의 있게 답변하는 AI 어시스턴트야."
@@ -142,11 +152,14 @@ class Chat_title
142
152
  }]
143
153
  }
144
154
 
155
+ answer = ''
156
+ retry_count = 0
157
+ max_retries = 5 # 최대 재시도 횟수
158
+
145
159
  begin
146
160
  req = HTTP.headers(headers).post(url, json: data)
147
161
 
148
162
  response = JSON.parse(req.body.to_s)
149
-
150
163
 
151
164
  if req.status == 429
152
165
  return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
@@ -161,28 +174,37 @@ class Chat_title
161
174
  answer ||= title # 응답이 없을 경우 기본 메시지 설정
162
175
  rescue => e
163
176
  puts "Error: #{e.message}"
164
- answer = "오류가 발생했습니다."
177
+ if e.message.include?('502') && retry_count < max_retries
178
+ retry_count += 1
179
+ puts "Retrying... Attempt ##{retry_count}"
180
+ sleep(5) # 잠시 대기 후 재시도
181
+ retry
182
+ else
183
+ answer = "오류가 발생했습니다."
184
+ end
165
185
  end
166
186
 
167
187
  # "생성 중..." 메시지 출력 종료
168
188
  thread.kill
169
189
 
170
- puts 'API return ==> '
171
- puts answer
190
+ puts 'API return ==> '.cyan
191
+ puts answer.cyan
172
192
  answer
173
193
  end
174
194
  end
175
195
 
176
196
 
177
197
  class Chat_content
178
- def initialize(api_key, gpt_content_prompt)
198
+ def initialize(api_key, gpt_content_prompt, model)
179
199
  @api_key = api_key
180
200
  @gpt_content_prompt = gpt_content_prompt
201
+ @model = model # 모델을 인자로 받도록 수정
181
202
  end
182
203
 
183
204
  def message(content)
184
- puts '주의:GPT 특성상 원고 길이가 공백 포함 4천자를 넘기면 오류가 발생할 수 있습니다.'
185
- puts 'Sending request to GPT...(내용 변형 중...)'
205
+ puts '주의:GPT 특성상 원고 길이가 공백 포함 4천자를 넘기면 오류가 발생할 수 있습니다.'.cyan
206
+ puts 'Sending request to GPT...(내용 변형 중...)'.cyan
207
+
186
208
  # "키워드 기반 글 생성 중..." 메시지를 별도 스레드로 처리
187
209
  thread = Thread.new do
188
210
  while true
@@ -190,14 +212,15 @@ class Chat_content
190
212
  sleep(3)
191
213
  end
192
214
  end
193
-
215
+
194
216
  url = 'https://api.openai.com/v1/chat/completions'
195
217
  headers = {
196
218
  'Content-Type' => 'application/json',
197
219
  'Authorization' => 'Bearer ' + @api_key
198
220
  }
221
+
199
222
  data = {
200
- 'model' => 'gpt-4',
223
+ 'model' => @model,
201
224
  'messages' => [{
202
225
  "role" => "system",
203
226
  "content" => "너는 매우 친절하고 성의 있게 답변하는 AI 어시스턴트야."
@@ -205,16 +228,18 @@ class Chat_content
205
228
  {
206
229
  "role" => "user",
207
230
  "content" => "#{@gpt_content_prompt}\n#{content}"
208
-
209
231
  }]
210
232
  }
211
233
 
234
+ answer = ''
235
+ retry_count = 0
236
+ max_retries = 5 # 최대 재시도 횟수
237
+
212
238
  begin
213
239
  req = HTTP.headers(headers).post(url, json: data)
214
240
 
215
241
  response = JSON.parse(req.body.to_s)
216
-
217
-
242
+
218
243
  if req.status == 429
219
244
  return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
220
245
  end
@@ -224,20 +249,28 @@ class Chat_content
224
249
  answer ||= (content) # 응답이 없을 경우 기본 메시지 설정
225
250
  rescue => e
226
251
  puts "Error: #{e.message}"
227
- answer = "오류가 발생했습니다."
252
+ if e.message.include?('502') && retry_count < max_retries
253
+ retry_count += 1
254
+ puts "Retrying... Attempt ##{retry_count}"
255
+ sleep(5) # 잠시 대기 후 재시도
256
+ retry
257
+ else
258
+ answer = "오류가 발생했습니다."
259
+ end
228
260
  end
229
261
 
230
262
  # "생성 중..." 메시지 출력 종료
231
263
  thread.kill
232
264
 
233
- puts 'API return ==> '
234
- puts answer
265
+ puts 'API return ==> '.cyan
266
+ puts answer.cyan
235
267
  answer
236
268
  end
237
269
  end
238
270
 
239
271
 
240
272
 
273
+
241
274
  #############################################gpt############################################
242
275
 
243
276
  class Naver
@@ -2279,83 +2312,111 @@ class Wordpress
2279
2312
  return @data2
2280
2313
  end
2281
2314
 
2282
- def auto_image(keyword = nil)
2283
- keyword ||= @keyword
2284
- puts "키워드: #{keyword}"
2285
-
2286
- client = HTTPClient.new
2287
- client.default_header = {
2288
- 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
2289
- '(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
2290
- 'Accept' => 'application/json, text/javascript, */*; q=0.01',
2291
- 'Accept-Language' => 'en-US,en;q=0.9',
2292
- 'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
2293
- 'X-Requested-With' => 'XMLHttpRequest'
2294
- }
2315
+ def crop_image_height_under_width(path, min_crop_ratio = 0.625)
2316
+ img = Magick::Image.read(path).first
2317
+ width = img.columns
2318
+ height = img.rows
2295
2319
 
2296
- retry_count = 0
2297
- max_retries = 10
2298
- results = []
2299
2320
 
2300
- begin
2301
- page = rand(1..15)
2302
- url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
2303
- puts "Request URL: #{url}"
2304
- res = client.get(url)
2305
-
2306
- unless res.status == 200
2307
- puts "HTTP Error: #{res.status}"
2308
- raise "HTTP Error"
2309
- end
2310
2321
 
2311
- json = JSON.parse(res.body)
2312
- results = json['results']
2313
- mm = []
2322
+ if height > width
2323
+ min_height = (width * min_crop_ratio).to_i
2324
+ new_height = rand(min_height..width)
2325
+ crop_top = ((height - new_height) / 2.0).round
2314
2326
 
2315
- results.each do |photo|
2316
- full_url = photo.dig('urls', 'full').to_s
2317
- regular_url = photo.dig('urls', 'regular').to_s
2327
+ cropped = img.crop(0, crop_top, width, new_height, true)
2328
+ cropped.write(path)
2318
2329
 
2319
- if full_url.start_with?("https://images.unsplash.com/photo-") &&
2320
- regular_url.include?("1080")
2321
- mm << full_url
2322
- end
2323
- end
2330
+
2331
+ else
2332
+
2333
+ end
2334
+ end
2324
2335
 
2325
- if mm.empty?
2326
- raise "No matching image"
2327
- end
2336
+ def auto_image(keyword = nil)
2337
+ # auto_image 내부에서만 crop 호출
2338
+ keyword ||= @keyword
2339
+ puts "키워드: #{keyword}"
2340
+
2341
+ client = HTTPClient.new
2342
+ client.default_header = {
2343
+ 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
2344
+ '(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
2345
+ 'Accept' => 'application/json, text/javascript, */*; q=0.01',
2346
+ 'Accept-Language' => 'en-US,en;q=0.9',
2347
+ 'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
2348
+ 'X-Requested-With' => 'XMLHttpRequest'
2349
+ }
2350
+
2351
+ retry_count = 0
2352
+ max_retries = 10
2353
+ results = []
2354
+
2355
+ begin
2356
+ page = rand(1..15)
2357
+ url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
2358
+ puts "Request URL: #{url}"
2359
+ res = client.get(url)
2360
+
2361
+ unless res.status == 200
2362
+ puts "HTTP Error: #{res.status}"
2363
+ raise "HTTP Error"
2364
+ end
2328
2365
 
2329
- selected_url = mm.sample
2330
- Down.download(selected_url, destination: "./image/memory.png")
2331
- puts "이미지 다운로드 완료: #{selected_url}"
2366
+ json = JSON.parse(res.body)
2367
+ results = json['results']
2368
+ mm = []
2332
2369
 
2333
- rescue => e
2334
- retry_count += 1
2335
- puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
2336
- sleep(3)
2337
- if retry_count < max_retries
2338
- retry
2339
- else
2340
- puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
2341
-
2342
- if results && !results.empty?
2343
- random_photo = results.sample
2344
- fallback_url = random_photo.dig('urls', 'full')
2345
- if fallback_url
2346
- Down.download(fallback_url, destination: "./image/memory.png")
2347
- puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
2348
- else
2349
- puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
2350
- color_image
2351
- end
2370
+ results.each do |photo|
2371
+ full_url = photo.dig('urls', 'full').to_s
2372
+ regular_url = photo.dig('urls', 'regular').to_s
2373
+
2374
+ if full_url.start_with?("https://images.unsplash.com/photo-") &&
2375
+ regular_url.include?("1080")
2376
+ mm << full_url
2377
+ end
2378
+ end
2379
+
2380
+ if mm.empty?
2381
+ raise "No matching image"
2382
+ end
2383
+
2384
+ selected_url = mm.sample
2385
+ destination_path = "./image/memory.png"
2386
+ Down.download(selected_url, destination: destination_path)
2387
+ puts "이미지 다운로드 완료: #{selected_url}"
2388
+
2389
+ # 오직 auto_image에서만 자르기 호출
2390
+ crop_image_height_under_width(destination_path)
2391
+
2392
+ rescue => e
2393
+ retry_count += 1
2394
+ puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
2395
+ sleep(3)
2396
+ if retry_count < max_retries
2397
+ retry
2398
+ else
2399
+ puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
2400
+
2401
+ if results && !results.empty?
2402
+ random_photo = results.sample
2403
+ fallback_url = random_photo.dig('urls', 'full')
2404
+ if fallback_url
2405
+ Down.download(fallback_url, destination: "./image/memory.png")
2406
+ puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
2407
+ crop_image_height_under_width("./image/memory.png")
2352
2408
  else
2353
- puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
2354
- color_image
2355
- end
2409
+ puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
2410
+ color_image
2356
2411
  end
2412
+ else
2413
+ puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
2414
+ color_image
2415
+ end
2357
2416
  end
2358
2417
  end
2418
+ end
2419
+
2359
2420
 
2360
2421
  def color_image
2361
2422
  color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
@@ -2449,56 +2510,103 @@ class Wordpress
2449
2510
  end
2450
2511
 
2451
2512
 
2452
- def image_text(text1, text2)
2513
+ def image_text(text1, text2)
2514
+ begin
2515
+ color = File.open('./color.ini', 'r', encoding: 'utf-8').read.split("\n").map(&:strip).reject(&:empty?)
2516
+ font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
2517
+ font2 = './fonts/' + font_files.sample
2518
+
2519
+ # 랜덤 글자색 선택
2520
+ color2 = color.sample
2521
+
2522
+ # 헬퍼 함수: 색상 문자열 '#RRGGBB' -> [R,G,B] 배열로 변환
2523
+ def hex_to_rgb(hex)
2524
+ hex = hex.delete('#')
2525
+ [hex[0..1], hex[2..3], hex[4..5]].map { |c| c.to_i(16) }
2526
+ end
2527
+
2528
+ # 헬퍼 함수: 두 RGB 색상의 차이 계산 (간단한 유클리드 거리)
2529
+ def color_distance(c1, c2)
2530
+ Math.sqrt(
2531
+ (c1[0] - c2[0])**2 +
2532
+ (c1[1] - c2[1])**2 +
2533
+ (c1[2] - c2[2])**2
2534
+ )
2535
+ end
2536
+
2537
+ # 대비가 충분히 되는 테두리 색상 선택
2538
+ max_attempts = 10
2539
+ stroke_color = nil
2540
+ base_rgb = hex_to_rgb(color2)
2541
+
2542
+ max_attempts.times do
2543
+ candidate = color.sample
2544
+ candidate_rgb = hex_to_rgb(candidate)
2545
+ dist = color_distance(base_rgb, candidate_rgb)
2546
+
2547
+ # 거리(차이) 임계값 100 (0~441 범위) — 필요시 조절 가능
2548
+ if dist > 100
2549
+ stroke_color = candidate
2550
+ break
2551
+ end
2552
+ end
2553
+ stroke_color ||= '#000000' # 만약 충분히 다른 색 없으면 검정색 기본값
2554
+
2555
+ img = Magick::Image.read('./image/memory.png').first
2556
+ draw = Magick::Draw.new
2557
+
2558
+ raw_message = "#{text1}\n#{text2}".strip
2559
+ max_width = img.columns * 0.85
2560
+ max_height = img.rows * 0.6
2561
+
2453
2562
  begin
2454
- color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
2455
- font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
2456
- font2 = './fonts/' + font_files.sample
2457
- color2 = color.sample
2458
-
2459
- img = Magick::Image.read('./image/memory.png').first
2460
- draw = Magick::Draw.new
2461
-
2462
- raw_message = "#{text1}\n#{text2}".strip
2463
- max_width = img.columns * 0.85
2464
- max_height = img.rows * 0.6
2465
-
2466
- begin
2467
- size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
2468
- rescue
2469
- size = 30
2470
- end
2471
-
2472
- wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
2473
-
2474
- if @data['이미지설정']['글자그림자'].checked?
2475
- img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
2476
- draw.gravity = Magick::CenterGravity
2477
- draw.pointsize = adjusted_size
2478
- draw.fill = '#000000'
2479
- draw.font = font2
2480
- end
2481
- end
2482
-
2483
- draw2 = Magick::Draw.new
2484
- img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
2485
- draw2.gravity = Magick::CenterGravity
2486
- draw2.pointsize = adjusted_size
2487
- draw2.fill = color2
2488
- draw2.font = font2
2489
- if @data['이미지설정']['글자테두리'].checked?
2490
- draw2.stroke_width = 2
2491
- draw2.stroke = '#000000'
2492
- end
2493
- end
2494
-
2495
- img.write('./image/memory.png')
2563
+ size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
2496
2564
  rescue
2497
- puts '이미지 폰트 불러오기 오류 재시도...'
2498
- sleep(3)
2499
- retry
2565
+ size = 30
2566
+ end
2567
+
2568
+ wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
2569
+
2570
+ if @data['이미지설정']['글자그림자'].checked?
2571
+ img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
2572
+ draw.gravity = Magick::CenterGravity
2573
+ draw.pointsize = adjusted_size
2574
+ draw.fill = '#000000'
2575
+ draw.font = font2
2576
+ end
2577
+ end
2578
+
2579
+ if @data['이미지설정']['글자테두리'].checked?
2580
+ draw_stroke = Magick::Draw.new
2581
+ img.annotate(draw_stroke, 0, 0, 0, 0, wrapped_message) do
2582
+ draw_stroke.gravity = Magick::CenterGravity
2583
+ draw_stroke.pointsize = adjusted_size
2584
+ draw_stroke.fill = 'none'
2585
+ draw_stroke.stroke = stroke_color
2586
+ draw_stroke.stroke_width = rand(5..10)
2587
+ draw_stroke.font = font2
2588
+ end
2589
+ end
2590
+
2591
+ draw2 = Magick::Draw.new
2592
+ img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
2593
+ draw2.gravity = Magick::CenterGravity
2594
+ draw2.pointsize = adjusted_size
2595
+ draw2.fill = color2
2596
+ draw2.stroke = 'none'
2597
+ draw2.font = font2
2500
2598
  end
2599
+
2600
+ img.write('./image/memory.png')
2601
+
2602
+ rescue => e
2603
+ puts "이미지 폰트 불러오기 오류 재시도... (#{e.message})"
2604
+ sleep(3)
2605
+ retry
2501
2606
  end
2607
+ end
2608
+
2609
+
2502
2610
 
2503
2611
  def border()
2504
2612
  color = File.open('./color.ini', 'r',:encoding => 'utf-8').read().split("\n")
@@ -2556,33 +2664,33 @@ class Wordpress
2556
2664
 
2557
2665
  if @data['이미지설정']['글자삽입1'].checked?
2558
2666
  if @data['이미지설정']['이미지글자1'].length == 0
2559
- image_text_path1 = ''
2667
+ image_text_path1 = ''
2560
2668
  else
2561
- if @data['이미지설정']['글자랜덤'].checked?
2562
- image_text_path1 = @data['이미지설정']['이미지글자1'].sample
2563
- else
2564
- image_text_path1 = @data['이미지설정']['이미지글자1'][@image_text_soon1]
2565
- @image_text_soon1 += 1
2566
- if @image_text_soon1 > @data['이미지설정']['이미지글자1'].length - 1
2567
- @image_text_soon1 = 0
2568
- end
2569
- end
2669
+ if @data['이미지설정']['글자랜덤'].checked?
2670
+ image_text_path1 = @data['이미지설정']['이미지글자1'].sample
2671
+ else
2672
+ image_text_path1 = @data['이미지설정']['이미지글자1'][@image_text_soon1]
2673
+ @image_text_soon1 += 1
2674
+ if @image_text_soon1 > @data['이미지설정']['이미지글자1'].length - 1
2675
+ @image_text_soon1 = 0
2676
+ end
2677
+ end
2570
2678
  end
2571
2679
  end
2572
2680
 
2573
2681
  if @data['이미지설정']['글자삽입2'].checked?
2574
2682
  if @data['이미지설정']['이미지글자2'].length == 0
2575
- image_text_path2 = ''
2576
- else
2577
- if @data['이미지설정']['글자랜덤'].checked?
2578
- image_text_path2 = @data['이미지설정']['이미지글자2'].sample
2683
+ image_text_path2 = ''
2579
2684
  else
2580
- image_text_path2 = @data['이미지설정']['이미지글자2'][@image_text_soon2]
2581
- @image_text_soon2 += 1
2582
- if @image_text_soon2 > @data['이미지설정']['이미지글자2'].length - 1
2583
- @image_text_soon2 = 0
2584
- end
2585
- end
2685
+ if @data['이미지설정']['글자랜덤'].checked?
2686
+ image_text_path2 = @data['이미지설정']['이미지글자2'].sample
2687
+ else
2688
+ image_text_path2 = @data['이미지설정']['이미지글자2'][@image_text_soon2]
2689
+ @image_text_soon2 += 1
2690
+ if @image_text_soon2 > @data['이미지설정']['이미지글자2'].length - 1
2691
+ @image_text_soon2 = 0
2692
+ end
2693
+ end
2586
2694
  end
2587
2695
  end
2588
2696
 
@@ -2796,6 +2904,19 @@ class Wordpress
2796
2904
  end
2797
2905
  end
2798
2906
 
2907
+ if @data['포스트설정']['gpt35'].checked? || @data['포스트설정']['gpt4turbo'].checked? || @data['포스트설정']['gpt4'].checked?
2908
+ gpt_model = if @data['포스트설정']['gpt35'].checked?
2909
+ 'gpt-3.5-turbo'
2910
+ elsif @data['포스트설정']['gpt4turbo'].checked?
2911
+ 'gpt-4-turbo'
2912
+ elsif @data['포스트설정']['gpt4'].checked?
2913
+ 'gpt-4'
2914
+ end
2915
+ puts "선택 된 GPT model: #{gpt_model}".green
2916
+ else
2917
+
2918
+ end
2919
+
2799
2920
  if @data['포스트설정']['gpt제목'].checked?
2800
2921
  gpt_title_prompt = @data['포스트설정']['gpt제목_프롬프트'].text.to_s.force_encoding('utf-8')
2801
2922
 
@@ -2803,7 +2924,7 @@ class Wordpress
2803
2924
  gpt_title_prompt_sample = gpt_title_prompt.strip.empty? ? "프롬프트: 문장을 비슷한 길이로 ChatGPT의 멘트는 빼고 표현을 더 추가해서 하나만 만들어줘." : gpt_title_prompt
2804
2925
 
2805
2926
  # gpt_title_prompt_sample을 Chat_title 객체에 전달
2806
- chat = Chat_title.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_title_prompt_sample)
2927
+ chat = Chat_title.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_title_prompt_sample, gpt_model)
2807
2928
 
2808
2929
  # 메시지 요청 후 title에 저장
2809
2930
  gpt_text1 = chat.message(title)
@@ -2859,7 +2980,7 @@ class Wordpress
2859
2980
  gpt_content_prompt_sample = gpt_content_prompt.strip.empty? ? "프롬프트:ChatGPT의 멘트는 빼고 위 전체적인 내용의 형식을 똑같이 표현을 더 추가하고 유사어로 변경하여 하나 만들어줘! 전화번호,연락처,가격,홈페이지안내 ,상담안내 관련 문구는 유지해야해" : gpt_content_prompt
2860
2981
 
2861
2982
  # Chat_content 객체 생성 시 api_key와 gpt_content_prompt_sample을 두 개의 인자로 전달
2862
- chat = Chat_content.new(api_key, gpt_content_prompt_sample)
2983
+ chat = Chat_content.new(api_key, gpt_content_prompt_sample, gpt_model)
2863
2984
 
2864
2985
  # 메시지 요청 후 content에 저장
2865
2986
  gpt_text3 = chat.message(content)
@@ -3007,7 +3128,7 @@ class Wordpress
3007
3128
  if @data['포스트설정']['gpt키워드'].checked?
3008
3129
  gpt_keyword_prompt = @data['포스트설정']['gpt키워드_프롬프트'].text.to_s.force_encoding('utf-8')
3009
3130
  gpt_keyword_prompt_sample = gpt_keyword_prompt.strip.empty? ? "프롬프트: 관련된 글을 1500자에서 2500자 사이로 만들어줘" : gpt_keyword_prompt
3010
- chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_keyword_prompt)
3131
+ chat = Chat.new(@data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8'), gpt_keyword_prompt, gpt_model)
3011
3132
  gpt_text = chat.message(keyword)
3012
3133
  #content = content.to_s + "\n(자동생성글)\n" + gpt_text.to_s
3013
3134
  content = content.to_s + "(자동생성글)" + gpt_text.to_s
@@ -4969,7 +5090,11 @@ class Wordpress
4969
5090
  vertical_box{
4970
5091
  horizontal_box{
4971
5092
  stretchy false
4972
- @data['image_type'][0] = checkbox('저장 사진 사용'){
5093
+ grid{
5094
+ stretchy false
5095
+ @data['image_type'][0] = checkbox('저장 사진 사용    '){
5096
+ top 0
5097
+ left 0
4973
5098
  on_toggled{
4974
5099
  if @data['image_type'][0].checked?
4975
5100
  @data['image_type'][1].checked = false
@@ -4977,7 +5102,9 @@ class Wordpress
4977
5102
  end
4978
5103
  }
4979
5104
  }
4980
- @data['image_type'][1] = checkbox('색상 사진 사용'){
5105
+ @data['image_type'][1] = checkbox('색상 사진 사용    '){
5106
+ top 0
5107
+ left 1
4981
5108
  on_toggled{
4982
5109
  if @data['image_type'][1].checked?
4983
5110
  @data['image_type'][0].checked = false
@@ -4986,6 +5113,8 @@ class Wordpress
4986
5113
  }
4987
5114
  }
4988
5115
  @data['image_type'][2] = checkbox('자동 다운로드 사진 사용'){
5116
+ top 0
5117
+ left 2
4989
5118
  on_toggled{
4990
5119
  if @data['image_type'][2].checked?
4991
5120
  @data['image_type'][1].checked = false
@@ -4994,7 +5123,7 @@ class Wordpress
4994
5123
  }
4995
5124
  }
4996
5125
  }
4997
-
5126
+ }
4998
5127
  grid{
4999
5128
  stretchy false
5000
5129
  @data['이미지설정']['글자삽입1'] = checkbox('글자 삽입1'){
@@ -5072,8 +5201,12 @@ class Wordpress
5072
5201
  top 1
5073
5202
  left 6
5074
5203
  }
5075
- @data['이미지설정']['글자순서'] = checkbox('글자 리스트 순서대로 사용'){
5076
- top 2
5204
+ }
5205
+
5206
+ grid{
5207
+ stretchy false
5208
+ @data['이미지설정']['글자순서'] = checkbox('글자 리스트 순서 사용 '){
5209
+ top 1
5077
5210
  left 0
5078
5211
  on_toggled{
5079
5212
  if @data['이미지설정']['글자순서'].checked?
@@ -5082,8 +5215,8 @@ class Wordpress
5082
5215
  }
5083
5216
  }
5084
5217
 
5085
- @data['이미지설정']['글자랜덤'] = checkbox('글자 리스트 랜덤으로 사용'){
5086
- top 2
5218
+ @data['이미지설정']['글자랜덤'] = checkbox('글자 리스트 랜덤 사용'){
5219
+ top 1
5087
5220
  left 1
5088
5221
  on_toggled{
5089
5222
  if @data['이미지설정']['글자랜덤'].checked?
@@ -5091,32 +5224,38 @@ class Wordpress
5091
5224
  end
5092
5225
  }
5093
5226
  }
5227
+ }
5094
5228
 
5095
5229
 
5096
- @data['이미지설정']['필터사용'] = checkbox('필터사용(색상 사진 적용불가)'){
5097
- top 2
5098
- left 2
5230
+ grid{
5231
+ stretchy false
5232
+ @data['이미지설정']['필터사용'] = checkbox('사진 필터 사용 [흑백,흐림,가우시안,,,등 랜덤] (※색상 사진 사용시 적용 불가)'){
5233
+ top 0
5234
+ left 0
5099
5235
  }
5100
- @data['이미지설정']['테두리사용'] = checkbox('테두리 사용'){
5101
- top 3
5236
+ }
5237
+ grid{
5238
+ stretchy false
5239
+ @data['이미지설정']['테두리사용'] = checkbox('사진 테두리 적용하기 '){
5240
+ top 1
5102
5241
  left 0
5103
5242
  }
5104
5243
  @data['이미지설정']['테두리크기1'] = entry{
5105
- top 3
5244
+ top 1
5106
5245
  left 2
5107
5246
  text 'ex) 1'
5108
5247
  }
5109
- label('pt'){
5110
- top 3
5248
+ label('px'){
5249
+ top 1
5111
5250
  left 3
5112
5251
  }
5113
5252
  @data['이미지설정']['테두리크기2'] = entry{
5114
- top 3
5253
+ top 1
5115
5254
  left 4
5116
5255
  text 'ex) 33'
5117
5256
  }
5118
- label('pt'){
5119
- top 3
5257
+ label('px'){
5258
+ top 1
5120
5259
  left 5
5121
5260
  }
5122
5261
 
@@ -5275,7 +5414,7 @@ class Wordpress
5275
5414
  stretchy false
5276
5415
  grid{
5277
5416
  stretchy false
5278
- @data['포스트설정']['제목키워드변경'] = checkbox('제목에 특정 단어를 내용에 사용할 키워드로 변경'){
5417
+ @data['포스트설정']['제목키워드변경'] = checkbox('제목에 특정 단어를 키워드로 변경'){
5279
5418
  top 0
5280
5419
  left 0
5281
5420
 
@@ -5318,13 +5457,10 @@ class Wordpress
5318
5457
  left 3
5319
5458
  text '최대수량'
5320
5459
  }
5321
- label('ㄴ'){
5322
- top 3
5323
- left 2
5324
- }
5325
- @data['포스트설정']['제목앞'] = checkbox('제목에 키워드 삽입 제목 앞'){
5460
+
5461
+ @data['포스트설정']['제목앞'] = checkbox('제목에 키워드 삽입시 제목 앞에 붙이기'){
5326
5462
  top 3
5327
- left 3
5463
+ left 0
5328
5464
  enabled false # 기본적으로 비활성화
5329
5465
  on_toggled{
5330
5466
  if @data['포스트설정']['제목앞'].checked? == true
@@ -5334,13 +5470,10 @@ class Wordpress
5334
5470
  end
5335
5471
  }
5336
5472
  }
5337
- label('ㄴ'){
5338
- top 4
5339
- left 2
5340
- }
5341
- @data['포스트설정']['제목뒤'] = checkbox('제목에 키워드 삽입 제목 뒤'){
5342
- top 4
5343
- left 3
5473
+
5474
+ @data['포스트설정']['제목뒤'] = checkbox('제목에 키워드시 삽입 제목 뒤에 붙이기'){
5475
+ top 3
5476
+ left 1
5344
5477
  enabled false # 기본적으로 비활성화
5345
5478
  on_toggled{
5346
5479
  if @data['포스트설정']['제목뒤'].checked? == true
@@ -5554,34 +5687,65 @@ class Wordpress
5554
5687
  text 'URL'
5555
5688
  }
5556
5689
 
5557
- @data['포스트설정']['ChatGPT사용'] = checkbox('Chat GPT 사용하기'){
5558
- top 15+ aa1
5559
- left 0
5560
- }
5561
-
5562
- @data['포스트설정']['api_key'] = entry(){
5563
- top 15+ aa1
5564
- left 1
5565
- text 'api key 입력 필수!!'
5566
- }
5567
-
5568
5690
  @data['포스트설정']['클립적용'] = checkbox('클립 내용에 넣기'){
5569
- top 16+ aa1
5691
+ top 15+ aa1
5570
5692
  left 0
5571
5693
  }
5572
5694
 
5573
5695
  @data['포스트설정']['클립단어'] = entry(){
5574
- top 16+ aa1
5696
+ top 15+ aa1
5575
5697
  left 1
5576
5698
  text '특정단어'
5577
5699
  }
5578
5700
  @data['포스트설정']['클립넘버'] = entry(){
5579
- top 16+ aa1
5701
+ top 15+ aa1
5580
5702
  left 3
5581
5703
  text '클립넘버 ex)1,2,3'
5582
5704
  }
5583
-
5584
5705
  }
5706
+ grid{
5707
+ stretchy false
5708
+ @data['포스트설정']['ChatGPT사용'] = checkbox('Chat GPT 사용하기             '){
5709
+ top 1
5710
+ left 0
5711
+ }
5712
+
5713
+ @data['포스트설정']['api_key'] = entry(){
5714
+ top 1
5715
+ left 1
5716
+ text 'api key 입력'
5717
+ }
5718
+ @data['포스트설정']['gpt35'] = checkbox('GPT 3.5-turbo'){
5719
+ top 1
5720
+ left 2
5721
+ on_toggled {
5722
+ if @data['포스트설정']['gpt35'].checked?
5723
+ @data['포스트설정']['gpt4'].checked = false
5724
+ @data['포스트설정']['gpt4turbo'].checked = false
5725
+ end
5726
+ }
5727
+ }
5728
+ @data['포스트설정']['gpt4'] = checkbox('GPT 4'){
5729
+ top 1
5730
+ left 3
5731
+ on_toggled {
5732
+ if @data['포스트설정']['gpt4'].checked?
5733
+ @data['포스트설정']['gpt35'].checked = false
5734
+ @data['포스트설정']['gpt4turbo'].checked = false
5735
+ end
5736
+ }
5737
+ }
5738
+ @data['포스트설정']['gpt4turbo'] = checkbox('GPT 4-turbo'){
5739
+ top 1
5740
+ left 4
5741
+ on_toggled {
5742
+ if @data['포스트설정']['gpt4turbo'].checked?
5743
+ @data['포스트설정']['gpt35'].checked = false
5744
+ @data['포스트설정']['gpt4'].checked = false
5745
+ end
5746
+ }
5747
+ }
5748
+ }
5585
5749
  }
5586
5750
 
5587
5751
  vertical_separator{
@@ -6121,6 +6285,7 @@ class Wordpress
6121
6285
  @data['포스트설정']['발행기능'].checked = true
6122
6286
  @data['포스트설정']['인용구랜덤'].checked = true
6123
6287
  @data['이미지설정']['글자순서'].checked = true
6288
+ @data['포스트설정']['gpt35'].checked = true
6124
6289
  }.show
6125
6290
  end
6126
6291
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nblog_duo
3
3
  version: !ruby/object:Gem::Version
4
- version: 111.119.999
4
+ version: 111.120.002
5
5
  platform: ruby
6
6
  authors:
7
7
  - zon
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-06-19 00:00:00.000000000 Z
10
+ date: 2025-06-26 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: File to Clipboard gem
13
13
  email: mymin26@naver.com