wp_posting_duo 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_duo.rb +303 -130
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 47717ece00cb608e31ccc7f3a77dfa14d31f3e9bbdc324c4265b4d3fe2792b07
4
- data.tar.gz: ac8078e3de95f30eae0ec01ee3a3916623be1b2cb0f97f2c353ebc87f38603a4
3
+ metadata.gz: 8f5792692b65f22913ddd7aa8405378e64d2df5580380a961a39233962888226
4
+ data.tar.gz: e8dbf27faf55c087cd7dc520fc2abcad4f7afba093869daa61edb9881d0b3d41
5
5
  SHA512:
6
- metadata.gz: 17b374d7691fe13d88491bd385ea8a3aec057dc968b47b22e8c92cf6e7978762ca2aa50bb8ef8460b5748428ec40613ec6165863647048c5bb4f57384fb28816
7
- data.tar.gz: ca106a19a91650171725c16058fc6fe076dcccacd66536a6cc7eb9100d31f1b5f00afc9fbe48ea21b002e2d1d6d110bc576642e95404bc4836e6d4ffc3e81d21
6
+ metadata.gz: 0f9684835d2fe336db76053d220cb854e624af6195348c68193716fbea417c62ce3246e6d02ba9521274343742bf2e060570cb38d1c51d82be63d665a722cdf1
7
+ data.tar.gz: 558cfa9f0c6eb0607282d6823e526aecf94fd2e4d2917124d4fa03380b868ffe7751a74e011344c6ee4d4e95be48766d9f43e69b8195b3f9ea8880d9b31964e4
@@ -403,83 +403,110 @@ class Wordpress
403
403
  return @data2
404
404
  end
405
405
 
406
- def auto_image(keyword = nil)
407
- keyword ||= @keyword
408
- puts "키워드: #{keyword}"
409
-
410
- client = HTTPClient.new
411
- client.default_header = {
412
- 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
413
- '(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
414
- 'Accept' => 'application/json, text/javascript, */*; q=0.01',
415
- 'Accept-Language' => 'en-US,en;q=0.9',
416
- 'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
417
- 'X-Requested-With' => 'XMLHttpRequest'
418
- }
406
+ def crop_image_height_under_width(path, min_crop_ratio = 0.625)
407
+ img = Magick::Image.read(path).first
408
+ width = img.columns
409
+ height = img.rows
419
410
 
420
- retry_count = 0
421
- max_retries = 10
422
- results = []
423
411
 
424
- begin
425
- page = rand(1..15)
426
- url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
427
- puts "Request URL: #{url}"
428
- res = client.get(url)
429
-
430
- unless res.status == 200
431
- puts "HTTP Error: #{res.status}"
432
- raise "HTTP Error"
433
- end
434
412
 
435
- json = JSON.parse(res.body)
436
- results = json['results']
437
- mm = []
413
+ if height > width
414
+ min_height = (width * min_crop_ratio).to_i
415
+ new_height = rand(min_height..width)
416
+ crop_top = ((height - new_height) / 2.0).round
438
417
 
439
- results.each do |photo|
440
- full_url = photo.dig('urls', 'full').to_s
441
- regular_url = photo.dig('urls', 'regular').to_s
418
+ cropped = img.crop(0, crop_top, width, new_height, true)
419
+ cropped.write(path)
442
420
 
443
- if full_url.start_with?("https://images.unsplash.com/photo-") &&
444
- regular_url.include?("1080")
445
- mm << full_url
446
- end
447
- end
421
+
422
+ else
423
+
424
+ end
425
+ end
448
426
 
