wp_posting_zon 0.0.7 → 0.0.9

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/wp_posting_zon.rb +303 -130
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6933d304ba0de74739de163a79202d5b0bc88532977b4127a6d13115e4bf1ea0
4
- data.tar.gz: 489e272f36bca3b99f9cc8eb5f4f054c45e57e67b5dfaa55a4bd8449a7f98f4f
3
+ metadata.gz: 5aeddc0ceb08cb7a26d1252f6b2e1c2b3cb3ee5c1404da3a2e97bf07c0ed0d0f
4
+ data.tar.gz: 3a33e130e13bc2ca04e57236c8620d03bfd29ed88b666882bb69e91746e1d056
5
5
  SHA512:
6
- metadata.gz: 38d59eff423b0bb6cef3795c84a17cbe2b81b5e2d5f39250fe60caf1a62e613c0a902f91c08a8678b7aaa398802e8a2afdc3cc2898e4a85d580e57d20695a7f5
7
- data.tar.gz: d25d6707b7761218972979e778f11d37bcc1113383c9915918c1e33d116674508e32ce670b1646121226dd2214a0fa0aa148f9dbb2f30067591480c00aeafeb3
6
+ metadata.gz: 959862a24098814c43dde5b88fe18ff2518c49d53c78e16c7f8d15ef8345d33fcada363599d7a06fd9e30d1ccf5fd4997f9be3f332677644dd3344e5958f17b4
7
+ data.tar.gz: 6ad3da66c7cc04822b594f32a64bb57051d05e7b61c7e9a5e7c3fe55712901c7142a5bf1f5245f1d2b78e8e77608f4ce3c36d23286202df4c83f461cc676e2b8
@@ -338,83 +338,110 @@ class Wordpress
338
338
  return @data2
339
339
  end
340
340
 
341
- def auto_image(keyword = nil)
342
- keyword ||= @keyword
343
- puts "키워드: #{keyword}"
344
-
345
- client = HTTPClient.new
346
- client.default_header = {
347
- 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
348
- '(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
349
- 'Accept' => 'application/json, text/javascript, */*; q=0.01',
350
- 'Accept-Language' => 'en-US,en;q=0.9',
351
- 'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
352
- 'X-Requested-With' => 'XMLHttpRequest'
353
- }
341
+ def crop_image_height_under_width(path, min_crop_ratio = 0.625)
342
+ img = Magick::Image.read(path).first
343
+ width = img.columns
344
+ height = img.rows
354
345
 
355
- retry_count = 0
356
- max_retries = 10
357
- results = []
358
346
 
359
- begin
360
- page = rand(1..15)
361
- url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
362
- puts "Request URL: #{url}"
363
- res = client.get(url)
364
-
365
- unless res.status == 200
366
- puts "HTTP Error: #{res.status}"
367
- raise "HTTP Error"
368
- end
369
347
 
370
- json = JSON.parse(res.body)
371
- results = json['results']
372
- mm = []
348
+ if height > width
349
+ min_height = (width * min_crop_ratio).to_i
350
+ new_height = rand(min_height..width)
351
+ crop_top = ((height - new_height) / 2.0).round
373
352
 
374
- results.each do |photo|
375
- full_url = photo.dig('urls', 'full').to_s
376
- regular_url = photo.dig('urls', 'regular').to_s
353
+ cropped = img.crop(0, crop_top, width, new_height, true)
354
+ cropped.write(path)
377
355
 
378
- if full_url.start_with?("https://images.unsplash.com/photo-") &&
379
- regular_url.include?("1080")
380
- mm << full_url
381
- end
382
- end
356
+
357
+ else
358
+
359
+ end
360
+ end
383
361
 
