wp_posting_zon 0.0.3 → 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.
- checksums.yaml +4 -4
- data/lib/wp_posting_zon.rb +314 -79
- metadata +3 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5aeddc0ceb08cb7a26d1252f6b2e1c2b3cb3ee5c1404da3a2e97bf07c0ed0d0f
|
4
|
+
data.tar.gz: 3a33e130e13bc2ca04e57236c8620d03bfd29ed88b666882bb69e91746e1d056
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 959862a24098814c43dde5b88fe18ff2518c49d53c78e16c7f8d15ef8345d33fcada363599d7a06fd9e30d1ccf5fd4997f9be3f332677644dd3344e5958f17b4
|
7
|
+
data.tar.gz: 6ad3da66c7cc04822b594f32a64bb57051d05e7b61c7e9a5e7c3fe55712901c7142a5bf1f5245f1d2b78e8e77608f4ce3c36d23286202df4c83f461cc676e2b8
|
data/lib/wp_posting_zon.rb
CHANGED
@@ -11,6 +11,7 @@ require 'open3'
|
|
11
11
|
require 'zlib'
|
12
12
|
require 'stringio'
|
13
13
|
require 'timeout'
|
14
|
+
require 'httpclient'
|
14
15
|
|
15
16
|
class Wordpress
|
16
17
|
include Glimmer
|
@@ -337,23 +338,111 @@ class Wordpress
|
|
337
338
|
return @data2
|
338
339
|
end
|
339
340
|
|
340
|
-
def
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
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
|
345
|
+
|
346
|
+
|
347
|
+
|
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
|
352
|
+
|
353
|
+
cropped = img.crop(0, crop_top, width, new_height, true)
|
354
|
+
cropped.write(path)
|
355
|
+
|
356
|
+
|
357
|
+
else
|
358
|
+
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
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
|
391
|
+
|
392
|
+
json = JSON.parse(res.body)
|
393
|
+
results = json['results']
|
394
|
+
mm = []
|
395
|
+
|
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")
|
434
|
+
else
|
435
|
+
puts "랜덤 이미지 URL을 찾을 수 없습니다. 단색 배경 이미지 생성합니다."
|
436
|
+
color_image
|
348
437
|
end
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
sleep(5)
|
354
|
-
retry
|
438
|
+
else
|
439
|
+
puts "이미지 결과가 없어 다운로드할 수 없습니다. 단색 배경 이미지 생성합니다."
|
440
|
+
color_image
|
441
|
+
end
|
355
442
|
end
|
356
443
|
end
|
444
|
+
end
|
445
|
+
|
357
446
|
|
358
447
|
def color_image
|
359
448
|
color = File.open('./color.ini', 'r', :encoding => 'utf-8').read().split("\n")
|
@@ -363,80 +452,188 @@ class Wordpress
|
|
363
452
|
|
364
453
|
def save_image
|
365
454
|
if @data['이미지설정']['이미지'].length == 0
|
366
|
-
|
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
|
367
464
|
else
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
@image_counter = 0
|
373
|
-
end
|
374
|
-
else
|
375
|
-
image_path = @data['이미지설정']['이미지'].sample[2]
|
465
|
+
# 초기화가 안됐거나 다 썼으면 새롭게 섞는다
|
466
|
+
@shuffled_images ||= []
|
467
|
+
if @shuffled_images.empty?
|
468
|
+
@shuffled_images = @data['이미지설정']['이미지'].shuffle
|
376
469
|
end
|
377
|
-
|
378
|
-
|
470
|
+
|
471
|
+
image_path = @shuffled_images.shift[2]
|
379
472
|
end
|
473
|
+
|
474
|
+
img = Magick::Image.read(image_path).first
|
475
|
+
img.write('./image/memory.png')
|
380
476
|
end
|
381
477
|
|
382
478
|
def change_image_size(w)
|
383
479
|
img = Magick::Image.read('./image/memory.png').first
|
384
480
|
width = img.columns
|
385
481
|
height = img.rows
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
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) # 예외 처리 시에도 리사이징
|
391
497
|
end
|
392
|
-
rescue
|
393
|
-
img.resize!(w, w)
|
394
498
|
end
|
499
|
+
|
500
|
+
# 리사이징된 이미지 저장
|
395
501
|
img.write('./image/memory.png')
|
396
502
|
end
|
397
503
|
|
398
|
-
def
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
text.fill = '#000000'
|
417
|
-
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
|
418
522
|
end
|
419
523
|
end
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
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
|
430
534
|
end
|
431
|
-
|
432
|
-
|
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)
|
433
590
|
rescue
|
434
|
-
|
435
|
-
|
436
|
-
|
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
|
437
624
|
end
|
625
|
+
|
626
|
+
img.write('./image/memory.png')
|
627
|
+
|
628
|
+
rescue => e
|
629
|
+
puts "이미지 폰트 불러오기 오류 재시도... (#{e.message})"
|
630
|
+
sleep(3)
|
631
|
+
retry
|
632
|
+
end
|
438
633
|
end
|
439
634
|
|
635
|
+
|
636
|
+
|
440
637
|
def border()
|
441
638
|
color = File.open('./color.ini', 'r',:encoding => 'utf-8').read().split("\n")
|
442
639
|
img = Magick::Image.read('./image/memory.png').first
|
@@ -462,48 +659,86 @@ class Wordpress
|
|
462
659
|
else
|
463
660
|
auto_image()
|
464
661
|
end
|
465
|
-
|
466
|
-
|
662
|
+
|
663
|
+
# '원본'을 포함한 이미지 크기 옵션 추가
|
664
|
+
image_size = [480, 740, 650, 550, 480, 'original']
|
467
665
|
size = 0
|
468
|
-
|
666
|
+
|
667
|
+
for n in 0..5 # 0부터 5까지 반복, '원본' 옵션까지 포함
|
469
668
|
if @data['image_size'][n].checked?
|
470
|
-
if n ==
|
471
|
-
size =
|
669
|
+
if n == 5 # '원본'이 선택되었을 경우
|
670
|
+
size = 'original'
|
671
|
+
elsif n == 0
|
672
|
+
size = image_size.sample # 랜덤 선택
|
472
673
|
else
|
473
674
|
size = image_size[n]
|
474
675
|
end
|
475
676
|
end
|
476
677
|
end
|
678
|
+
|
679
|
+
# '원본'이 선택되지 않았다면 기본 값 설정
|
477
680
|
if size == 0
|
478
681
|
size = 480
|
479
682
|
end
|
683
|
+
|
684
|
+
change_image_size(size) # 크기 변경 함수 호출
|
480
685
|
|
481
|
-
change_image_size(size)
|
482
686
|
|
483
687
|
if @data['이미지설정']['필터사용'].checked?
|
484
688
|
image_filter()
|
485
689
|
end
|
486
690
|
|
487
|
-
insert_image_text1 = ''
|
488
|
-
insert_image_text2 = ''
|
489
691
|
if @data['이미지설정']['글자삽입1'].checked?
|
490
|
-
|
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
|
491
705
|
end
|
492
706
|
|
493
707
|
if @data['이미지설정']['글자삽입2'].checked?
|
494
|
-
|
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
|
495
721
|
end
|
496
|
-
|
722
|
+
|
497
723
|
if @data['이미지설정']['글자삽입1'].checked? or @data['이미지설정']['글자삽입2'].checked?
|
498
|
-
image_text(
|
724
|
+
image_text(image_text_path1, image_text_path2)
|
499
725
|
end
|
500
726
|
|
501
727
|
if @data['이미지설정']['테두리사용'].checked?
|
502
728
|
border()
|
503
729
|
end
|
504
730
|
|
731
|
+
sleep(1)
|
505
732
|
time = Time.now.to_s.split(' ')[0..1].join('').split(':').join('').split('-').join('')
|
506
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'
|
507
742
|
end
|
508
743
|
|
509
744
|
def image_update22
|
metadata
CHANGED
@@ -1,14 +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.
|
4
|
+
version: 0.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- zon
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date: 2025-
|
10
|
+
date: 2025-06-26 00:00:00.000000000 Z
|
12
11
|
dependencies: []
|
13
12
|
description: File to Clipboard gem
|
14
13
|
email: mymin26@naver.com
|
@@ -21,7 +20,6 @@ homepage: ''
|
|
21
20
|
licenses:
|
22
21
|
- zon
|
23
22
|
metadata: {}
|
24
|
-
post_install_message:
|
25
23
|
rdoc_options: []
|
26
24
|
require_paths:
|
27
25
|
- lib
|
@@ -36,8 +34,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
36
34
|
- !ruby/object:Gem::Version
|
37
35
|
version: '0'
|
38
36
|
requirements: []
|
39
|
-
rubygems_version: 3.
|
40
|
-
signing_key:
|
37
|
+
rubygems_version: 3.6.7
|
41
38
|
specification_version: 4
|
42
39
|
summary: file to clipboard
|
43
40
|
test_files: []
|