449
- if mm.empty?
450
- raise "No matching image"
451
- end
427
+ def auto_image(keyword = nil)
428
+ # auto_image 내부에서만 crop 호출
429
+ keyword ||= @keyword
430
+ puts "키워드: #{keyword}"
431
+
432
+ client = HTTPClient.new
433
+ client.default_header = {
434
+ 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '\
435
+ '(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36',
436
+ 'Accept' => 'application/json, text/javascript, */*; q=0.01',
437
+ 'Accept-Language' => 'en-US,en;q=0.9',
438
+ 'Referer' => "https://unsplash.com/s/photos/#{URI.encode_www_form_component(keyword)}",
439
+ 'X-Requested-With' => 'XMLHttpRequest'
440
+ }
441
+
442
+ retry_count = 0
443
+ max_retries = 10
444
+ results = []
445
+
446
+ begin
447
+ page = rand(1..15)
448
+ url = "https://unsplash.com/napi/search/photos?query=#{URI.encode_www_form_component(keyword)}&page=#{page}&per_page=20"
449
+ puts "Request URL: #{url}"
450
+ res = client.get(url)
451
+
452
+ unless res.status == 200
453
+ puts "HTTP Error: #{res.status}"
454
+ raise "HTTP Error"
455
+ end
452
456
 
453
- selected_url = mm.sample
454
- Down.download(selected_url, destination: "./image/memory.png")
455
- puts "이미지 다운로드 완료: #{selected_url}"
457
+ json = JSON.parse(res.body)
458
+ results = json['results']
459
+ mm = []
456
460
 
457
- rescue => e
458
- retry_count += 1
459
- puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
460
- sleep(3)
461
- if retry_count < max_retries
462
- retry
463
- else
464
- puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
465
-
466
- if results && !results.empty?
467
- random_photo = results.sample
468
- fallback_url = random_photo.dig('urls', 'full')
469
- if fallback_url
470
- Down.download(fallback_url, destination: "./image/memory.png")
471
- puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
472
- else
473
- puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
474
- color_image
475
- end
461
+ results.each do |photo|
462
+ full_url = photo.dig('urls', 'full').to_s
463
+ regular_url = photo.dig('urls', 'regular').to_s
464
+
465
+ if full_url.start_with?("https://images.unsplash.com/photo-") &&
466
+ regular_url.include?("1080")
467
+ mm << full_url
468
+ end
469
+ end
470
+
471
+ if mm.empty?
472
+ raise "No matching image"
473
+ end
474
+
475
+ selected_url = mm.sample
476
+ destination_path = "./image/memory.png"
477
+ Down.download(selected_url, destination: destination_path)
478
+ puts "이미지 다운로드 완료: #{selected_url}"
479
+
480
+ # 오직 auto_image에서만 자르기 호출
481
+ crop_image_height_under_width(destination_path)
482
+
483
+ rescue => e
484
+ retry_count += 1
485
+ puts "auto_image 에러: #{e.message} (재시도 #{retry_count}/#{max_retries})"
486
+ sleep(3)
487
+ if retry_count < max_retries
488
+ retry
489
+ else
490
+ puts "최대 재시도 초과. 조건 무시하고 랜덤 이미지 다운로드 시도..."
491
+
492
+ if results && !results.empty?
493
+ random_photo = results.sample
494
+ fallback_url = random_photo.dig('urls', 'full')
495
+ if fallback_url
496
+ Down.download(fallback_url, destination: "./image/memory.png")
497
+ puts "랜덤 이미지 다운로드 완료: #{fallback_url}"
498
+ crop_image_height_under_width("./image/memory.png")
476
499
  else
477
- puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
478
- color_image
479
- end
500
+ puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
501
+ color_image
480
502
  end
503
+ else
504
+ puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
505
+ color_image
506
+ end
481
507
  end
482
508
  end
509
+ end
483
510
 
484
511
 
485
512
  def color_image
@@ -490,80 +517,188 @@ class Wordpress
490
517
 
491
518
  def save_image
492
519
  if @data['이미지설정']['이미지'].length == 0
493
-
520
+ return
521
+ end
522
+
523
+ if @data['이미지설정']['순서사용'].checked?
524
+ image_path = @data['이미지설정']['이미지'][@image_counter][2]
525
+ @image_counter += 1
526
+ if @image_counter > @data['이미지설정']['이미지'].length - 1
527
+ @image_counter = 0
528
+ end
494
529
  else
495
- if @data['이미지설정']['순서사용'].checked?
496
- image_path = @data['이미지설정']['이미지'][@image_counter][2]
497
- @image_counter += 1
498
- if @image_counter > @data['이미지설정']['이미지'].length-1
499
- @image_counter = 0
500
- end
501
- else
502
- image_path = @data['이미지설정']['이미지'].sample[2]
530
+ # 초기화가 안됐거나 다 썼으면 새롭게 섞는다
531
+ @shuffled_images ||= []
532
+ if @shuffled_images.empty?
533
+ @shuffled_images = @data['이미지설정']['이미지'].shuffle
503
534
  end