384
- if mm.empty?
385
- raise "No matching image"
386
- end
362
+ def auto_image(keyword = nil)
363
+ # auto_image 내부에서만 crop 호출
364
+ keyword ||= @keyword
365
+ puts "키워드: #{keyword}"
366
+
367
+ client = HTTPClient.new
368
+ client.default_header = {
369
+ 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
370
+ '(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
371
+ 'Accept' => 'application/json, text/javascript, */*; q=0.01',
372
+ 'Accept-Language' => 'en-US,en;q=0.9',
373
+ 'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
374
+ 'X-Requested-With' => 'XMLHttpRequest'
375
+ }
376
+
377
+ retry_count = 0
378
+ max_retries = 10
379
+ results = []
380
+
381
+ begin
382
+ page = rand(1..15)
383
+ url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
384
+ puts "Request URL: #{url}"
385
+ res = client.get(url)
386
+
387
+ unless res.status == 200
388
+ puts "HTTP Error: #{res.status}"
389
+ raise "HTTP Error"
390
+ end
387
391
 
388
- selected_url = mm.sample
389
- Down.download(selected_url, destination: "./image/memory.png")
390
- puts "이미지 다운로드 완료: #{selected_url}"
392
+ json = JSON.parse(res.body)
393
+ results = json['results']
394
+ mm = []
391
395
 
392
- rescue => e
393
- retry_count += 1
394
- puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
395
- sleep(3)
396
- if retry_count < max_retries
397
- retry
398
- else
399
- puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
400
-
401
- if results && !results.empty?
402
- random_photo = results.sample
403
- fallback_url = random_photo.dig('urls', 'full')
404
- if fallback_url
405
- Down.download(fallback_url, destination: "./image/memory.png")
406
- puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
407
- else
408
- puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
409
- color_image
410
- end
396
+ results.each do |photo|
397
+ full_url = photo.dig('urls', 'full').to_s
398
+ regular_url = photo.dig('urls', 'regular').to_s
399
+
400
+ if full_url.start_with?("https://images.unsplash.com/photo-") &&
401
+ regular_url.include?("1080")
402
+ mm << full_url
403
+ end
404
+ end
405
+
406
+ if mm.empty?
407
+ raise "No matching image"
408
+ end
409
+
410
+ selected_url = mm.sample
411
+ destination_path = "./image/memory.png"
412
+ Down.download(selected_url, destination: destination_path)
413
+ puts "이미지 다운로드 완료: #{selected_url}"
414
+
415
+ # 오직 auto_image에서만 자르기 호출
416
+ crop_image_height_under_width(destination_path)
417
+
418
+ rescue => e
419
+ retry_count += 1
420
+ puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
421
+ sleep(3)
422
+ if retry_count < max_retries
423
+ retry
424
+ else
425
+ puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
426
+
427
+ if results && !results.empty?
428
+ random_photo = results.sample
429
+ fallback_url = random_photo.dig('urls', 'full')
430
+ if fallback_url
431
+ Down.download(fallback_url, destination: "./image/memory.png")
432
+ puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
433
+ crop_image_height_under_width("./image/memory.png")
411
434
  else
412
- puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
413
- color_image
414
- end
435
+ puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
436
+ color_image
415
437
  end
438
+ else
439
+ puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
440
+ color_image
441
+ end
416
442
  end
417
443
  end
444
+ end
418
445
 
419
446
 
420
447
  def color_image
@@ -425,80 +452,188 @@ class Wordpress
425
452
 
426
453
  def save_image
427
454
  if @data['이미지설정']['이미지'].length == 0
428
-
455
+ return
456
+ end
457
+
458
+ if @data['이미지설정']['순서사용'].checked?
459
+ image_path = @data['이미지설정']['이미지'][@image_counter][2]
460
+ @image_counter += 1
461
+ if @image_counter > @data['이미지설정']['이미지'].length - 1
462
+ @image_counter = 0
463
+ end
429
464
  else
430
- if @data['이미지설정']['순서사용'].checked?
431
- image_path = @data['이미지설정']['이미지'][@image_counter][2]
432
- @image_counter += 1
433
- if @image_counter > @data['이미지설정']['이미지'].length-1
434
- @image_counter = 0
435
- end
436
- else
437
- image_path = @data['이미지설정']['이미지'].sample[2]
465
+ # 초기화가 안됐거나 다 썼으면 새롭게 섞는다
466
+ @shuffled_images ||= []
467
+ if @shuffled_images.empty?
468
+ @shuffled_images = @data['이미지설정']['이미지'].shuffle
438
469
  end
