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.
- checksums.yaml +4 -4
- data/lib/nblog_duo.rb +207 -131
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92d60eb5158a9850b865e0f0610181c13e6a90968e27e8ab32667a3bcbcd51ae
|
4
|
+
data.tar.gz: 68ca780336905933aeb6584b78944eb437524209d48fa65508fe0e966f599981
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
2315
|
-
|
2316
|
-
|
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
|
-
|
2344
|
-
|
2345
|
-
|
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
|
-
|
2348
|
-
|
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
|
-
|
2352
|
-
|
2353
|
-
|
2354
|
-
|
2355
|
-
|
2330
|
+
|
2331
|
+
else
|
2332
|
+
|
2333
|
+
end
|
2334
|
+
end
|
2356
2335
|
|
2357
|
-
|
2358
|
-
|
2359
|
-
|
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
|
-
|
2362
|
-
|
2363
|
-
|
2366
|
+
json = JSON.parse(res.body)
|
2367
|
+
results = json['results']
|
2368
|
+
mm = []
|
2364
2369
|
|
2365
|
-
|
2366
|
-
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2373
|
-
|
2374
|
-
|
2375
|
-
|
2376
|
-
|
2377
|
-
|
2378
|
-
|
2379
|
-
|
2380
|
-
|
2381
|
-
|
2382
|
-
|
2383
|
-
|
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
|
-
|
2386
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
2530
|
-
|
2531
|
-
|
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
|
-
|
2592
|
-
else
|
2593
|
-
if @data['이미지설정']['글자랜덤'].checked?
|
2594
|
-
image_text_path1 = @data['이미지설정']['이미지글자1'].sample
|
2667
|
+
image_text_path1 = ''
|
2595
2668
|
else
|
2596
|
-
|
2597
|
-
|
2598
|
-
|
2599
|
-
|
2600
|
-
|
2601
|
-
|
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
|
-
|
2608
|
-
else
|
2609
|
-
if @data['이미지설정']['글자랜덤'].checked?
|
2610
|
-
image_text_path2 = @data['이미지설정']['이미지글자2'].sample
|
2683
|
+
image_text_path2 = ''
|
2611
2684
|
else
|
2612
|
-
|
2613
|
-
|
2614
|
-
|
2615
|
-
|
2616
|
-
|
2617
|
-
|
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
|
|