nblog_duo 111.120.001 → 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 +207 -131
  3. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: efa881c404a2b73abfcf72dec471351cad68e8b32d673f618b97e12a7b5576f8
4
- data.tar.gz: 25843ebb12c59f00fa36bba1e70bdbe670503e67b8a2d31334c8b68ec00c8b18
3
+ metadata.gz: 92d60eb5158a9850b865e0f0610181c13e6a90968e27e8ab32667a3bcbcd51ae
4
+ data.tar.gz: 68ca780336905933aeb6584b78944eb437524209d48fa65508fe0e966f599981
5
5
  SHA512:
6
- metadata.gz: 33818d85d4c36faf98aa79ca8a3d9182dc869e70305b02e95a608ff146a9e4a0c643c2bad6d599e939e5b3d2d2cfecf4408d345139af38f8714a550f9b42c44e
7
- data.tar.gz: 81e22e9e1a697c2420156095106263740b5f0ef8fae1e42255fa824791a396fb457d6c11e9c9c7ff036084337b5308f1583e0a78db4a6b37a33539255d9d9922
6
+ metadata.gz: 654a707ff0466ecdd152c4983dbcc8a31e2ad073fe1839b2a8d89574161b2189676f8908fda768bb667d87fe814734851ed03be1bfd0589d5abdba8eb72d738f
7
+ data.tar.gz: 9a539dfd8d82121f8eb79c313be8d1d5f54ffc86cc436fbcc26f420aaf955d532e555c095d8dcb55cd8dc68e721764b67da959ef4f67c459b0b9c9907e3cfd4a
data/lib/nblog_duo.rb CHANGED
@@ -22,6 +22,7 @@ require 'httpclient'
22
22
  include AutoClickMethods
23
23
  using Rainbow
24
24
  include Glimmer
25
+
25
26
  class Chat
26
27
  def initialize(api_key, gpt_keyword_prompt, model)
27
28
  @api_key = api_key
@@ -2311,84 +2312,112 @@ class Wordpress
2311
2312
  return @data2
2312
2313
  end
2313
2314
 
2314
- def auto_image(keyword = nil)
2315
- keyword ||= @keyword
2316
- puts "키워드: #{keyword}"
2317
-
2318
- client = HTTPClient.new
2319
- client.default_header = {
2320
- 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
2321
- '(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
2322
- 'Accept' => 'application/json, text/javascript, */*; q=0.01',
2323
- 'Accept-Language' => 'en-US,en;q=0.9',
2324
- 'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
2325
- 'X-Requested-With' => 'XMLHttpRequest'
2326
- }
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
2327
2319
 
2328
- retry_count = 0
2329
- max_retries = 10
2330
- results = []
2331
2320
 
2332
- begin
2333
- page = rand(1..15)
2334
- url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
2335
- puts "Request URL: #{url}"
2336
- res = client.get(url)
2337
-
2338
- unless res.status == 200
2339
- puts "HTTP Error: #{res.status}"
2340
- raise "HTTP Error"
2341
- end
2342
2321
 
2343
- json = JSON.parse(res.body)
2344
- results = json['results']
2345
- 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
2346
2326
 
2347
- results.each do |photo|
2348
- full_url = photo.dig('urls', 'full').to_s
2349
- regular_url = photo.dig('urls', 'regular').to_s
2327
+ cropped = img.crop(0, crop_top, width, new_height, true)
2328
+ cropped.write(path)
2350
2329
 
2351
- if full_url.start_with?("https://images.unsplash.com/photo-") &&
2352
- regular_url.include?("1080")
2353
- mm << full_url
2354
- end
2355
- end
2330
+
2331
+ else
2332
+
2333
+ end
2334
+ end
2356
2335
 
2357
- if mm.empty?
2358
- raise "No matching image"
2359
- 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
2360
2365
 
2361
- selected_url = mm.sample
2362
- Down.download(selected_url, destination: "./image/memory.png")
2363
- puts "이미지 다운로드 완료: #{selected_url}"
2366
+ json = JSON.parse(res.body)
2367
+ results = json['results']
2368
+ mm = []
2364
2369
 
2365
- rescue => e
2366
- retry_count += 1
2367
- puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
2368
- sleep(3)
2369
- if retry_count < max_retries
2370
- retry
2371
- else
2372
- puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
2373
-
2374
- if results && !results.empty?
2375
- random_photo = results.sample
2376
- fallback_url = random_photo.dig('urls', 'full')
2377
- if fallback_url
2378
- Down.download(fallback_url, destination: "./image/memory.png")
2379
- puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
2380
- else
2381
- puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
2382
- color_image
2383
- 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")
2384
2408
  else