439
- img = Magick::Image.read(image_path).first
440
- img.write('./image/memory.png')
470
+
471
+ image_path = @shuffled_images.shift[2]
441
472
  end
473
+
474
+ img = Magick::Image.read(image_path).first
475
+ img.write('./image/memory.png')
442
476
  end
443
477
 
444
478
  def change_image_size(w)
445
479
  img = Magick::Image.read('./image/memory.png').first
446
480
  width = img.columns
447
481
  height = img.rows
448
- begin
449
- if @data['image_type'][0].checked? or @data['image_type'][2].checked?
450
- img.resize!(w, w*(height.to_f/width.to_f))
451
- else
452
- img.resize!(w, w)
482
+
483
+ # '원본' 선택된 경우, 리사이징을 하지 않고 원본 이미지를 그대로 반환
484
+ if w == 'original'
485
+ return img # 원본 이미지 그대로 반환
486
+ else
487
+ begin
488
+ if @data['image_type'][0].checked? or @data['image_type'][2].checked?
489
+ # 비율을 맞추어 리사이징
490
+ img.resize!(w, w * (height.to_f / width.to_f))
491
+ else
492
+ # 정사각형으로 리사이징
493
+ img.resize!(w, w)
494
+ end
495
+ rescue
496
+ img.resize!(w, w) # 예외 처리 시에도 리사이징
453
497
  end
454
- rescue
455
- img.resize!(w, w)
456
498
  end
499
+
500
+ # 리사이징된 이미지 저장
457
501
  img.write('./image/memory.png')
458
502
  end
459
503
 
460
- def image_text(text1, text2)
461
- begin
462
- color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
463
- font = Dir.entries('./fonts')
464
- img = Magick::Image.read('./image/memory.png').first
465
- text = Magick::Draw.new
466
- color2 = color.sample
467
- font2 = './fonts/'+font.sample
468
- message = text1.to_s+"\n"+text2.to_s
469
- begin
470
- size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
471
- rescue
472
- size = 30
473
- end
474
- if @data['이미지설정']['글자그림자'].checked?
475
- img.annotate(text, 0,0, +3,+3, message) do
476
- text.gravity = Magick::CenterGravity
477
- text.pointsize = size
478
- text.fill = '#000000'
479
- text.font = font2
504
+ def wrap_text_to_fit(draw, text, max_width, max_height, font_path, initial_size)
505
+ size = initial_size
506
+ draw.font = font_path
507
+
508
+ loop do
509
+ draw.pointsize = size
510
+ words = text.chars # 글자 단위로 자름 (한국어 기준)
511
+ lines = []
512
+ line = ""
513
+
514
+ words.each do |char|
515
+ test_line = line + char
516
+ metrics = draw.get_type_metrics(test_line)
517
+ if metrics.width > max_width
518
+ lines << line
519
+ line = char
520
+ else
521
+ line = test_line
480
522
  end
481
523
  end
482
-
483
- img.annotate(text, 0,0,0,0, message) do
484
- text.gravity = Magick::CenterGravity
485
- text.pointsize = size
486
- if @data['이미지설정']['글자테두리'].checked?
487
- text.stroke_width = 2
488
- text.stroke = '#000000'
489
- end
490
- text.fill = color2
491
- text.font = font2
524
+ lines << line unless line.empty?
525
+
526
+ line_height = draw.get_type_metrics("가").height
527
+ total_height = line_height * lines.size
528
+
529
+ # 세로 초과 안 하면 성공
530
+ if total_height <= max_height || size <= 10
531
+ return [lines.join("\n"), size]
532
+ else
533
+ size -= 2
492
534
  end
