nblog_duo 111.120.001 → 111.120.003

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 +210 -130
  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: 86ab7a8651d203747ab15ea4cca81b769adfec5c0e7c0cc10636b14a8daea03a
4
+ data.tar.gz: 0df26f49762720cdc20d17b8d4943539db9aa51b31161c6fc0268bdee600f6d6
5
5
  SHA512:
6
- metadata.gz: 33818d85d4c36faf98aa79ca8a3d9182dc869e70305b02e95a608ff146a9e4a0c643c2bad6d599e939e5b3d2d2cfecf4408d345139af38f8714a550f9b42c44e
7
- data.tar.gz: 81e22e9e1a697c2420156095106263740b5f0ef8fae1e42255fa824791a396fb457d6c11e9c9c7ff036084337b5308f1583e0a78db4a6b37a33539255d9d9922
6
+ metadata.gz: 553ce970ce17140182002e176f8eaa14a2d9e426dc5fdd9bd003ae9f749088a08b318092fcf1b51c69e142d57491927f8213755819dee32970cf770b81c2284a
7
+ data.tar.gz: 65ad848b5e5e2a90cc97502afa5f5186463e9b6028c380e6191a3ccea8a44be9cd1ffd2bb9dc2c1e03ff3e70669a2f9eaaae033e8239902bed9e186759b6bd83
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,83 +2312,115 @@ 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 = []
2320
+ if height > width
2321
+ min_height = (width * min_crop_ratio).to_i
2322
+ new_height = rand(min_height..width)
2323
+ crop_top = ((height - new_height) / 2.0).round
2331
2324
 
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"
2325
+ cropped = img.crop(0, crop_top, width, new_height, true)
2326
+
2327
+ retries = 0
2328
+ begin
2329
+ cropped.write(path)
2330
+ rescue => e
2331
+ retries += 1
2332
+ puts "이미지 저장 오류 (#{e.message}), 재시도 #{retries}/5"
2333
+ sleep(1)
2334
+ retry if retries < 5
2335
+ raise "이미지 저장 실패: #{e.message}"
2341
2336
  end
2337
+ end
2338
+ end
2342
2339
 
2343
- json = JSON.parse(res.body)
2344
- results = json['results']
2345
- mm = []
2340
+ def auto_image(keyword = nil)
2341
+ # auto_image 내부에서만 crop 호출
2342
+ keyword ||= @keyword
2343
+ puts "키워드: #{keyword}"
2344
+
2345
+ client = HTTPClient.new
2346
+ client.default_header = {
2347
+ 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
2348
+ '(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
2349
+ 'Accept' => 'application/json, text/javascript, */*; q=0.01',
2350
+ 'Accept-Language' => 'en-US,en;q=0.9',
2351
+ 'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
2352
+ 'X-Requested-With' => 'XMLHttpRequest'
2353
+ }
2354
+
2355
+ retry_count = 0
2356
+ max_retries = 10
2357
+ results = []
2358
+
2359
+ begin
2360
+ page = rand(1..15)
2361
+ url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
2362
+ puts "Request URL: #{url}"
2363
+ res = client.get(url)
2364
+
2365
+ unless res.status == 200
2366
+ puts "HTTP Error: #{res.status}"
2367
+ raise "HTTP Error"
2368
+ end
2346
2369
 
2347
- results.each do |photo|
2348
- full_url = photo.dig('urls', 'full').to_s
2349
- regular_url = photo.dig('urls', 'regular').to_s
2370
+ json = JSON.parse(res.body)
2371
+ results = json['results']
2372
+ mm = []
2350
2373
 
2351
- if full_url.start_with?("https://images.unsplash.com/photo-") &&
2352
- regular_url.include?("1080")
2353
- mm << full_url
2354
- end
2355
- end
2374
+ results.each do |photo|
2375
+ full_url = photo.dig('urls', 'full').to_s
2376
+ regular_url = photo.dig('urls', 'regular').to_s
2356
2377
 
2357
- if mm.empty?
2358
- raise "No matching image"
2359
- end
2378
+ if full_url.start_with?("https://images.unsplash.com/photo-") &&
2379
+ regular_url.include?("1080")
2380
+ mm << full_url
2381
+ end
2382
+ end
2360
2383
 
