posting_zon 3.111.003 → 3.111.005

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/posting_zon.rb +292 -128
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b292f1aa782c927e934070c47d89c90480fecae9b346c259c3cc7e4fb13b8296
4
- data.tar.gz: 2657a7e97dfa02ec0d7254ccde92df6cfc6d7856a8704fe3c1becd513c34db67
3
+ metadata.gz: 4cc0c303b04c477f8b1c6571e2c8d3c8c7d308b0ce981280e10cbcefb7cae0fb
4
+ data.tar.gz: 40f8a0b7550bceac056fcf9ed4ddc89dec4ce4cdffb072a718c737d5a5ef0407
5
5
  SHA512:
6
- metadata.gz: 1c24c787c5e22ce059c4b6212e6d2627f53cf117fbb28384503421f4c8c4fa8450ee169c290b666d44a315f504bfdd4eb8520c0c5bde26436c6b41b260367a7c
7
- data.tar.gz: 74a1b8b73e7f464b317690655fc5675f62eb153fbb662c1bd005ae1a2dd020dbb31720078cb7e385bf0544775cfd41b84f7a230e4752398cd56f4efa4a24d16d
6
+ metadata.gz: 971f7b80bcd49c588b1c40bacf0d1612f4ec6ce861bce0cc93ec75d9a539e71610da2ad58fa5013258db6f96598ed8f76ef5f2a0ee5af2361f866038279052cf
7
+ data.tar.gz: b693cc1459a8415fffed9f2397251627b188060a43dd9d9c68ff9f20f5262fa1dcc559a1687261f8d81bf61daf50479b90b001e3f3bdf68152ae65f607f07263
data/lib/posting_zon.rb CHANGED
@@ -12984,82 +12984,109 @@ class Wordpress
12984
12984
 
12985
12985
 
12986
12986
 
12987
+ def crop_image_height_under_width(path, min_crop_ratio = 0.625)
12988
+ img = Magick::Image.read(path).first
12989
+ width = img.columns
12990
+ height = img.rows
12991
+
12992
+
12993
+
12994
+ if height > width
12995
+ min_height = (width * min_crop_ratio).to_i
12996
+ new_height = rand(min_height..width)
12997
+ crop_top = ((height - new_height) / 2.0).round
12998
+
12999
+ cropped = img.crop(0, crop_top, width, new_height, true)
13000
+ cropped.write(path)
13001
+
13002
+
13003
+ else
13004
+
13005
+ end
13006
+ end
13007
+
12987
13008
  def auto_image(keyword = nil)
12988
- keyword ||= @keyword
12989
- puts "키워드: #{keyword}"
12990
-
12991
- client = HTTPClient.new
12992
- client.default_header = {
12993
- 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
12994
- '(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
12995
- 'Accept' => 'application/json, text/javascript, */*; q=0.01',
12996
- 'Accept-Language' => 'en-US,en;q=0.9',
12997
- 'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
12998
- 'X-Requested-With' => 'XMLHttpRequest'
12999
- }
13009
+ # auto_image 내부에서만 crop 호출
13010
+ keyword ||= @keyword
13011
+ puts "키워드: #{keyword}"
13012
+
13013
+ client = HTTPClient.new
13014
+ client.default_header = {
13015
+ 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
13016
+ '(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
13017
+ 'Accept' => 'application/json, text/javascript, */*; q=0.01',
13018
+ 'Accept-Language' => 'en-US,en;q=0.9',
13019
+ 'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
13020
+ 'X-Requested-With' => 'XMLHttpRequest'
13021
+ }
13000
13022
 
13001
- retry_count = 0
13002
- max_retries = 10
13003
- results = []
13023
+ retry_count = 0
13024
+ max_retries = 10
13025
+ results = []
13004
13026
 
13005
- begin
13006
- page = rand(1..15)
13007
- url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
13008
- puts "Request URL: #{url}"
13009
- res = client.get(url)
13010
-
13011
- unless res.status == 200
13012
- puts "HTTP Error: #{res.status}"
13013
- raise "HTTP Error"
13014
- end
13027
+ begin
13028
+ page = rand(1..15)
13029
+ url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
13030
+ puts "Request URL: #{url}"
13031
+ res = client.get(url)
13032
+
13033
+ unless res.status == 200
13034
+ puts "HTTP Error: #{res.status}"
13035
+ raise "HTTP Error"
13036
+ end
13015
13037
 
