cafe_buy_duo 0.1.51 → 0.1.53

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/cafe_buy_duo.rb +189 -110
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ab9b13b2f6755f84dfcad6193902351caa52ba3cfbed979a8e717920ca328e4
4
- data.tar.gz: b43408a87613df0002c399f652e355e904732d129a92abd7ee2173db383c4f84
3
+ metadata.gz: 385bc3207c8c11406b1a4334217f61a88631a28085a923a52fa8b17adb665257
4
+ data.tar.gz: c582a195fb18bed9a08b9cb0c7e2c109292e6341bf209974d412965d6ae90b99
5
5
  SHA512:
6
- metadata.gz: d9dddfb0a0a315ff6b24eeaa9a4685d1817551f9eab78a356681784192888c492befc9c5f3cb1b8f78672a62607c06fc9c1a30ae1fac64ef2a819d372efa6b65
7
- data.tar.gz: 222c76cac0fc0d4a83256afe91d98651bf5dbd4aaa76b0b1b781f4e5ddfd1def96f4722d36042fc6dfa4d03d3d742a0597593c2128ab050869fffe6582bdbcee
6
+ metadata.gz: d9126d46589500b7ebf21dcb59117cde07a547ffdba727d7973588f762562807f5672c9ef0c3a1053dddbce1013f77bf2b6b93c000f57fd64db5148d9c77300b
7
+ data.tar.gz: 949882637008bafc25eaa2841c22bf95f8287b038e1b7244ac6ed74d646ec17c97069aa956ce568c3570474fd2c8fd00fa8f99d449e4bf1eef7316654ea86a93
data/lib/cafe_buy_duo.rb CHANGED
@@ -2434,83 +2434,115 @@ class Wordpress
2434
2434
 
2435
2435
 
2436
2436
 
2437
- def auto_image(keyword = nil)
2438
- keyword ||= @keyword
2439
- puts "키워드: #{keyword}"
2440
-
2441
- client = HTTPClient.new
2442
- client.default_header = {
2443
- 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
2444
- '(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
2445
- 'Accept' => 'application/json, text/javascript, */*; q=0.01',
2446
- 'Accept-Language' => 'en-US,en;q=0.9',
2447
- 'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
2448
- 'X-Requested-With' => 'XMLHttpRequest'
2449
- }
2437
+ def crop_image_height_under_width(path, min_crop_ratio = 0.625)
2438
+ img = Magick::Image.read(path).first
2439
+ width = img.columns
2440
+ height = img.rows
2450
2441
 
2451
- retry_count = 0
2452
- max_retries = 10
2453
- results = []
2442
+ if height > width
2443
+ min_height = (width * min_crop_ratio).to_i
2444
+ new_height = rand(min_height..width)
2445
+ crop_top = ((height - new_height) / 2.0).round
2454
2446
 
2455
- begin
2456
- page = rand(1..15)
2457
- url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
2458
- puts "Request URL: #{url}"
2459
- res = client.get(url)
2460
-
2461
- unless res.status == 200
2462
- puts "HTTP Error: #{res.status}"
2463
- raise "HTTP Error"
2447
+ cropped = img.crop(0, crop_top, width, new_height, true)
2448
+
2449
+ retries = 0
2450
+ begin
2451
+ cropped.write(path)
2452
+ rescue => e
2453
+ retries += 1
2454
+ puts "이미지 저장 오류 (#{e.message}), 재시도 #{retries}/5"
2455
+ sleep(1)
2456
+ retry if retries < 5
2457
+ raise "이미지 저장 실패: #{e.message}"
2464
2458
  end
2459
+ end
2460
+ end
2465
2461
 
2466
- json = JSON.parse(res.body)
2467
- results = json['results']
2468
- mm = []
2462
+ def auto_image(keyword = nil)
2463
+ # auto_image 내부에서만 crop 호출
2464
+ keyword ||= @keyword
2465
+ puts "키워드: #{keyword}"
2466
+
2467
+ client = HTTPClient.new
2468
+ client.default_header = {
2469
+ 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
2470
+ '(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
2471
+ 'Accept' => 'application/json, text/javascript, */*; q=0.01',
2472
+ 'Accept-Language' => 'en-US,en;q=0.9',
2473
+ 'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
2474
+ 'X-Requested-With' => 'XMLHttpRequest'
2475
+ }
2476
+
2477
+ retry_count = 0
2478
+ max_retries = 10
2479
+ results = []
2469
2480
 