2361
- selected_url = mm.sample
2362
- Down.download(selected_url, destination: "./image/memory.png")
2363
- puts "이미지 다운로드 완료: #{selected_url}"
2384
+ if mm.empty?
2385
+ raise "No matching image"
2386
+ end
2364
2387
 
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
2388
+ selected_url = mm.sample
2389
+ destination_path = "./image/memory.png"
2390
+ Down.download(selected_url, destination: destination_path)
2391
+ puts "이미지 다운로드 완료: #{selected_url}"
2392
+
2393
+ # 오직 auto_image에서만 자르기 호출
2394
+ crop_image_height_under_width(destination_path)
2395
+
2396
+ rescue => e
2397
+ retry_count += 1
2398
+ puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
2399
+ sleep(3)
2400
+ if retry_count < max_retries
2401
+ retry
2402
+ else
2403
+ puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
2404
+
2405
+ if results && !results.empty?
2406
+ random_photo = results.sample
2407
+ fallback_url = random_photo.dig('urls', 'full')
2408
+ if fallback_url
2409
+ Down.download(fallback_url, destination: "./image/memory.png")
2410
+ puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
2411
+ crop_image_height_under_width("./image/memory.png")
2384
2412
  else
2385
- puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
2386
- color_image
2387
- end
2413
+ puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
2414
+ color_image
2388
2415
  end
2416
+ else
2417
+ puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
2418
+ color_image
2419
+ end
2389
2420
  end
2390
2421
  end
2422
+ end
2423
+
2391
2424
 
2392
2425
  def color_image
2393
2426
  color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
@@ -2481,57 +2514,104 @@ class Wordpress
2481
2514
  end
2482
2515
 
2483
2516
 
2484
- def image_text(text1, text2)
2517
+ def image_text(text1, text2)
2518
+ begin
2519
+ color = File.open('./color.ini', 'r', encoding: 'utf-8').read.split("\n").map(&:strip).reject(&:empty?)
2520
+ font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
2521
+ font2 = './fonts/' + font_files.sample
2522
+
2523
+ # 랜덤 글자색 선택
2524
+ color2 = color.sample
2525
+
2526
+ # 헬퍼 함수: 색상 문자열 '#RRGGBB' -> [R,G,B] 배열로 변환
2527
+ def hex_to_rgb(hex)
2528
+ hex = hex.delete('#')
2529
+ [hex[0..1], hex[2..3], hex[4..5]].map { |c| c.to_i(16) }
2530
+ end
2531
+
2532
+ # 헬퍼 함수: 두 RGB 색상의 차이 계산 (간단한 유클리드 거리)
2533
+ def color_distance(c1, c2)
2534
+ Math.sqrt(
2535
+ (c1[0] - c2[0])**2 +
2536
+ (c1[1] - c2[1])**2 +
2537
+ (c1[2] - c2[2])**2
2538
+ )
2539
+ end
2540
+
2541
+ # 대비가 충분히 되는 테두리 색상 선택
2542
+ max_attempts = 10
2543
+ stroke_color = nil
2544
+ base_rgb = hex_to_rgb(color2)
2545
+
2546
+ max_attempts.times do
2547
+ candidate = color.sample
2548
+ candidate_rgb = hex_to_rgb(candidate)
2549
+ dist = color_distance(base_rgb, candidate_rgb)
2550
+
2551
+ # 거리(차이) 임계값 100 (0~441 범위) — 필요시 조절 가능
2552
+ if dist > 100
2553
+ stroke_color = candidate
2554
+ break
2555
+ end
2556
+ end
2557
+ stroke_color ||= '#000000' # 만약 충분히 다른 색 없으면 검정색 기본값
2558
+
2559
+ img = Magick::Image.read('./image/memory.png').first
2560
+ draw = Magick::Draw.new
2561
+
2562
+ raw_message = "#{text1}\n#{text2}".strip
2563
+ max_width = img.columns * 0.85
2564
+ max_height = img.rows * 0.6
2565
+
2485
2566
  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')
2567
+ size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
2528
2568
  rescue