13016
- json = JSON.parse(res.body)
13017
- results = json['results']
13018
- mm = []
13038
+ json = JSON.parse(res.body)
13039
+ results = json['results']
13040
+ mm = []
13019
13041
 
13020
- results.each do |photo|
13021
- full_url = photo.dig('urls', 'full').to_s
13022
- regular_url = photo.dig('urls', 'regular').to_s
13042
+ results.each do |photo|
13043
+ full_url = photo.dig('urls', 'full').to_s
13044
+ regular_url = photo.dig('urls', 'regular').to_s
13023
13045
 
13024
- if full_url.start_with?("https://images.unsplash.com/photo-") &&
13025
- regular_url.include?("1080")
13026
- mm << full_url
13027
- end
13028
- end
13046
+ if full_url.start_with?("https://images.unsplash.com/photo-") &&
13047
+ regular_url.include?("1080")
13048
+ mm << full_url
13049
+ end
13050
+ end
13029
13051
 
13030
- if mm.empty?
13031
- raise "No matching image"
13032
- end
13052
+ if mm.empty?
13053
+ raise "No matching image"
13054
+ end
13033
13055
 
13034
- selected_url = mm.sample
13035
- Down.download(selected_url, destination: "./image/memory.png")
13036
- puts "이미지 다운로드 완료: #{selected_url}"
13056
+ selected_url = mm.sample
13057
+ destination_path = "./image/memory.png"
13058
+ Down.download(selected_url, destination: destination_path)
13059
+ puts "이미지 다운로드 완료: #{selected_url}"
13037
13060
 
13038
- rescue => e
13039
- retry_count += 1
13040
- puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
13041
- sleep(3)
13042
- if retry_count < max_retries
13043
- retry
13044
- else
13045
- puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
13046
-
13047
- if results && !results.empty?
13048
- random_photo = results.sample
13049
- fallback_url = random_photo.dig('urls', 'full')
13050
- if fallback_url
13051
- Down.download(fallback_url, destination: "./image/memory.png")
13052
- puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
13053
- else
13054
- puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
13055
- color_image
13056
- end
13061
+ # 오직 auto_image에서만 자르기 호출
13062
+ crop_image_height_under_width(destination_path)
13063
+
13064
+ rescue => e
13065
+ retry_count += 1
13066
+ puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
13067
+ sleep(3)
13068
+ if retry_count < max_retries
13069
+ retry
13070
+ else
13071
+ puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
13072
+
13073
+ if results && !results.empty?
13074
+ random_photo = results.sample
13075
+ fallback_url = random_photo.dig('urls', 'full')
13076
+ if fallback_url
13077
+ Down.download(fallback_url, destination: "./image/memory.png")
13078
+ puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
13079
+ crop_image_height_under_width("./image/memory.png")
13057
13080
  else
13058
- puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
13059
- color_image
13060
- end
13081
+ puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
13082
+ color_image
13061
13083
  end
13084
+ else
13085
+ puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
13086
+ color_image
13062
13087
  end
13088
+ end
13089
+ end
13063
13090
  end
13064
13091
 
13065
13092
 
@@ -13071,79 +13098,187 @@ class Wordpress
13071
13098
 
13072
13099
  def save_image
13073
13100
  if @data['이미지설정']['이미지'].length == 0
13074
-
13101
+ return
13102
+ end
13103
+
13104
+ if @data['이미지설정']['순서사용'].checked?
13105
+ image_path = @data['이미지설정']['이미지'][@image_counter][2]
13106
+ @image_counter += 1
13107
+ if @image_counter > @data['이미지설정']['이미지'].length - 1
13108
+ @image_counter = 0
13109
+ end
13075
13110
  else