2470
- results.each do |photo|
2471
- full_url = photo.dig('urls', 'full').to_s
2472
- regular_url = photo.dig('urls', 'regular').to_s
2481
+ begin
2482
+ page = rand(1..15)
2483
+ url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
2484
+ puts "Request URL: #{url}"
2485
+ res = client.get(url)
2486
+
2487
+ unless res.status == 200
2488
+ puts "HTTP Error: #{res.status}"
2489
+ raise "HTTP Error"
2490
+ end
2473
2491
 
2474
- if full_url.start_with?("https://images.unsplash.com/photo-") &&
2475
- regular_url.include?("1080")
2476
- mm << full_url
2477
- end
2478
- end
2492
+ json = JSON.parse(res.body)
2493
+ results = json['results']
2494
+ mm = []
2479
2495
 
2480
- if mm.empty?
2481
- raise "No matching image"
2482
- end
2496
+ results.each do |photo|
2497
+ full_url = photo.dig('urls', 'full').to_s
2498
+ regular_url = photo.dig('urls', 'regular').to_s
2483
2499
 
2484
- selected_url = mm.sample
2485
- Down.download(selected_url, destination: "./image/memory.png")
2486
- puts "이미지 다운로드 완료: #{selected_url}"
2500
+ if full_url.start_with?("https://images.unsplash.com/photo-") &&
2501
+ regular_url.include?("1080")
2502
+ mm << full_url
2503
+ end
2504
+ end
2487
2505
 
2488
- rescue => e
2489
- retry_count += 1
2490
- puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
2491
- sleep(3)
2492
- if retry_count < max_retries
2493
- retry
2494
- else
2495
- puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
2496
-
2497
- if results && !results.empty?
2498
- random_photo = results.sample
2499
- fallback_url = random_photo.dig('urls', 'full')
2500
- if fallback_url
2501
- Down.download(fallback_url, destination: "./image/memory.png")
2502
- puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
2503
- else
2504
- puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
2505
- color_image
2506
- end
2506
+ if mm.empty?
2507
+ raise "No matching image"
2508
+ end
2509
+
2510
+ selected_url = mm.sample
2511
+ destination_path = "./image/memory.png"
2512
+ Down.download(selected_url, destination: destination_path)
2513
+ puts "이미지 다운로드 완료: #{selected_url}"
2514
+
2515
+ # 오직 auto_image에서만 자르기 호출
2516
+ crop_image_height_under_width(destination_path)
2517
+
2518
+ rescue => e
2519
+ retry_count += 1
2520
+ puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
2521
+ sleep(3)
2522
+ if retry_count < max_retries
2523
+ retry
2524
+ else
2525
+ puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
2526
+
2527
+ if results && !results.empty?
2528
+ random_photo = results.sample
2529
+ fallback_url = random_photo.dig('urls', 'full')
2530
+ if fallback_url
2531
+ Down.download(fallback_url, destination: "./image/memory.png")
2532
+ puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
2533
+ crop_image_height_under_width("./image/memory.png")
2507
2534
  else
2508
- puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
2509
- color_image
2510
- end
2535
+ puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
2536
+ color_image
2511
2537
  end
2538
+ else
2539
+ puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
2540
+ color_image
2541
+ end
2512
2542
  end
2513
2543
  end
2544
+ end
2545
+
2514
2546
 
2515
2547
  def color_image
2516
2548
  color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
@@ -2604,57 +2636,104 @@ class Wordpress
2604
2636
  end
2605
2637
 
2606
2638
 
2607
- def image_text(text1, text2)
2639
+ def image_text(text1, text2)
2640
+ begin
2641
+ color = File.open('./color.ini', 'r', encoding: 'utf-8').read.split("\n").map(&:strip).reject(&:empty?)
2642
+ font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
2643
+ font2 = './fonts/' + font_files.sample
2644
+
2645
+ # 랜덤 글자색 선택
2646
+ color2 = color.sample
2647
+
2648
+ # 헬퍼 함수: 색상 문자열 '#RRGGBB' -> [R,G,B] 배열로 변환
2649
+ def hex_to_rgb(hex)
2650
+ hex = hex.delete('#')
2651
+ [hex[0..1], hex[2..3], hex[4..5]].map { |c| c.to_i(16) }
2652
+ end
2653
+
2654
+ # 헬퍼 함수: 두 RGB 색상의 차이 계산 (간단한 유클리드 거리)
2655
+ def color_distance(c1, c2)
2656
+ Math.sqrt(
2657
+ (c1[0] - c2[0])**2 +
2658
+ (c1[1] - c2[1])**2 +
2659
+ (c1[2] - c2[2])**2
2660
+ )
2661
+ end
2662
+
2663
+ # 대비가 충분히 되는 테두리 색상 선택
2664
+ max_attempts = 10
2665
+ stroke_color = nil
2666
+ base_rgb = hex_to_rgb(color2)
2667
+
2668
+ max_attempts.times do
2669
+ candidate = color.sample
2670
+ candidate_rgb = hex_to_rgb(candidate)
2671
+ dist = color_distance(base_rgb, candidate_rgb)
2672
+
2673
+ # 거리(차이) 임계값 100 (0~441 범위) — 필요시 조절 가능
2674
+ if dist > 100
2675
+ stroke_color = candidate
2676
+ break
2677
+ end
2678
+ end
2679
+ stroke_color ||= '#000000' # 만약 충분히 다른 색 없으면 검정색 기본값
2680
+
2681
+ img = Magick::Image.read('./image/memory.png').first
2682
+ draw = Magick::Draw.new
2683
+
2684
+ raw_message = "#{text1}\n#{text2}".strip
2685
+ max_width = img.columns * 0.85
2686
+ max_height = img.rows * 0.6
2687
+
2608
2688
  begin