2529
- puts '이미지 폰트 불러오기 오류 재시도...'
2530
- sleep(3)
2531
- retry
2569
+ size = 30
2570
+ end
2571
+
2572
+ wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
2573
+
2574
+ if @data['이미지설정']['글자그림자'].checked?
2575
+ img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
2576
+ draw.gravity = Magick::CenterGravity
2577
+ draw.pointsize = adjusted_size
2578
+ draw.fill = '#000000'
2579
+ draw.font = font2
2580
+ end
2581
+ end
2582
+
2583
+ if @data['이미지설정']['글자테두리'].checked?
2584
+ draw_stroke = Magick::Draw.new
2585
+ img.annotate(draw_stroke, 0, 0, 0, 0, wrapped_message) do
2586
+ draw_stroke.gravity = Magick::CenterGravity
2587
+ draw_stroke.pointsize = adjusted_size
2588
+ draw_stroke.fill = 'none'
2589
+ draw_stroke.stroke = stroke_color
2590
+ draw_stroke.stroke_width = rand(5..10)
2591
+ draw_stroke.font = font2
2532
2592
  end
2593
+ end
2594
+
2595
+ draw2 = Magick::Draw.new
2596
+ img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
2597
+ draw2.gravity = Magick::CenterGravity
2598
+ draw2.pointsize = adjusted_size
2599
+ draw2.fill = color2
2600
+ draw2.stroke = 'none'
2601
+ draw2.font = font2
2602
+ end
2603
+
2604
+ img.write('./image/memory.png')
2605
+
2606
+ rescue => e
2607
+ puts "이미지 폰트 불러오기 오류 재시도... (#{e.message})"
2608
+ sleep(3)
2609
+ retry
2610
+ end
2533
2611
  end
2534
2612
 
2613
+
2614
+
2535
2615
  def border()
2536
2616
  color = File.open('./color.ini', 'r',:encoding => 'utf-8').read().split("\n")
2537
2617
  img = Magick::Image.read('./image/memory.png').first
@@ -2588,33 +2668,33 @@ class Wordpress
2588
2668
 
2589
2669
  if @data['이미지설정']['글자삽입1'].checked?
2590
2670
  if @data['이미지설정']['이미지글자1'].length == 0
2591
- image_text_path1 = ''
2592
- else
2593
- if @data['이미지설정']['글자랜덤'].checked?
2594
- image_text_path1 = @data['이미지설정']['이미지글자1'].sample
2671
+ image_text_path1 = ''
2595
2672
  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
2673
+ if @data['이미지설정']['글자랜덤'].checked?
2674
+ image_text_path1 = @data['이미지설정']['이미지글자1'].sample
2675
+ else
2676
+ image_text_path1 = @data['이미지설정']['이미지글자1'][@image_text_soon1]
2677
+ @image_text_soon1 += 1
2678
+ if @image_text_soon1 > @data['이미지설정']['이미지글자1'].length - 1
2679
+ @image_text_soon1 = 0
2680
+ end
2681
+ end
2602
2682
  end
2603
2683
  end
2604
2684
 
2605
2685
  if @data['이미지설정']['글자삽입2'].checked?
2606
2686
  if @data['이미지설정']['이미지글자2'].length == 0
2607
- image_text_path2 = ''
2608
- else
2609
- if @data['이미지설정']['글자랜덤'].checked?
2610
- image_text_path2 = @data['이미지설정']['이미지글자2'].sample
2687
+ image_text_path2 = ''
2611
2688
  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
2689
+ if @data['이미지설정']['글자랜덤'].checked?
2690
+ image_text_path2 = @data['이미지설정']['이미지글자2'].sample
2691
+ else
2692
+ image_text_path2 = @data['이미지설정']['이미지글자2'][@image_text_soon2]
2693
+ @image_text_soon2 += 1
2694
+ if @image_text_soon2 > @data['이미지설정']['이미지글자2'].length - 1
2695
+ @image_text_soon2 = 0
2696
+ end
2697
+ end
2618
2698
  end
2619
2699
  end
2620
2700
 
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.003
5
5
  platform: ruby
6
6
  authors:
7
7
  - zon