13076
- if @data['이미지설정']['순서사용'].checked?
13077
- image_path = @data['이미지설정']['이미지'][@image_counter][2]
13078
- @image_counter += 1
13079
- if @image_counter > @data['이미지설정']['이미지'].length-1
13080
- @image_counter = 0
13081
- end
13082
- else
13083
- image_path = @data['이미지설정']['이미지'].sample[2]
13111
+ # 초기화가 안됐거나 다 썼으면 새롭게 섞는다
13112
+ @shuffled_images ||= []
13113
+ if @shuffled_images.empty?
13114
+ @shuffled_images = @data['이미지설정']['이미지'].shuffle
13084
13115
  end
13085
- img = Magick::Image.read(image_path).first
13086
- img.write('./image/memory.png')
13116
+
13117
+ image_path = @shuffled_images.shift[2]
13087
13118
  end
13119
+
13120
+ img = Magick::Image.read(image_path).first
13121
+ img.write('./image/memory.png')
13088
13122
  end
13089
13123
 
13090
13124
  def change_image_size(w)
13091
13125
  img = Magick::Image.read('./image/memory.png').first
13092
13126
  width = img.columns
13093
13127
  height = img.rows
13094
- begin
13095
- if @data['image_type'][0].checked? or @data['image_type'][2].checked?
13096
- img.resize!(w, w*(height.to_f/width.to_f))
13097
- else
13098
- img.resize!(w, w)
13128
+
13129
+ # '원본' 선택된 경우, 리사이징을 하지 않고 원본 이미지를 그대로 반환
13130
+ if w == 'original'
13131
+ return img # 원본 이미지 그대로 반환
13132
+ else
13133
+ begin
13134
+ if @data['image_type'][0].checked? or @data['image_type'][2].checked?
13135
+ # 비율을 맞추어 리사이징
13136
+ img.resize!(w, w * (height.to_f / width.to_f))
13137
+ else
13138
+ # 정사각형으로 리사이징
13139
+ img.resize!(w, w)
13140
+ end
13141
+ rescue
13142
+ img.resize!(w, w) # 예외 처리 시에도 리사이징
13099
13143
  end
13100
- rescue
13101
- img.resize!(w, w)
13102
13144
  end
13145
+
13146
+ # 리사이징된 이미지 저장
13103
13147
  img.write('./image/memory.png')
13104
13148
  end
13105
13149
 
13106
- def image_text(text1, text2)
13107
- begin
13108
- color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
13109
- font = Dir.entries('./fonts')
13110
- img = Magick::Image.read('./image/memory.png').first
13111
- text = Magick::Draw.new
13112
- color2 = color.sample
13113
- font2 = './fonts/'+font.sample
13114
- message = text1.to_s+"\n"+text2.to_s
13115
- begin
13116
- size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
13117
- rescue
13118
- size = 30
13119
- end
13120
- if @data['이미지설정']['글자그림자'].checked?
13121
- img.annotate(text, 0,0, +3,+3, message) do
13122
- text.gravity = Magick::CenterGravity
13123
- text.pointsize = size
13124
- text.fill = '#000000'
13125
- text.font = font2
13150
+ def wrap_text_to_fit(draw, text, max_width, max_height, font_path, initial_size)
13151
+ size = initial_size
13152
+ draw.font = font_path
13153
+
13154
+ loop do
13155
+ draw.pointsize = size
13156
+ words = text.chars # 글자 단위로 자름 (한국어 기준)
13157
+ lines = []
13158
+ line = ""
13159
+
13160
+ words.each do |char|
13161
+ test_line = line + char
13162
+ metrics = draw.get_type_metrics(test_line)
13163
+ if metrics.width > max_width
13164
+ lines << line
13165
+ line = char
13166
+ else
13167
+ line = test_line
13126
13168
  end
13127
13169
  end
13128
-
13129
- img.annotate(text, 0,0,0,0, message) do
13130
- text.gravity = Magick::CenterGravity
13131
- text.pointsize = size
13132
- if @data['이미지설정']['글자테두리'].checked?
13133
- text.stroke_width = 2
13134
- text.stroke = '#000000'
13135
- end
13136
- text.fill = color2
13137
- text.font = font2
13170
+ lines << line unless line.empty?
13171
+
13172
+ line_height = draw.get_type_metrics("가").height
13173
+ total_height = line_height * lines.size
13174
+
13175
+ # 세로 초과 안 하면 성공
13176
+ if total_height <= max_height || size <= 10
13177
+ return [lines.join("\n"), size]
13178
+ else
13179
+ size -= 2
13138
13180
  end