493
-
494
- img.write('./image/memory.png')
535
+ end
536
+ end
537
+
538
+
539
+ def image_text(text1, text2)
540
+ begin
541
+ color = File.open('./color.ini', 'r', encoding: 'utf-8').read.split("\n").map(&:strip).reject(&:empty?)
542
+ font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
543
+ font2 = './fonts/' + font_files.sample
544
+
545
+ # 랜덤 글자색 선택
546
+ color2 = color.sample
547
+
548
+ # 헬퍼 함수: 색상 문자열 '#RRGGBB' -> [R,G,B] 배열로 변환
549
+ def hex_to_rgb(hex)
550
+ hex = hex.delete('#')
551
+ [hex[0..1], hex[2..3], hex[4..5]].map { |c| c.to_i(16) }
552
+ end
553
+
554
+ # 헬퍼 함수: 두 RGB 색상의 차이 계산 (간단한 유클리드 거리)
555
+ def color_distance(c1, c2)
556
+ Math.sqrt(
557
+ (c1[0] - c2[0])**2 +
558
+ (c1[1] - c2[1])**2 +
559
+ (c1[2] - c2[2])**2
560
+ )
561
+ end
562
+
563
+ # 대비가 충분히 되는 테두리 색상 선택
564
+ max_attempts = 10
565
+ stroke_color = nil
566
+ base_rgb = hex_to_rgb(color2)
567
+
568
+ max_attempts.times do
569
+ candidate = color.sample
570
+ candidate_rgb = hex_to_rgb(candidate)
571
+ dist = color_distance(base_rgb, candidate_rgb)
572
+
573
+ # 거리(차이) 임계값 100 (0~441 범위) — 필요시 조절 가능
574
+ if dist > 100
575
+ stroke_color = candidate
576
+ break
577
+ end
578
+ end
579
+ stroke_color ||= '#000000' # 만약 충분히 다른 색 없으면 검정색 기본값
580
+
581
+ img = Magick::Image.read('./image/memory.png').first
582
+ draw = Magick::Draw.new
583
+
584
+ raw_message = "#{text1}\n#{text2}".strip
585
+ max_width = img.columns * 0.85
586
+ max_height = img.rows * 0.6
587
+
588
+ begin
589
+ size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
495
590
  rescue
496
- puts '이미지 폰트 불러오기 오류 재시도...'
497
- sleep(3)
498
- retry
591
+ size = 30
592
+ end
593
+
594
+ wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
595
+
596
+ if @data['이미지설정']['글자그림자'].checked?
597
+ img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
598
+ draw.gravity = Magick::CenterGravity
599
+ draw.pointsize = adjusted_size
600
+ draw.fill = '#000000'
601
+ draw.font = font2
602
+ end
603
+ end
604
+
605
+ if @data['이미지설정']['글자테두리'].checked?
606
+ draw_stroke = Magick::Draw.new
607
+ img.annotate(draw_stroke, 0, 0, 0, 0, wrapped_message) do
608
+ draw_stroke.gravity = Magick::CenterGravity
609
+ draw_stroke.pointsize = adjusted_size
610
+ draw_stroke.fill = 'none'
611
+ draw_stroke.stroke = stroke_color
612
+ draw_stroke.stroke_width = rand(5..10)
613
+ draw_stroke.font = font2
614
+ end
615
+ end
616
+
617
+ draw2 = Magick::Draw.new
618
+ img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
619
+ draw2.gravity = Magick::CenterGravity
620
+ draw2.pointsize = adjusted_size
621
+ draw2.fill = color2
622
+ draw2.stroke = 'none'
623
+ draw2.font = font2
499
624
  end
625
+
626
+ img.write('./image/memory.png')
627
+
628
+ rescue => e
629
+ puts "이미지 폰트 불러오기 오류 재시도... (#{e.message})"
630
+ sleep(3)
631
+ retry
632
+ end
500
633
  end
501
634
 
635
+
636
+
502
637
  def border()
503
638
  color = File.open('./color.ini', 'r',:encoding => 'utf-8').read().split("\n")
504
639
  img = Magick::Image.read('./image/memory.png').first