504
- img = Magick::Image.read(image_path).first
505
- img.write('./image/memory.png')
535
+
536
+ image_path = @shuffled_images.shift[2]
506
537
  end
538
+
539
+ img = Magick::Image.read(image_path).first
540
+ img.write('./image/memory.png')
507
541
  end
508
542
 
509
543
  def change_image_size(w)
510
544
  img = Magick::Image.read('./image/memory.png').first
511
545
  width = img.columns
512
546
  height = img.rows
513
- begin
514
- if @data['image_type'][0].checked? or @data['image_type'][2].checked?
515
- img.resize!(w, w*(height.to_f/width.to_f))
516
- else
517
- img.resize!(w, w)
547
+
548
+ # '원본' 선택된 경우, 리사이징을 하지 않고 원본 이미지를 그대로 반환
549
+ if w == 'original'
550
+ return img # 원본 이미지 그대로 반환
551
+ else
552
+ begin
553
+ if @data['image_type'][0].checked? or @data['image_type'][2].checked?
554
+ # 비율을 맞추어 리사이징
555
+ img.resize!(w, w * (height.to_f / width.to_f))
556
+ else
557
+ # 정사각형으로 리사이징
558
+ img.resize!(w, w)
559
+ end
560
+ rescue
561
+ img.resize!(w, w) # 예외 처리 시에도 리사이징
518
562
  end
519
- rescue
520
- img.resize!(w, w)
521
563
  end
564
+
565
+ # 리사이징된 이미지 저장
522
566
  img.write('./image/memory.png')
523
567
  end
524
568
 
525
- def image_text(text1, text2)
526
- begin
527
- color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
528
- font = Dir.entries('./fonts')
529
- img = Magick::Image.read('./image/memory.png').first
530
- text = Magick::Draw.new
531
- color2 = color.sample
532
- font2 = './fonts/'+font.sample
533
- message = text1.to_s+"\n"+text2.to_s
534
- begin
535
- size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
536
- rescue
537
- size = 30
538
- end
539
- if @data['이미지설정']['글자그림자'].checked?
540
- img.annotate(text, 0,0, +3,+3, message) do
541
- text.gravity = Magick::CenterGravity
542
- text.pointsize = size
543
- text.fill = '#000000'
544
- text.font = font2
569
+ def wrap_text_to_fit(draw, text, max_width, max_height, font_path, initial_size)
570
+ size = initial_size
571
+ draw.font = font_path
572
+
573
+ loop do
574
+ draw.pointsize = size
575
+ words = text.chars # 글자 단위로 자름 (한국어 기준)
576
+ lines = []
577
+ line = ""
578
+
579
+ words.each do |char|
580
+ test_line = line + char
581
+ metrics = draw.get_type_metrics(test_line)
582
+ if metrics.width > max_width
583
+ lines << line
584
+ line = char
585
+ else
586
+ line = test_line
545
587
  end
546
588
  end
547
-
548
- img.annotate(text, 0,0,0,0, message) do
549
- text.gravity = Magick::CenterGravity
550
- text.pointsize = size
551
- if @data['이미지설정']['글자테두리'].checked?
552
- text.stroke_width = 2
553
- text.stroke = '#000000'
554
- end
555
- text.fill = color2
556
- text.font = font2
589
+ lines << line unless line.empty?
590
+
591
+ line_height = draw.get_type_metrics("가").height
592
+ total_height = line_height * lines.size
593
+
594
+ # 세로 초과 안 하면 성공
595
+ if total_height <= max_height || size <= 10
596
+ return [lines.join("\n"), size]
597
+ else
598
+ size -= 2
557
599
  end