2609
- color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
2610
- font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
2611
- font2 = './fonts/' + font_files.sample
2612
- color2 = color.sample
2613
-
2614
- img = Magick::Image.read('./image/memory.png').first
2615
- draw = Magick::Draw.new
2616
-
2617
- raw_message = "#{text1}\n#{text2}".strip
2618
- max_width = img.columns * 0.85
2619
- max_height = img.rows * 0.6
2620
-
2621
- begin
2622
- size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
2623
- rescue
2624
- size = 30
2625
- end
2626
-
2627
- wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
2628
-
2629
- if @data['이미지설정']['글자그림자'].checked?
2630
- img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
2631
- draw.gravity = Magick::CenterGravity
2632
- draw.pointsize = adjusted_size
2633
- draw.fill = '#000000'
2634
- draw.font = font2
2635
- end
2636
- end
2637
-
2638
- draw2 = Magick::Draw.new
2639
- img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
2640
- draw2.gravity = Magick::CenterGravity
2641
- draw2.pointsize = adjusted_size
2642
- draw2.fill = color2
2643
- draw2.font = font2
2644
- if @data['이미지설정']['글자테두리'].checked?
2645
- draw2.stroke_width = 2
2646
- draw2.stroke = '#000000'
2647
- end
2648
- end
2649
-
2650
- img.write('./image/memory.png')
2689
+ size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
2651
2690
  rescue
2652
- puts '이미지 폰트 불러오기 오류 재시도...'
2653
- sleep(3)
2654
- retry
2691
+ size = 30
2692
+ end
2693
+
2694
+ wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
2695
+
2696
+ if @data['이미지설정']['글자그림자'].checked?
2697
+ img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
2698
+ draw.gravity = Magick::CenterGravity
2699
+ draw.pointsize = adjusted_size
2700
+ draw.fill = '#000000'
2701
+ draw.font = font2
2702
+ end
2703
+ end
2704
+
2705
+ if @data['이미지설정']['글자테두리'].checked?
2706
+ draw_stroke = Magick::Draw.new
2707
+ img.annotate(draw_stroke, 0, 0, 0, 0, wrapped_message) do
2708
+ draw_stroke.gravity = Magick::CenterGravity
2709
+ draw_stroke.pointsize = adjusted_size
2710
+ draw_stroke.fill = 'none'
2711
+ draw_stroke.stroke = stroke_color
2712
+ draw_stroke.stroke_width = rand(5..10)
2713
+ draw_stroke.font = font2
2655
2714
  end
2715
+ end
2716
+
2717
+ draw2 = Magick::Draw.new
2718
+ img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
2719
+ draw2.gravity = Magick::CenterGravity
2720
+ draw2.pointsize = adjusted_size
2721
+ draw2.fill = color2
2722
+ draw2.stroke = 'none'
2723
+ draw2.font = font2
2724
+ end
2725
+
2726
+ img.write('./image/memory.png')
2727
+
2728
+ rescue => e
2729
+ puts "이미지 폰트 불러오기 오류 재시도... (#{e.message})"
2730
+ sleep(3)
2731
+ retry
2732
+ end
2656
2733
  end
2657
2734
 
2735
+
2736
+
2658
2737
  def border()
2659
2738
  color = File.open('./color.ini', 'r',:encoding => 'utf-8').read().split("\n")
2660
2739
  img = Magick::Image.read('./image/memory.png').first
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cafe_buy_duo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.51
4
+ version: 0.1.53
5
5
  platform: ruby
6
6
  authors:
7
7
  - zon
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-06-25 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