cafe_buy 0.1.51 → 0.1.52
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/cafe_buy.rb +185 -110
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f94b7d1bcfb6264a812baed1a521a2f8f4ddf2724b49520f03db280675989019
|
4
|
+
data.tar.gz: a85ba553efe2bdc42104ca639ecc5d67035b4e74a1a87db6873ba082d1d7c4a7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc56b9eff065ad14f45f3ad5711e8cf1a6a5b0c8305e587454c3ed0c4ac749e9cedb668329ff84c66596f49cffa1e50bce12d2b0af7889c939e1bc49f87c6b52
|
7
|
+
data.tar.gz: 61bccdfb975cd969708c6729066408476b70ccd79f7df844c87fbb32ac67374725e3aff811d8e7fbc8ef002f913de8184434df30b73f7d036502ae1901ddeb2e
|
data/lib/cafe_buy.rb
CHANGED
@@ -2366,84 +2366,112 @@ class Wordpress
|
|
2366
2366
|
|
2367
2367
|
|
2368
2368
|
|
2369
|
+
def crop_image_height_under_width(path, min_crop_ratio = 0.625)
|
2370
|
+
img = Magick::Image.read(path).first
|
2371
|
+
width = img.columns
|
2372
|
+
height = img.rows
|
2373
|
+
|
2374
|
+
|
2375
|
+
|
2376
|
+
if height > width
|
2377
|
+
min_height = (width * min_crop_ratio).to_i
|
2378
|
+
new_height = rand(min_height..width)
|
2379
|
+
crop_top = ((height - new_height) / 2.0).round
|
2380
|
+
|
2381
|
+
cropped = img.crop(0, crop_top, width, new_height, true)
|
2382
|
+
cropped.write(path)
|
2383
|
+
|
2384
|
+
|
2385
|
+
else
|
2386
|
+
|
2387
|
+
end
|
2388
|
+
end
|
2389
|
+
|
2369
2390
|
def auto_image(keyword = nil)
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2373
|
-
|
2374
|
-
|
2375
|
-
|
2376
|
-
|
2377
|
-
|
2378
|
-
|
2379
|
-
|
2380
|
-
|
2381
|
-
|
2391
|
+
# auto_image 내부에서만 crop 호출
|
2392
|
+
keyword ||= @keyword
|
2393
|
+
puts "키워드: #{keyword}"
|
2394
|
+
|
2395
|
+
client = HTTPClient.new
|
2396
|
+
client.default_header = {
|
2397
|
+
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
|
2398
|
+
'(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
|
2399
|
+
'Accept' => 'application/json, text/javascript, */*; q=0.01',
|
2400
|
+
'Accept-Language' => 'en-US,en;q=0.9',
|
2401
|
+
'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
|
2402
|
+
'X-Requested-With' => 'XMLHttpRequest'
|
2403
|
+
}
|
2404
|
+
|
2405
|
+
retry_count = 0
|
2406
|
+
max_retries = 10
|
2407
|
+
results = []
|
2382
2408
|
|
2383
|
-
|
2384
|
-
|
2385
|
-
|
2409
|
+
begin
|
2410
|
+
page = rand(1..15)
|
2411
|
+
url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
|
2412
|
+
puts "Request URL: #{url}"
|
2413
|
+
res = client.get(url)
|
2414
|
+
|
2415
|
+
unless res.status == 200
|
2416
|
+
puts "HTTP Error: #{res.status}"
|
2417
|
+
raise "HTTP Error"
|
2418
|
+
end
|
2386
2419
|
|
2387
|
-
|
2388
|
-
|
2389
|
-
|
2390
|
-
puts "Request URL: #{url}"
|
2391
|
-
res = client.get(url)
|
2392
|
-
|
2393
|
-
unless res.status == 200
|
2394
|
-
puts "HTTP Error: #{res.status}"
|
2395
|
-
raise "HTTP Error"
|
2396
|
-
end
|
2420
|
+
json = JSON.parse(res.body)
|
2421
|
+
results = json['results']
|
2422
|
+
mm = []
|
2397
2423
|
|
2398
|
-
|
2399
|
-
|
2400
|
-
|
2424
|
+
results.each do |photo|
|
2425
|
+
full_url = photo.dig('urls', 'full').to_s
|
2426
|
+
regular_url = photo.dig('urls', 'regular').to_s
|
2401
2427
|
|
2402
|
-
|
2403
|
-
|
2404
|
-
|
2428
|
+
if full_url.start_with?("https://images.unsplash.com/photo-") &&
|
2429
|
+
regular_url.include?("1080")
|
2430
|
+
mm << full_url
|
2431
|
+
end
|
2432
|
+
end
|
2405
2433
|
|
2406
|
-
|
2407
|
-
|
2408
|
-
|
2409
|
-
end
|
2410
|
-
end
|
2434
|
+
if mm.empty?
|
2435
|
+
raise "No matching image"
|
2436
|
+
end
|
2411
2437
|
|
2412
|
-
|
2413
|
-
|
2414
|
-
|
2438
|
+
selected_url = mm.sample
|
2439
|
+
destination_path = "./image/memory.png"
|
2440
|
+
Down.download(selected_url, destination: destination_path)
|
2441
|
+
puts "이미지 다운로드 완료: #{selected_url}"
|
2415
2442
|
|
2416
|
-
|
2417
|
-
|
2418
|
-
puts "이미지 다운로드 완료: #{selected_url}"
|
2443
|
+
# 오직 auto_image에서만 자르기 호출
|
2444
|
+
crop_image_height_under_width(destination_path)
|
2419
2445
|
|
2420
|
-
|
2421
|
-
|
2422
|
-
|
2423
|
-
|
2424
|
-
|
2425
|
-
|
2426
|
-
|
2427
|
-
|
2428
|
-
|
2429
|
-
|
2430
|
-
|
2431
|
-
|
2432
|
-
|
2433
|
-
|
2434
|
-
|
2435
|
-
|
2436
|
-
puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
|
2437
|
-
color_image
|
2438
|
-
end
|
2446
|
+
rescue => e
|
2447
|
+
retry_count += 1
|
2448
|
+
puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
|
2449
|
+
sleep(3)
|
2450
|
+
if retry_count < max_retries
|
2451
|
+
retry
|
2452
|
+
else
|
2453
|
+
puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
|
2454
|
+
|
2455
|
+
if results && !results.empty?
|
2456
|
+
random_photo = results.sample
|
2457
|
+
fallback_url = random_photo.dig('urls', 'full')
|
2458
|
+
if fallback_url
|
2459
|
+
Down.download(fallback_url, destination: "./image/memory.png")
|
2460
|
+
puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
|
2461
|
+
crop_image_height_under_width("./image/memory.png")
|
2439
2462
|
else
|
2440
|
-
|
2441
|
-
|
2442
|
-
end
|
2463
|
+
puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
|
2464
|
+
color_image
|
2443
2465
|
end
|
2466
|
+
else
|
2467
|
+
puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
|
2468
|
+
color_image
|
2444
2469
|
end
|
2470
|
+
end
|
2471
|
+
end
|
2445
2472
|
end
|
2446
2473
|
|
2474
|
+
|
2447
2475
|
def color_image
|
2448
2476
|
color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
|
2449
2477
|
image = Magick::Image.new(740, 740) { |k| k.background_color = color.sample }
|
@@ -2536,57 +2564,104 @@ class Wordpress
|
|
2536
2564
|
end
|
2537
2565
|
|
2538
2566
|
|
2539
|
-
|
2567
|
+
def image_text(text1, text2)
|
2568
|
+
begin
|
2569
|
+
color = File.open('./color.ini', 'r', encoding: 'utf-8').read.split("\n").map(&:strip).reject(&:empty?)
|
2570
|
+
font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
|
2571
|
+
font2 = './fonts/' + font_files.sample
|
2572
|
+
|
2573
|
+
# 랜덤 글자색 선택
|
2574
|
+
color2 = color.sample
|
2575
|
+
|
2576
|
+
# 헬퍼 함수: 색상 문자열 '#RRGGBB' -> [R,G,B] 배열로 변환
|
2577
|
+
def hex_to_rgb(hex)
|
2578
|
+
hex = hex.delete('#')
|
2579
|
+
[hex[0..1], hex[2..3], hex[4..5]].map { |c| c.to_i(16) }
|
2580
|
+
end
|
2581
|
+
|
2582
|
+
# 헬퍼 함수: 두 RGB 색상의 차이 계산 (간단한 유클리드 거리)
|
2583
|
+
def color_distance(c1, c2)
|
2584
|
+
Math.sqrt(
|
2585
|
+
(c1[0] - c2[0])**2 +
|
2586
|
+
(c1[1] - c2[1])**2 +
|
2587
|
+
(c1[2] - c2[2])**2
|
2588
|
+
)
|
2589
|
+
end
|
2590
|
+
|
2591
|
+
# 대비가 충분히 되는 테두리 색상 선택
|
2592
|
+
max_attempts = 10
|
2593
|
+
stroke_color = nil
|
2594
|
+
base_rgb = hex_to_rgb(color2)
|
2595
|
+
|
2596
|
+
max_attempts.times do
|
2597
|
+
candidate = color.sample
|
2598
|
+
candidate_rgb = hex_to_rgb(candidate)
|
2599
|
+
dist = color_distance(base_rgb, candidate_rgb)
|
2600
|
+
|
2601
|
+
# 거리(차이) 임계값 100 (0~441 범위) — 필요시 조절 가능
|
2602
|
+
if dist > 100
|
2603
|
+
stroke_color = candidate
|
2604
|
+
break
|
2605
|
+
end
|
2606
|
+
end
|
2607
|
+
stroke_color ||= '#000000' # 만약 충분히 다른 색 없으면 검정색 기본값
|
2608
|
+
|
2609
|
+
img = Magick::Image.read('./image/memory.png').first
|
2610
|
+
draw = Magick::Draw.new
|
2611
|
+
|
2612
|
+
raw_message = "#{text1}\n#{text2}".strip
|
2613
|
+
max_width = img.columns * 0.85
|
2614
|
+
max_height = img.rows * 0.6
|
2615
|
+
|
2540
2616
|
begin
|
2541
|
-
|
2542
|
-
font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
|
2543
|
-
font2 = './fonts/' + font_files.sample
|
2544
|
-
color2 = color.sample
|
2545
|
-
|
2546
|
-
img = Magick::Image.read('./image/memory.png').first
|
2547
|
-
draw = Magick::Draw.new
|
2548
|
-
|
2549
|
-
raw_message = "#{text1}\n#{text2}".strip
|
2550
|
-
max_width = img.columns * 0.85
|
2551
|
-
max_height = img.rows * 0.6
|
2552
|
-
|
2553
|
-
begin
|
2554
|
-
size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
|
2555
|
-
rescue
|
2556
|
-
size = 30
|
2557
|
-
end
|
2558
|
-
|
2559
|
-
wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
|
2560
|
-
|
2561
|
-
if @data['이미지설정']['글자그림자'].checked?
|
2562
|
-
img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
|
2563
|
-
draw.gravity = Magick::CenterGravity
|
2564
|
-
draw.pointsize = adjusted_size
|
2565
|
-
draw.fill = '#000000'
|
2566
|
-
draw.font = font2
|
2567
|
-
end
|
2568
|
-
end
|
2569
|
-
|
2570
|
-
draw2 = Magick::Draw.new
|
2571
|
-
img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
|
2572
|
-
draw2.gravity = Magick::CenterGravity
|
2573
|
-
draw2.pointsize = adjusted_size
|
2574
|
-
draw2.fill = color2
|
2575
|
-
draw2.font = font2
|
2576
|
-
if @data['이미지설정']['글자테두리'].checked?
|
2577
|
-
draw2.stroke_width = 2
|
2578
|
-
draw2.stroke = '#000000'
|
2579
|
-
end
|
2580
|
-
end
|
2581
|
-
|
2582
|
-
img.write('./image/memory.png')
|
2617
|
+
size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
|
2583
2618
|
rescue
|
2584
|
-
|
2585
|
-
|
2586
|
-
|
2619
|
+
size = 30
|
2620
|
+
end
|
2621
|
+
|
2622
|
+
wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
|
2623
|
+
|
2624
|
+
if @data['이미지설정']['글자그림자'].checked?
|
2625
|
+
img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
|
2626
|
+
draw.gravity = Magick::CenterGravity
|
2627
|
+
draw.pointsize = adjusted_size
|
2628
|
+
draw.fill = '#000000'
|
2629
|
+
draw.font = font2
|
2630
|
+
end
|
2631
|
+
end
|
2632
|
+
|
2633
|
+
if @data['이미지설정']['글자테두리'].checked?
|
2634
|
+
draw_stroke = Magick::Draw.new
|
2635
|
+
img.annotate(draw_stroke, 0, 0, 0, 0, wrapped_message) do
|
2636
|
+
draw_stroke.gravity = Magick::CenterGravity
|
2637
|
+
draw_stroke.pointsize = adjusted_size
|
2638
|
+
draw_stroke.fill = 'none'
|
2639
|
+
draw_stroke.stroke = stroke_color
|
2640
|
+
draw_stroke.stroke_width = rand(5..10)
|
2641
|
+
draw_stroke.font = font2
|
2587
2642
|
end
|
2643
|
+
end
|
2644
|
+
|
2645
|
+
draw2 = Magick::Draw.new
|
2646
|
+
img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
|
2647
|
+
draw2.gravity = Magick::CenterGravity
|
2648
|
+
draw2.pointsize = adjusted_size
|
2649
|
+
draw2.fill = color2
|
2650
|
+
draw2.stroke = 'none'
|
2651
|
+
draw2.font = font2
|
2652
|
+
end
|
2653
|
+
|
2654
|
+
img.write('./image/memory.png')
|
2655
|
+
|
2656
|
+
rescue => e
|
2657
|
+
puts "이미지 폰트 불러오기 오류 재시도... (#{e.message})"
|
2658
|
+
sleep(3)
|
2659
|
+
retry
|
2660
|
+
end
|
2588
2661
|
end
|
2589
2662
|
|
2663
|
+
|
2664
|
+
|
2590
2665
|
def border()
|
2591
2666
|
color = File.open('./color.ini', 'r',:encoding => 'utf-8').read().split("\n")
|
2592
2667
|
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
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.52
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- zon
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-06-
|
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
|