558
-
559
- img.write('./image/memory.png')
600
+ end
601
+ end
602
+
603
+
604
+ def image_text(text1, text2)
605
+ begin
606
+ color = File.open('./color.ini', 'r', encoding: 'utf-8').read.split("\n").map(&:strip).reject(&:empty?)
607
+ font_files = Dir.entries('./fonts').select { |f| f.downcase.end_with?('.ttf') }
608
+ font2 = './fonts/' + font_files.sample
609
+
610
+ # 랜덤 글자색 선택
611
+ color2 = color.sample
612
+
613
+ # 헬퍼 함수: 색상 문자열 '#RRGGBB' -> [R,G,B] 배열로 변환
614
+ def hex_to_rgb(hex)
615
+ hex = hex.delete('#')
616
+ [hex[0..1], hex[2..3], hex[4..5]].map { |c| c.to_i(16) }
617
+ end
618
+
619
+ # 헬퍼 함수: 두 RGB 색상의 차이 계산 (간단한 유클리드 거리)
620
+ def color_distance(c1, c2)
621
+ Math.sqrt(
622
+ (c1[0] - c2[0])**2 +
623
+ (c1[1] - c2[1])**2 +
624
+ (c1[2] - c2[2])**2
625
+ )
626
+ end
627
+
628
+ # 대비가 충분히 되는 테두리 색상 선택
629
+ max_attempts = 10
630
+ stroke_color = nil
631
+ base_rgb = hex_to_rgb(color2)
632
+
633
+ max_attempts.times do
634
+ candidate = color.sample
635
+ candidate_rgb = hex_to_rgb(candidate)
636
+ dist = color_distance(base_rgb, candidate_rgb)
637
+
638
+ # 거리(차이) 임계값 100 (0~441 범위) — 필요시 조절 가능
639
+ if dist > 100
640
+ stroke_color = candidate
641
+ break
642
+ end
643
+ end
644
+ stroke_color ||= '#000000' # 만약 충분히 다른 색 없으면 검정색 기본값
645
+
646
+ img = Magick::Image.read('./image/memory.png').first
647
+ draw = Magick::Draw.new
648
+
649
+ raw_message = "#{text1}\n#{text2}".strip
650
+ max_width = img.columns * 0.85
651
+ max_height = img.rows * 0.6
652
+
653
+ begin
654
+ size = rand(@data['이미지설정']['이미지글자1크기1'].text.to_i..@data['이미지설정']['이미지글자1크기2'].text.to_i)
560
655
  rescue
561
- puts '이미지 폰트 불러오기 오류 재시도...'
562
- sleep(3)
563
- retry
656
+ size = 30
657
+ end
658
+
659
+ wrapped_message, adjusted_size = wrap_text_to_fit(draw, raw_message, max_width, max_height, font2, size)
660
+
661
+ if @data['이미지설정']['글자그림자'].checked?
662
+ img.annotate(draw, 0, 0, 2, 2, wrapped_message) do
663
+ draw.gravity = Magick::CenterGravity
664
+ draw.pointsize = adjusted_size
665
+ draw.fill = '#000000'
666
+ draw.font = font2
667
+ end
668
+ end
669
+
670
+ if @data['이미지설정']['글자테두리'].checked?
671
+ draw_stroke = Magick::Draw.new
672
+ img.annotate(draw_stroke, 0, 0, 0, 0, wrapped_message) do
673
+ draw_stroke.gravity = Magick::CenterGravity
674
+ draw_stroke.pointsize = adjusted_size
675
+ draw_stroke.fill = 'none'
676
+ draw_stroke.stroke = stroke_color
677
+ draw_stroke.stroke_width = rand(5..10)
678
+ draw_stroke.font = font2
679
+ end
680
+ end
681
+
682
+ draw2 = Magick::Draw.new
683
+ img.annotate(draw2, 0, 0, 0, 0, wrapped_message) do
684
+ draw2.gravity = Magick::CenterGravity
685
+ draw2.pointsize = adjusted_size
686
+ draw2.fill = color2
687
+ draw2.stroke = 'none'
688
+ draw2.font = font2
564
689
  end
690
+
691
+ img.write('./image/memory.png')
692
+
693
+ rescue => e
694
+ puts "이미지 폰트 불러오기 오류 재시도... (#{e.message})"
695
+ sleep(3)
696
+ retry
697
+ end
565
698
  end
566
699
 
700
+
701
+
567
702
  def border()