13181
+ end
13182
+ end
13183
+
13184
+
13185
+ def image_text(text1, text2)
13186
+ begin
13187
+ color = File.open('./color.ini', 'r', encoding: 'utf-8').read.split("\n").map(&:strip).reject(&:empty?)
13188
+ font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
13189
+ font2 = './fonts/' + font_files.sample
13139
13190
 
13140
- img.write('./image/memory.png')
13191
+ # 랜덤 글자색 선택
13192
+ color2 = color.sample
13193
+
13194
+ # 헬퍼 함수: 색상 문자열 '#RRGGBB' -> [R,G,B] 배열로 변환
13195
+ def hex_to_rgb(hex)
13196
+ hex = hex.delete('#')
13197
+ [hex[0..1], hex[2..3], hex[4..5]].map { |c| c.to_i(16) }
13198
+ end
13199
+
13200
+ # 헬퍼 함수: 두 RGB 색상의 차이 계산 (간단한 유클리드 거리)
13201
+ def color_distance(c1, c2)
13202
+ Math.sqrt(
13203
+ (c1[0] - c2[0])**2 +
13204
+ (c1[1] - c2[1])**2 +
13205
+ (c1[2] - c2[2])**2
13206
+ )
13207
+ end
13208
+
13209
+ # 대비가 충분히 되는 테두리 색상 선택
13210
+ max_attempts = 10
13211
+ stroke_color = nil
13212
+ base_rgb = hex_to_rgb(color2)
13213
+
13214
+ max_attempts.times do
13215
+ candidate = color.sample
13216
+ candidate_rgb = hex_to_rgb(candidate)
13217
+ dist = color_distance(base_rgb, candidate_rgb)
13218
+
13219
+ # 거리(차이) 임계값 100 (0~441 범위) — 필요시 조절 가능
13220
+ if dist > 100
13221
+ stroke_color = candidate
13222
+ break
13223
+ end
13224
+ end
13225
+ stroke_color ||= '#000000' # 만약 충분히 다른 색 없으면 검정색 기본값
13226
+
13227
+ img = Magick::Image.read('./image/memory.png').first
13228
+ draw = Magick::Draw.new
13229
+
13230
+ raw_message = "#{text1}\n#{text2}".strip
13231
+ max_width = img.columns * 0.85
13232
+ max_height = img.rows * 0.6
13233
+
13234
+ begin
13235
+ size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
13141
13236
  rescue
13142
- puts '이미지 폰트 불러오기 오류 재시도...'
13143
- sleep(3)
13144
- retry
13237
+ size = 30
13238
+ end
13239
+
13240
+ wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
13241
+
13242
+ if @data['이미지설정']['글자그림자'].checked?
13243
+ img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
13244
+ draw.gravity = Magick::CenterGravity
13245
+ draw.pointsize = adjusted_size
13246
+ draw.fill = '#000000'
13247
+ draw.font = font2
13248
+ end
13145
13249
  end
13250
+
13251
+ if @data['이미지설정']['글자테두리'].checked?
13252
+ draw_stroke = Magick::Draw.new
13253
+ img.annotate(draw_stroke, 0, 0, 0, 0, wrapped_message) do
13254
+ draw_stroke.gravity = Magick::CenterGravity
13255
+ draw_stroke.pointsize = adjusted_size
13256
+ draw_stroke.fill = 'none'
13257
+ draw_stroke.stroke = stroke_color
13258
+ draw_stroke.stroke_width = rand(5..10)
13259
+ draw_stroke.font = font2
13260
+ end
13261
+ end
13262
+
13263
+ draw2 = Magick::Draw.new
13264
+ img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
13265
+ draw2.gravity = Magick::CenterGravity
13266
+ draw2.pointsize = adjusted_size
13267
+ draw2.fill = color2
13268
+ draw2.stroke = 'none'
13269
+ draw2.font = font2
13270
+ end
13271
+
13272
+ img.write('./image/memory.png')
13273
+
13274
+ rescue => e
13275
+ puts "이미지 폰트 불러오기 오류 재시도... (#{e.message})"
13276
+ sleep(3)
13277
+ retry
13146
13278
  end
