cafe_basics 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.
- checksums.yaml +4 -4
- data/lib/cafe_basics.rb +189 -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: 1d0451aa966f88b0f13e3da4eab576aa33f5963cb34e6a8bd4d4c415e4bc5104
|
4
|
+
data.tar.gz: 86ed985fe0ea99eaa3e09f4dc9993ac41f81808e840d0f8c9ece283826023bab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b08db72d293ebde33a55ac524785316cc62130f4c18b63f0c37ce8703ece4aeeb59094688b6812e46e0abb62877bc86f6d53fc6cf4cf0ea4fcb41d1b35bd6421
|
7
|
+
data.tar.gz: 2a1fd28e15ce350458c5ab6f7e9dcf688d5b9e4eb227b46b387f1d71d299b126643788a0ec7c0a39bdf46baecae4062548406ef30c0f538b84327c89d07559f9
|
data/lib/cafe_basics.rb
CHANGED
@@ -2029,83 +2029,115 @@ class Wordpress
|
|
2029
2029
|
|
2030
2030
|
|
2031
2031
|
|
2032
|
-
def
|
2033
|
-
|
2034
|
-
|
2035
|
-
|
2036
|
-
client = HTTPClient.new
|
2037
|
-
client.default_header = {
|
2038
|
-
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
|
2039
|
-
'(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
|
2040
|
-
'Accept' => 'application/json, text/javascript, */*; q=0.01',
|
2041
|
-
'Accept-Language' => 'en-US,en;q=0.9',
|
2042
|
-
'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
|
2043
|
-
'X-Requested-With' => 'XMLHttpRequest'
|
2044
|
-
}
|
2032
|
+
def crop_image_height_under_width(path, min_crop_ratio = 0.625)
|
2033
|
+
img = Magick::Image.read(path).first
|
2034
|
+
width = img.columns
|
2035
|
+
height = img.rows
|
2045
2036
|
|
2046
|
-
|
2047
|
-
|
2048
|
-
|
2037
|
+
if height > width
|
2038
|
+
min_height = (width * min_crop_ratio).to_i
|
2039
|
+
new_height = rand(min_height..width)
|
2040
|
+
crop_top = ((height - new_height) / 2.0).round
|
2049
2041
|
|
2050
|
-
|
2051
|
-
|
2052
|
-
|
2053
|
-
|
2054
|
-
|
2055
|
-
|
2056
|
-
|
2057
|
-
|
2058
|
-
|
2042
|
+
cropped = img.crop(0, crop_top, width, new_height, true)
|
2043
|
+
|
2044
|
+
retries = 0
|
2045
|
+
begin
|
2046
|
+
cropped.write(path)
|
2047
|
+
rescue => e
|
2048
|
+
retries += 1
|
2049
|
+
puts "이미지 저장 오류 (#{e.message}), 재시도 #{retries}/5"
|
2050
|
+
sleep(1)
|
2051
|
+
retry if retries < 5
|
2052
|
+
raise "이미지 저장 실패: #{e.message}"
|
2059
2053
|
end
|
2054
|
+
end
|
2055
|
+
end
|
2060
2056
|
|
2061
|
-
|
2062
|
-
|
2063
|
-
|
2057
|
+
def auto_image(keyword = nil)
|
2058
|
+
# auto_image 내부에서만 crop 호출
|
2059
|
+
keyword ||= @keyword
|
2060
|
+
puts "키워드: #{keyword}"
|
2061
|
+
|
2062
|
+
client = HTTPClient.new
|
2063
|
+
client.default_header = {
|
2064
|
+
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
|
2065
|
+
'(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
|
2066
|
+
'Accept' => 'application/json, text/javascript, */*; q=0.01',
|
2067
|
+
'Accept-Language' => 'en-US,en;q=0.9',
|
2068
|
+
'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
|
2069
|
+
'X-Requested-With' => 'XMLHttpRequest'
|
2070
|
+
}
|
2071
|
+
|
2072
|
+
retry_count = 0
|
2073
|
+
max_retries = 10
|
2074
|
+
results = []
|
2075
|
+
|
2076
|
+
begin
|
2077
|
+
page = rand(1..15)
|
2078
|
+
url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
|
2079
|
+
puts "Request URL: #{url}"
|
2080
|
+
res = client.get(url)
|
2081
|
+
|
2082
|
+
unless res.status == 200
|
2083
|
+
puts "HTTP Error: #{res.status}"
|
2084
|
+
raise "HTTP Error"
|
2085
|
+
end
|
2064
2086
|
|
2065
|
-
|
2066
|
-
|
2067
|
-
|
2087
|
+
json = JSON.parse(res.body)
|
2088
|
+
results = json['results']
|
2089
|
+
mm = []
|
2068
2090
|
|
2069
|
-
|
2070
|
-
|
2071
|
-
|
2072
|
-
end
|
2073
|
-
end
|
2091
|
+
results.each do |photo|
|
2092
|
+
full_url = photo.dig('urls', 'full').to_s
|
2093
|
+
regular_url = photo.dig('urls', 'regular').to_s
|
2074
2094
|
|
2075
|
-
|
2076
|
-
|
2077
|
-
|
2095
|
+
if full_url.start_with?("https://images.unsplash.com/photo-") &&
|
2096
|
+
regular_url.include?("1080")
|
2097
|
+
mm << full_url
|
2098
|
+
end
|
2099
|
+
end
|
2100
|
+
|
2101
|
+
if mm.empty?
|
2102
|
+
raise "No matching image"
|
2103
|
+
end
|
2078
2104
|
|
2079
|
-
|
2080
|
-
|
2081
|
-
|
2105
|
+
selected_url = mm.sample
|
2106
|
+
destination_path = "./image/memory.png"
|
2107
|
+
Down.download(selected_url, destination: destination_path)
|
2108
|
+
puts "이미지 다운로드 완료: #{selected_url}"
|
2082
2109
|
|
2083
|
-
|
2084
|
-
|
2085
|
-
|
2086
|
-
|
2087
|
-
|
2088
|
-
|
2089
|
-
|
2090
|
-
|
2091
|
-
|
2092
|
-
|
2093
|
-
|
2094
|
-
|
2095
|
-
|
2096
|
-
|
2097
|
-
|
2098
|
-
|
2099
|
-
|
2100
|
-
|
2101
|
-
|
2110
|
+
# 오직 auto_image에서만 자르기 호출
|
2111
|
+
crop_image_height_under_width(destination_path)
|
2112
|
+
|
2113
|
+
rescue => e
|
2114
|
+
retry_count += 1
|
2115
|
+
puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
|
2116
|
+
sleep(3)
|
2117
|
+
if retry_count < max_retries
|
2118
|
+
retry
|
2119
|
+
else
|
2120
|
+
puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
|
2121
|
+
|
2122
|
+
if results && !results.empty?
|
2123
|
+
random_photo = results.sample
|
2124
|
+
fallback_url = random_photo.dig('urls', 'full')
|
2125
|
+
if fallback_url
|
2126
|
+
Down.download(fallback_url, destination: "./image/memory.png")
|
2127
|
+
puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
|
2128
|
+
crop_image_height_under_width("./image/memory.png")
|
2102
2129
|
else
|
2103
|
-
|
2104
|
-
|
2105
|
-
end
|
2130
|
+
puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
|
2131
|
+
color_image
|
2106
2132
|
end
|
2133
|
+
else
|
2134
|
+
puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
|
2135
|
+
color_image
|
2136
|
+
end
|
2107
2137
|
end
|
2108
2138
|
end
|
2139
|
+
end
|
2140
|
+
|
2109
2141
|
|
2110
2142
|
def color_image
|
2111
2143
|
color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
|
@@ -2199,57 +2231,104 @@ class Wordpress
|
|
2199
2231
|
end
|
2200
2232
|
|
2201
2233
|
|
2202
|
-
|
2234
|
+
def image_text(text1, text2)
|
2235
|
+
begin
|
2236
|
+
color = File.open('./color.ini', 'r', encoding: 'utf-8').read.split("\n").map(&:strip).reject(&:empty?)
|
2237
|
+
font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
|
2238
|
+
font2 = './fonts/' + font_files.sample
|
2239
|
+
|
2240
|
+
# 랜덤 글자색 선택
|
2241
|
+
color2 = color.sample
|
2242
|
+
|
2243
|
+
# 헬퍼 함수: 색상 문자열 '#RRGGBB' -> [R,G,B] 배열로 변환
|
2244
|
+
def hex_to_rgb(hex)
|
2245
|
+
hex = hex.delete('#')
|
2246
|
+
[hex[0..1], hex[2..3], hex[4..5]].map { |c| c.to_i(16) }
|
2247
|
+
end
|
2248
|
+
|
2249
|
+
# 헬퍼 함수: 두 RGB 색상의 차이 계산 (간단한 유클리드 거리)
|
2250
|
+
def color_distance(c1, c2)
|
2251
|
+
Math.sqrt(
|
2252
|
+
(c1[0] - c2[0])**2 +
|
2253
|
+
(c1[1] - c2[1])**2 +
|
2254
|
+
(c1[2] - c2[2])**2
|
2255
|
+
)
|
2256
|
+
end
|
2257
|
+
|
2258
|
+
# 대비가 충분히 되는 테두리 색상 선택
|
2259
|
+
max_attempts = 10
|
2260
|
+
stroke_color = nil
|
2261
|
+
base_rgb = hex_to_rgb(color2)
|
2262
|
+
|
2263
|
+
max_attempts.times do
|
2264
|
+
candidate = color.sample
|
2265
|
+
candidate_rgb = hex_to_rgb(candidate)
|
2266
|
+
dist = color_distance(base_rgb, candidate_rgb)
|
2267
|
+
|
2268
|
+
# 거리(차이) 임계값 100 (0~441 범위) — 필요시 조절 가능
|
2269
|
+
if dist > 100
|
2270
|
+
stroke_color = candidate
|
2271
|
+
break
|
2272
|
+
end
|
2273
|
+
end
|
2274
|
+
stroke_color ||= '#000000' # 만약 충분히 다른 색 없으면 검정색 기본값
|
2275
|
+
|
2276
|
+
img = Magick::Image.read('./image/memory.png').first
|
2277
|
+
draw = Magick::Draw.new
|
2278
|
+
|
2279
|
+
raw_message = "#{text1}\n#{text2}".strip
|
2280
|
+
max_width = img.columns * 0.85
|
2281
|
+
max_height = img.rows * 0.6
|
2282
|
+
|
2203
2283
|
begin
|
2204
|
-
|
2205
|
-
font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
|
2206
|
-
font2 = './fonts/' + font_files.sample
|
2207
|
-
color2 = color.sample
|
2208
|
-
|
2209
|
-
img = Magick::Image.read('./image/memory.png').first
|
2210
|
-
draw = Magick::Draw.new
|
2211
|
-
|
2212
|
-
raw_message = "#{text1}\n#{text2}".strip
|
2213
|
-
max_width = img.columns * 0.85
|
2214
|
-
max_height = img.rows * 0.6
|
2215
|
-
|
2216
|
-
begin
|
2217
|
-
size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
|
2218
|
-
rescue
|
2219
|
-
size = 30
|
2220
|
-
end
|
2221
|
-
|
2222
|
-
wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
|
2223
|
-
|
2224
|
-
if @data['이미지설정']['글자그림자'].checked?
|
2225
|
-
img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
|
2226
|
-
draw.gravity = Magick::CenterGravity
|
2227
|
-
draw.pointsize = adjusted_size
|
2228
|
-
draw.fill = '#000000'
|
2229
|
-
draw.font = font2
|
2230
|
-
end
|
2231
|
-
end
|
2232
|
-
|
2233
|
-
draw2 = Magick::Draw.new
|
2234
|
-
img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
|
2235
|
-
draw2.gravity = Magick::CenterGravity
|
2236
|
-
draw2.pointsize = adjusted_size
|
2237
|
-
draw2.fill = color2
|
2238
|
-
draw2.font = font2
|
2239
|
-
if @data['이미지설정']['글자테두리'].checked?
|
2240
|
-
draw2.stroke_width = 2
|
2241
|
-
draw2.stroke = '#000000'
|
2242
|
-
end
|
2243
|
-
end
|
2244
|
-
|
2245
|
-
img.write('./image/memory.png')
|
2284
|
+
size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
|
2246
2285
|
rescue
|
2247
|
-
|
2248
|
-
|
2249
|
-
|
2286
|
+
size = 30
|
2287
|
+
end
|
2288
|
+
|
2289
|
+
wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
|
2290
|
+
|
2291
|
+
if @data['이미지설정']['글자그림자'].checked?
|
2292
|
+
img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
|
2293
|
+
draw.gravity = Magick::CenterGravity
|
2294
|
+
draw.pointsize = adjusted_size
|
2295
|
+
draw.fill = '#000000'
|
2296
|
+
draw.font = font2
|
2297
|
+
end
|
2298
|
+
end
|
2299
|
+
|
2300
|
+
if @data['이미지설정']['글자테두리'].checked?
|
2301
|
+
draw_stroke = Magick::Draw.new
|
2302
|
+
img.annotate(draw_stroke, 0, 0, 0, 0, wrapped_message) do
|
2303
|
+
draw_stroke.gravity = Magick::CenterGravity
|
2304
|
+
draw_stroke.pointsize = adjusted_size
|
2305
|
+
draw_stroke.fill = 'none'
|
2306
|
+
draw_stroke.stroke = stroke_color
|
2307
|
+
draw_stroke.stroke_width = rand(5..10)
|
2308
|
+
draw_stroke.font = font2
|
2309
|
+
end
|
2250
2310
|
end
|
2311
|
+
|
2312
|
+
draw2 = Magick::Draw.new
|
2313
|
+
img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
|
2314
|
+
draw2.gravity = Magick::CenterGravity
|
2315
|
+
draw2.pointsize = adjusted_size
|
2316
|
+
draw2.fill = color2
|
2317
|
+
draw2.stroke = 'none'
|
2318
|
+
draw2.font = font2
|
2319
|
+
end
|
2320
|
+
|
2321
|
+
img.write('./image/memory.png')
|
2322
|
+
|
2323
|
+
rescue => e
|
2324
|
+
puts "이미지 폰트 불러오기 오류 재시도... (#{e.message})"
|
2325
|
+
sleep(3)
|
2326
|
+
retry
|
2327
|
+
end
|
2251
2328
|
end
|
2252
2329
|
|
2330
|
+
|
2331
|
+
|
2253
2332
|
def border()
|
2254
2333
|
color = File.open('./color.ini', 'r',:encoding => 'utf-8').read().split("\n")
|
2255
2334
|
img = Magick::Image.read('./image/memory.png').first
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cafe_basics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
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-
|
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
|