568
703
  color = File.open('./color.ini', 'r',:encoding => 'utf-8').read().split("\n")
569
704
  img = Magick::Image.read('./image/memory.png').first
@@ -589,48 +724,86 @@ class Wordpress
589
724
  else
590
725
  auto_image()
591
726
  end
592
-
593
- image_size = [480,740,650,550,480]
727
+
728
+ # '원본'을 포함한 이미지 크기 옵션 추가
729
+ image_size = [480, 740, 650, 550, 480, 'original']
594
730
  size = 0
595
- for n in 0..4
731
+
732
+ for n in 0..5 # 0부터 5까지 반복, '원본' 옵션까지 포함
596
733
  if @data['image_size'][n].checked?
597
- if n == 0
598
- size = image_size.sample
734
+ if n == 5 # '원본'이 선택되었을 경우
735
+ size = 'original'
736
+ elsif n == 0
737
+ size = image_size.sample # 랜덤 선택
599
738
  else
600
739
  size = image_size[n]
601
740
  end
602
741
  end
603
742
  end
743
+
744
+ # '원본'이 선택되지 않았다면 기본 값 설정
604
745
  if size == 0
605
746
  size = 480
606
747
  end
748
+
749
+ change_image_size(size) # 크기 변경 함수 호출
607
750
 
608
- change_image_size(size)
609
751
 
610
752
  if @data['이미지설정']['필터사용'].checked?
611
753
  image_filter()
612
754
  end
613
755
 
614
- insert_image_text1 = ''
615
- insert_image_text2 = ''
616
756
  if @data['이미지설정']['글자삽입1'].checked?
617
- insert_image_text1 = @data['이미지설정']['이미지글자1'].sample
757
+ if @data['이미지설정']['이미지글자1'].length == 0
758
+ image_text_path1 = ''
759
+ else
760
+ if @data['이미지설정']['글자랜덤'].checked?
761
+ image_text_path1 = @data['이미지설정']['이미지글자1'].sample
762
+ else
763
+ image_text_path1 = @data['이미지설정']['이미지글자1'][@image_text_soon1]
764
+ @image_text_soon1 += 1
765
+ if @image_text_soon1 > @data['이미지설정']['이미지글자1'].length - 1
766
+ @image_text_soon1 = 0
767
+ end
768
+ end
769
+ end
618
770
  end
619
771
 
620
772
  if @data['이미지설정']['글자삽입2'].checked?
621
- insert_image_text2 = @data['이미지설정']['이미지글자2'].sample
773
+ if @data['이미지설정']['이미지글자2'].length == 0
774
+ image_text_path2 = ''
775
+ else
776
+ if @data['이미지설정']['글자랜덤'].checked?
777
+ image_text_path2 = @data['이미지설정']['이미지글자2'].sample
778
+ else
779
+ image_text_path2 = @data['이미지설정']['이미지글자2'][@image_text_soon2]
780
+ @image_text_soon2 += 1
781
+ if @image_text_soon2 > @data['이미지설정']['이미지글자2'].length - 1
782
+ @image_text_soon2 = 0
783
+ end
784
+ end
785
+ end
622
786
  end
623
-
787
+
624
788
  if @data['이미지설정']['글자삽입1'].checked? or @data['이미지설정']['글자삽입2'].checked?
625
- image_text(insert_image_text1, insert_image_text2)
789
+ image_text(image_text_path1, image_text_path2)
626
790
  end
627
791
 
628
792
  if @data['이미지설정']['테두리사용'].checked?
629
793
  border()
630
794
  end
631
795
 
796
+ sleep(1)
632
797
  time = Time.now.to_s.split(' ')[0..1].join('').split(':').join('').split('-').join('')
633
798
  FileUtils.cp('./image/memory.png', './image/'+@keyword+time+'.png')
799
+ hi_dir = Dir.pwd
800
+ iconv = Iconv.new('UTF-8', 'CP949')
801
+ begin
802
+ hi_dir = iconv.iconv(hi_dir)
803
+ rescue
804
+
805
+ end
806
+ return hi_dir+'/image/'+@keyword+time+'.png'
634
807
  end
635
808
 
636
809
  def image_update22
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wp_posting_duo
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