@@ -524,48 +659,86 @@ class Wordpress
524
659
  else
525
660
  auto_image()
526
661
  end
527
-
528
- image_size = [480,740,650,550,480]
662
+
663
+ # '원본'을 포함한 이미지 크기 옵션 추가
664
+ image_size = [480, 740, 650, 550, 480, 'original']
529
665
  size = 0
530
- for n in 0..4
666
+
667
+ for n in 0..5 # 0부터 5까지 반복, '원본' 옵션까지 포함
531
668
  if @data['image_size'][n].checked?
532
- if n == 0
533
- size = image_size.sample
669
+ if n == 5 # '원본'이 선택되었을 경우
670
+ size = 'original'
671
+ elsif n == 0
672
+ size = image_size.sample # 랜덤 선택
534
673
  else
535
674
  size = image_size[n]
536
675
  end
537
676
  end
538
677
  end
678
+
679
+ # '원본'이 선택되지 않았다면 기본 값 설정
539
680
  if size == 0
540
681
  size = 480
541
682
  end
683
+
684
+ change_image_size(size) # 크기 변경 함수 호출
542
685
 
543
- change_image_size(size)
544
686
 
545
687
  if @data['이미지설정']['필터사용'].checked?
546
688
  image_filter()
547
689
  end
548
690
 
549
- insert_image_text1 = ''
550
- insert_image_text2 = ''
551
691
  if @data['이미지설정']['글자삽입1'].checked?
552
- insert_image_text1 = @data['이미지설정']['이미지글자1'].sample
692
+ if @data['이미지설정']['이미지글자1'].length == 0
693
+ image_text_path1 = ''
694
+ else
695
+ if @data['이미지설정']['글자랜덤'].checked?
696
+ image_text_path1 = @data['이미지설정']['이미지글자1'].sample
697
+ else
698
+ image_text_path1 = @data['이미지설정']['이미지글자1'][@image_text_soon1]
699
+ @image_text_soon1 += 1
700
+ if @image_text_soon1 > @data['이미지설정']['이미지글자1'].length - 1
701
+ @image_text_soon1 = 0
702
+ end
703
+ end
704
+ end
553
705
  end
554
706
 
555
707
  if @data['이미지설정']['글자삽입2'].checked?
556
- insert_image_text2 = @data['이미지설정']['이미지글자2'].sample
708
+ if @data['이미지설정']['이미지글자2'].length == 0
709
+ image_text_path2 = ''
710
+ else
711
+ if @data['이미지설정']['글자랜덤'].checked?
712
+ image_text_path2 = @data['이미지설정']['이미지글자2'].sample
713
+ else
714
+ image_text_path2 = @data['이미지설정']['이미지글자2'][@image_text_soon2]
715
+ @image_text_soon2 += 1
716
+ if @image_text_soon2 > @data['이미지설정']['이미지글자2'].length - 1
717
+ @image_text_soon2 = 0
718
+ end
719
+ end
720
+ end
557
721
  end
558
-
722
+
559
723
  if @data['이미지설정']['글자삽입1'].checked? or @data['이미지설정']['글자삽입2'].checked?
560
- image_text(insert_image_text1, insert_image_text2)
724
+ image_text(image_text_path1, image_text_path2)
561
725
  end
562
726
 
563
727
  if @data['이미지설정']['테두리사용'].checked?
564
728
  border()
565
729
  end
566
730
 
731
+ sleep(1)
567
732
  time = Time.now.to_s.split(' ')[0..1].join('').split(':').join('').split('-').join('')
568
733
  FileUtils.cp('./image/memory.png', './image/'+@keyword+time+'.png')
734
+ hi_dir = Dir.pwd
735
+ iconv = Iconv.new('UTF-8', 'CP949')
736
+ begin
737
+ hi_dir = iconv.iconv(hi_dir)
738
+ rescue
739
+
740
+ end
741
+ return hi_dir+'/image/'+@keyword+time+'.png'
569
742
  end
570
743
 
571
744
  def image_update22
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wp_posting_zon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - zon
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-05-23 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