2385
- puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
2386
- color_image
2387
- end
2409
+ puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
2410
+ color_image
2388
2411
  end
2412
+ else
2413
+ puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
2414
+ color_image
2389
2415
  end
2416
+ end
2417
+ end
2390
2418
  end
2391
2419
 
2420
+
2392
2421
  def color_image
2393
2422
  color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
2394
2423
  image = Magick::Image.new(740, 740) { |k| k.background_color = color.sample }
@@ -2481,57 +2510,104 @@ class Wordpress
2481
2510
  end
2482
2511
 
2483
2512
 
2484
- 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
+
2485
2562
  begin
2486
- color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
2487
- font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
2488
- font2 = './fonts/' + font_files.sample
2489
- color2 = color.sample
2490
-
2491
- img = Magick::Image.read('./image/memory.png').first
2492
- draw = Magick::Draw.new
2493
-
2494
- raw_message = "#{text1}\n#{text2}".strip
2495
- max_width = img.columns * 0.85
2496
- max_height = img.rows * 0.6
2497
-
2498
- begin
2499
- size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
2500
- rescue
2501
- size = 30
2502
- end
2503
-
2504
- wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
2505
-
2506
- if @data['이미지설정']['글자그림자'].checked?
2507
- img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
2508
- draw.gravity = Magick::CenterGravity
2509
- draw.pointsize = adjusted_size
2510
- draw.fill = '#000000'
2511
- draw.font = font2
2512
- end
2513
- end
2514
-
2515
- draw2 = Magick::Draw.new
2516
- img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
2517
- draw2.gravity = Magick::CenterGravity
2518
- draw2.pointsize = adjusted_size
2519
- draw2.fill = color2
2520
- draw2.font = font2
2521
- if @data['이미지설정']['글자테두리'].checked?
2522
- draw2.stroke_width = 2
2523
- draw2.stroke = '#000000'
2524
- end
2525
- end
2526
-
2527
- img.write('./image/memory.png')
2563
+ size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
2528
2564
  rescue
2529
- puts '이미지 폰트 불러오기 오류 재시도...'
2530
- sleep(3)
2531
- 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
2532
2598
  end
2599
+
2600
+ img.write('./image/memory.png')
2601
+
2602
+ rescue => e
2603
+ puts "이미지 폰트 불러오기 오류 재시도... (#{e.message})"
2604
+ sleep(3)
2605
+ retry
2606
+ end
2533
2607
  end
2534
2608
 
2609
+
2610
+
2535
2611
  def border()
2536
2612
  color = File.open('./color.ini', 'r',:encoding => 'utf-8').read().split("\n")
2537
2613
  img = Magick::Image.read('./image/memory.png').first
@@ -2588,33 +2664,33 @@ class Wordpress
2588
2664
 
2589
2665
  if @data['이미지설정']['글자삽입1'].checked?
2590
2666
  if @data['이미지설정']['이미지글자1'].length == 0
2591
- image_text_path1 = ''
2592
- else
2593
- if @data['이미지설정']['글자랜덤'].checked?
2594
- image_text_path1 = @data['이미지설정']['이미지글자1'].sample
2667
+ image_text_path1 = ''
2595
2668
  else
2596
- image_text_path1 = @data['이미지설정']['이미지글자1'][@image_text_soon1]
2597
- @image_text_soon1 += 1
2598
- if @image_text_soon1 > @data['이미지설정']['이미지글자1'].length - 1
2599
- @image_text_soon1 = 0
2600
- end
2601
- 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
2602
2678
  end
2603
2679
  end
2604
2680
 
2605
2681
  if @data['이미지설정']['글자삽입2'].checked?
2606
2682
  if @data['이미지설정']['이미지글자2'].length == 0
2607
- image_text_path2 = ''
2608
- else
2609
- if @data['이미지설정']['글자랜덤'].checked?
2610
- image_text_path2 = @data['이미지설정']['이미지글자2'].sample
2683
+ image_text_path2 = ''
2611
2684
  else
2612
- image_text_path2 = @data['이미지설정']['이미지글자2'][@image_text_soon2]
2613
- @image_text_soon2 += 1
2614
- if @image_text_soon2 > @data['이미지설정']['이미지글자2'].length - 1
2615
- @image_text_soon2 = 0
2616
- end
2617
- 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
2618
2694
  end
2619
2695
  end
2620
2696
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nblog_duo
3
3
  version: !ruby/object:Gem::Version
4
- version: 111.120.001
4
+ version: 111.120.002
5
5
  platform: ruby
6
6
  authors:
7
7
  - zon