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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cafe_basics.rb +189 -110
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 664038efea4ab22edff62d90296fa46a585afdbcdcddf25c0f583d74d0949299
4
- data.tar.gz: 501f147f6085475e49942e6a1e489dfd9f13d5d203d23444567abb34cd1a6fa9
3
+ metadata.gz: 1d0451aa966f88b0f13e3da4eab576aa33f5963cb34e6a8bd4d4c415e4bc5104
4
+ data.tar.gz: 86ed985fe0ea99eaa3e09f4dc9993ac41f81808e840d0f8c9ece283826023bab
5
5
  SHA512:
6
- metadata.gz: 39cd755984562579ee0f6e9cc1c826a0409afca6fb7495e4a7e8567c145b7f9e5f64b2219723bb8c99682f8aaafd92b912bedd65b01cc712e99a2fb95e06a709
7
- data.tar.gz: 77a54824410ae82c383794eafa81002ed7aedb5d474b6df33eb05f25b138506938f6b7f4a03f475552502051ce38d8cc68d83d3841a6fe2e357f3217f15c3bdd
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 auto_image(keyword = nil)
2033
- keyword ||= @keyword
2034
- puts "키워드: #{keyword}"
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
- retry_count = 0
2047
- max_retries = 10
2048
- results = []
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
- begin
2051
- page = rand(1..15)
2052
- url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
2053
- puts "Request URL: #{url}"
2054
- res = client.get(url)
2055
-
2056
- unless res.status == 200
2057
- puts "HTTP Error: #{res.status}"
2058
- raise "HTTP Error"
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
- json = JSON.parse(res.body)
2062
- results = json['results']
2063
- mm = []
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
- results.each do |photo|
2066
- full_url = photo.dig('urls', 'full').to_s
2067
- regular_url = photo.dig('urls', 'regular').to_s
2087
+ json = JSON.parse(res.body)
2088
+ results = json['results']
2089
+ mm = []
2068
2090
 
2069
- if full_url.start_with?("https://images.unsplash.com/photo-") &&
2070
- regular_url.include?("1080")
2071
- mm << full_url
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
- if mm.empty?
2076
- raise "No matching image"
2077
- end
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
- selected_url = mm.sample
2080
- Down.download(selected_url, destination: "./image/memory.png")
2081
- puts "이미지 다운로드 완료: #{selected_url}"
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
- rescue => e
2084
- retry_count += 1
2085
- puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
2086
- sleep(3)
2087
- if retry_count < max_retries
2088
- retry
2089
- else
2090
- puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
2091
-
2092
- if results && !results.empty?
2093
- random_photo = results.sample
2094
- fallback_url = random_photo.dig('urls', 'full')
2095
- if fallback_url
2096
- Down.download(fallback_url, destination: "./image/memory.png")
2097
- puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
2098
- else
2099
- puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
2100
- color_image
2101
- end
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
- puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
2104
- color_image
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
- def image_text(text1, text2)
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
- color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
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
- puts '이미지 폰트 불러오기 오류 재시도...'
2248
- sleep(3)
2249
- retry
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.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