13279
+ end
13280
+
13281
+
13147
13282
 
13148
13283
  def border()
13149
13284
  color = File.open('./color.ini', 'r',:encoding => 'utf-8').read().split("\n")
@@ -13170,40 +13305,69 @@ class Wordpress
13170
13305
  else
13171
13306
  auto_image()
13172
13307
  end
13173
-
13174
- image_size = [480,740,650,550,480]
13308
+
13309
+ # '원본'을 포함한 이미지 크기 옵션 추가
13310
+ image_size = [480, 740, 650, 550, 480, 'original']
13175
13311
  size = 0
13176
- for n in 0..4
13312
+
13313
+ for n in 0..5 # 0부터 5까지 반복, '원본' 옵션까지 포함
13177
13314
  if @data['image_size'][n].checked?
13178
- if n == 0
13179
- size = image_size.sample
13315
+ if n == 5 # '원본'이 선택되었을 경우
13316
+ size = 'original'
13317
+ elsif n == 0
13318
+ size = image_size.sample # 랜덤 선택
13180
13319
  else
13181
13320
  size = image_size[n]
13182
13321
  end
13183
13322
  end
13184
13323
  end
13324
+
13325
+ # '원본'이 선택되지 않았다면 기본 값 설정
13185
13326
  if size == 0
13186
13327
  size = 480
13187
13328
  end
13329
+
13330
+ change_image_size(size) # 크기 변경 함수 호출
13188
13331
 
13189
- change_image_size(size)
13190
13332
 
13191
13333
  if @data['이미지설정']['필터사용'].checked?
13192
13334
  image_filter()
13193
13335
  end
13194
13336
 
13195
- insert_image_text1 = ''
13196
- insert_image_text2 = ''
13197
13337
  if @data['이미지설정']['글자삽입1'].checked?
13198
- insert_image_text1 = @data['이미지설정']['이미지글자1'].sample
13338
+ if @data['이미지설정']['이미지글자1'].length == 0
13339
+ image_text_path1 = ''
13340
+ else
13341
+ if @data['이미지설정']['글자랜덤'].checked?
13342
+ image_text_path1 = @data['이미지설정']['이미지글자1'].sample
13343
+ else
13344
+ image_text_path1 = @data['이미지설정']['이미지글자1'][@image_text_soon1]
13345
+ @image_text_soon1 += 1
13346
+ if @image_text_soon1 > @data['이미지설정']['이미지글자1'].length - 1
13347
+ @image_text_soon1 = 0
13348
+ end
13349
+ end
13350
+ end
13199
13351
  end
13200
13352
 
13201
13353
  if @data['이미지설정']['글자삽입2'].checked?
13202
- insert_image_text2 = @data['이미지설정']['이미지글자2'].sample
13354
+ if @data['이미지설정']['이미지글자2'].length == 0
13355
+ image_text_path2 = ''
13356
+ else
13357
+ if @data['이미지설정']['글자랜덤'].checked?
13358
+ image_text_path2 = @data['이미지설정']['이미지글자2'].sample
13359
+ else
13360
+ image_text_path2 = @data['이미지설정']['이미지글자2'][@image_text_soon2]
13361
+ @image_text_soon2 += 1
13362
+ if @image_text_soon2 > @data['이미지설정']['이미지글자2'].length - 1
13363
+ @image_text_soon2 = 0
13364
+ end
13365
+ end
13366
+ end
13203
13367
  end
13204
-
13368
+
13205
13369
  if @data['이미지설정']['글자삽입1'].checked? or @data['이미지설정']['글자삽입2'].checked?
13206
- image_text(insert_image_text1, insert_image_text2)
13370
+ image_text(image_text_path1, image_text_path2)
13207
13371
  end
13208
13372
 
13209
13373
  if @data['이미지설정']['테두리사용'].checked?
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: posting_zon
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.111.003
4
+ version: 3.111.005
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: posting app
13
13
  email: mymin26@naver.com