duo_cafe_comment 0.0.50 → 0.0.51
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/duo_cafe_comment.rb +2188 -518
- metadata +2 -2
data/lib/duo_cafe_comment.rb
CHANGED
@@ -493,36 +493,7 @@ class Naver
|
|
493
493
|
sleep(1)
|
494
494
|
@driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="cafe_main"]')) # 아이프레임 선택
|
495
495
|
|
496
|
-
|
497
|
-
@content_soon ||= 0 # 초기 한 번만 0으로 세팅
|
498
|
-
|
499
|
-
if @data['내용설정']['내용'].nil? || @data['내용설정']['내용'].empty?
|
500
|
-
content = ''
|
501
|
-
else
|
502
|
-
if @data.dig('내용설정', '랜덤사용')&.respond_to?(:checked?) && @data['내용설정']['랜덤사용'].checked?
|
503
|
-
content = @data['내용설정']['내용'].sample[2]
|
504
|
-
else
|
505
|
-
content = @data['내용설정']['내용'][@content_soon][2]
|
506
|
-
@content_soon += 1
|
507
|
-
@content_soon = 0 if @content_soon >= @data['내용설정']['내용'].length
|
508
|
-
end
|
509
|
-
end
|
510
|
-
else
|
511
|
-
end
|
512
|
-
|
513
|
-
# 디엠 자동 변경이 체크된 경우 content를 변환
|
514
|
-
if @data['포스트설정']['내용자동변경'].checked?
|
515
|
-
change_memory = {}
|
516
|
-
@data['포스트설정']['내용자동변경값'].each do |key, v|
|
517
|
-
change_memory[key] = v.sample
|
518
|
-
end
|
519
|
-
@data['포스트설정']['내용자동변경값'].each do |key, _|
|
520
|
-
if content.include?(key)
|
521
|
-
content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
|
522
|
-
else
|
523
|
-
end
|
524
|
-
end
|
525
|
-
end
|
496
|
+
|
526
497
|
|
527
498
|
if option['좋아요'] == 'true'
|
528
499
|
puts "좋아요 클릭 옵션 진행!!".cyan
|
@@ -551,134 +522,707 @@ class Naver
|
|
551
522
|
else
|
552
523
|
end
|
553
524
|
|
554
|
-
|
555
|
-
begin
|
556
|
-
wait = Selenium::WebDriver::Wait.new(:timeout => 10)
|
557
|
-
wait.until { @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]') }
|
558
|
-
|
559
|
-
# 댓글 입력
|
560
|
-
element = @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]')
|
561
|
-
@driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
|
562
|
-
sleep(1)
|
563
|
-
if option['ChatGPT사용'] == 'true'
|
564
|
-
pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
|
565
|
-
sleep(1)
|
566
525
|
|
567
|
-
puts "ChatGPT로 댓글을 만드는 중입니다."
|
568
|
-
@api_key = api_key
|
569
|
-
url = 'https://api.openai.com/v1/chat/completions'
|
570
|
-
headers = {
|
571
|
-
'Content-Type' => 'application/json',
|
572
|
-
'Authorization' => 'Bearer ' + @api_key
|
573
|
-
}
|
574
|
-
data = {
|
575
|
-
'model' => 'gpt-3.5-turbo',
|
576
|
-
'messages' => [
|
577
|
-
{ "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
|
578
|
-
{ "role" => "user", "content" => pcol1 } # pcol1 직접 사용
|
579
|
-
]
|
580
|
-
}
|
581
526
|
|
527
|
+
if option['re_coment'] == 'true' # 대 댓글 작업때
|
528
|
+
if @data['포스트설정']['전체대댓글'].checked?
|
582
529
|
begin
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
530
|
+
comment_items = @driver.find_elements(:css, 'li.CommentItem')
|
531
|
+
original_comments = comment_items.select { |item| !item.attribute('class').include?('CommentItem--reply') }
|
532
|
+
|
533
|
+
original_comments.each_with_index do |item, index|
|
534
|
+
|
535
|
+
begin
|
536
|
+
|
537
|
+
if @data['포스트설정']['순서사용2'].checked?
|
538
|
+
@content_soon ||= 0 # 초기 한 번만 0으로 세팅
|
539
|
+
|
540
|
+
if @data['내용설정']['내용'].nil? || @data['내용설정']['내용'].empty?
|
541
|
+
content = ''
|
542
|
+
else
|
543
|
+
if @data.dig('내용설정', '랜덤사용')&.respond_to?(:checked?) && @data['내용설정']['랜덤사용'].checked?
|
544
|
+
content = @data['내용설정']['내용'].sample[2]
|
545
|
+
else
|
546
|
+
content = @data['내용설정']['내용'][@content_soon][2]
|
547
|
+
@content_soon += 1
|
548
|
+
@content_soon = 0 if @content_soon >= @data['내용설정']['내용'].length
|
549
|
+
end
|
550
|
+
end
|
551
|
+
else
|
552
|
+
end
|
553
|
+
|
554
|
+
# 디엠 자동 변경이 체크된 경우 content를 변환
|
555
|
+
if @data['포스트설정']['내용자동변경'].checked?
|
556
|
+
change_memory = {}
|
557
|
+
@data['포스트설정']['내용자동변경값'].each do |key, v|
|
558
|
+
change_memory[key] = v.sample
|
559
|
+
end
|
560
|
+
@data['포스트설정']['내용자동변경값'].each do |key, _|
|
561
|
+
if content.include?(key)
|
562
|
+
content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
|
563
|
+
else
|
564
|
+
end
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
568
|
+
if option['ChatGPT사용'] == 'true'
|
569
|
+
pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
|
570
|
+
sleep(1)
|
571
|
+
|
572
|
+
puts "ChatGPT로 댓글을 만드는 중입니다."
|
573
|
+
@api_key = api_key
|
574
|
+
url = 'https://api.openai.com/v1/chat/completions'
|
575
|
+
headers = {
|
576
|
+
'Content-Type' => 'application/json',
|
577
|
+
'Authorization' => 'Bearer ' + @api_key
|
578
|
+
}
|
579
|
+
data = {
|
580
|
+
'model' => 'gpt-3.5-turbo',
|
581
|
+
'messages' => [
|
582
|
+
{ "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
|
583
|
+
{ "role" => "user", "content" => pcol1 } # pcol1 직접 사용
|
584
|
+
]
|
585
|
+
}
|
586
|
+
|
587
|
+
begin
|
588
|
+
req = HTTP.headers(headers).post(url, json: data)
|
589
|
+
puts "HTTP Status: #{req.status}" # 상태 코드 확인
|
590
|
+
response = JSON.parse(req.body.to_s)
|
591
|
+
puts "API Response: #{response}" # 전체 응답 출력
|
592
|
+
|
593
|
+
if req.status == 429
|
594
|
+
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
595
|
+
end
|
596
|
+
|
597
|
+
# 응답 데이터에서 안전하게 값 추출
|
598
|
+
raw_content = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
|
599
|
+
content = raw_content.gsub(/\. /, ".\n") # 줄바꿈 추가
|
600
|
+
|
601
|
+
rescue => e
|
602
|
+
puts "Error: #{e.message}"
|
603
|
+
content = "오류가 발생했습니다."
|
604
|
+
end
|
605
|
+
else
|
606
|
+
end
|
607
|
+
|
608
|
+
reply_button = item.find_element(:css, 'a.comment_info_button')
|
609
|
+
puts "대댓글 #{index + 1} 작성 중..."
|
610
|
+
reply_button.click
|
611
|
+
sleep(1.5)
|
612
|
+
|
613
|
+
textarea = @driver.find_element(:css, 'textarea.comment_inbox_text')
|
614
|
+
textarea.send_keys(content)
|
615
|
+
sleep(1)
|
616
|
+
|
617
|
+
if option['이모티콘자동삽입'] == 'true'
|
618
|
+
puts "이모티콘 자동 삽입 옵션 진행!!".cyan
|
619
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
620
|
+
reply_comments.each_with_index do |item, index|
|
621
|
+
begin
|
622
|
+
|
623
|
+
|
624
|
+
# 해당 대댓글 내부의 이모티콘 버튼 찾기
|
625
|
+
sticker_button = item.find_element(:css, 'a.button_sticker')
|
626
|
+
sticker_button.click
|
627
|
+
sleep(1)
|
628
|
+
|
629
|
+
rescue
|
630
|
+
end
|
631
|
+
end
|
632
|
+
begin
|
633
|
+
# 'se2_line_sticker_set' 클래스를 가진 <ul> 요소 안의 모든 <li> 요소 찾기
|
634
|
+
sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
|
635
|
+
|
636
|
+
# 16개 <li> 요소 중 랜덤으로 하나 선택하여 클릭
|
637
|
+
random_li = sticker_list_elements.sample
|
638
|
+
random_button = random_li.find_element(:tag_name, 'button') # <button> 태그 찾기
|
639
|
+
random_button.click
|
640
|
+
|
641
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
642
|
+
|
643
|
+
# 첫 번째 클릭한 <li> 내에서 버튼을 찾기
|
644
|
+
inner_buttons = random_li.find_elements(:tag_name, 'button')
|
645
|
+
|
646
|
+
# 20개 <button> 요소 중 랜덤으로 하나 선택하여 클릭
|
647
|
+
random_button_in_li = inner_buttons.sample
|
648
|
+
sleep(1)
|
649
|
+
random_button_in_li.click
|
650
|
+
|
651
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
652
|
+
|
653
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError => e
|
654
|
+
#puts "Stale element reference 오류 발생, 계속 진행: #{e.message}".yellow
|
655
|
+
# 오류 발생 시에도 계속 진행하려면 작업을 계속하도록 처리
|
656
|
+
# 예를 들어, continue, or next 등으로 다음 단계로 넘어갈 수 있습니다.
|
657
|
+
|
658
|
+
rescue => e
|
659
|
+
puts "기타 오류로 인해 이모티콘 삽입 안됨"
|
660
|
+
# 기타 오류 처리
|
661
|
+
# 여기에 추가적인 예외 처리 로직을 넣을 수 있습니다.
|
662
|
+
end
|
663
|
+
else
|
664
|
+
puts "이모티콘 자동 삽입 옵션이 비활성화됨."
|
665
|
+
end
|
666
|
+
|
667
|
+
# 이미지 자동 삽입
|
668
|
+
if option['이미지자동삽입'] == 'true'
|
669
|
+
puts "이미지 자동 상입 옵션 진행!!".cyan
|
670
|
+
|
671
|
+
# 아이프레임 요소가 나타날 때까지 기다립니다.
|
672
|
+
@image = image
|
673
|
+
image_path = image
|
674
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
675
|
+
|
676
|
+
reply_comments.each_with_index do |item, index|
|
677
|
+
begin
|
678
|
+
|
679
|
+
|
680
|
+
# 해당 대댓글 내부에서 for="attach2"인 라벨 클릭
|
681
|
+
attach_button = item.find_element(:xpath, './/*[@class="button_file"]')
|
682
|
+
attach_button.click
|
683
|
+
sleep(1)
|
684
|
+
|
685
|
+
rescue
|
686
|
+
end
|
687
|
+
end
|
688
|
+
key_stroke('escape')
|
689
|
+
# 파일 경로 자동 입력
|
690
|
+
file_input = @driver.find_element(:xpath, '//*[@title="사진첨부"]')
|
691
|
+
|
692
|
+
# send_keys로 파일 경로를 입력하여 이미지 업로드
|
693
|
+
file_input.send_keys(image_path)
|
694
|
+
sleep(2)
|
695
|
+
|
696
|
+
else
|
697
|
+
end
|
698
|
+
|
699
|
+
register_btn = @driver.find_element(:css, 'a.button.btn_register')
|
700
|
+
register_btn.click
|
701
|
+
sleep(2)
|
702
|
+
|
703
|
+
rescue => e
|
704
|
+
puts "대댓글 #{index + 1} 처리 중 오류 발생: #{e.message}"
|
705
|
+
next
|
706
|
+
end
|
707
|
+
end
|
596
708
|
rescue => e
|
597
|
-
|
598
|
-
answer = "오류가 발생했습니다."
|
709
|
+
puts "전체대댓글 처리 중 예외 발생: #{e.message}"
|
599
710
|
end
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
711
|
+
|
712
|
+
elsif @data['포스트설정']['지정대댓글'].checked?
|
713
|
+
targets = @data['포스트설정']['nik_or_number'].text.to_s.force_encoding('utf-8').split(',').map(&:strip)
|
714
|
+
targets.each do |target|
|
715
|
+
if target.match?(/^\d+$/)
|
716
|
+
index = target.to_i - 1
|
717
|
+
comment_items = @driver.find_elements(:css, 'li.CommentItem')
|
718
|
+
original_comments = comment_items.select { |item| !item.attribute('class').include?('CommentItem--reply') }
|
719
|
+
|
720
|
+
if original_comments[index]
|
721
|
+
begin
|
722
|
+
|
723
|
+
if @data['포스트설정']['순서사용2'].checked?
|
724
|
+
@content_soon ||= 0 # 초기 한 번만 0으로 세팅
|
725
|
+
|
726
|
+
if @data['내용설정']['내용'].nil? || @data['내용설정']['내용'].empty?
|
727
|
+
content = ''
|
728
|
+
else
|
729
|
+
if @data.dig('내용설정', '랜덤사용')&.respond_to?(:checked?) && @data['내용설정']['랜덤사용'].checked?
|
730
|
+
content = @data['내용설정']['내용'].sample[2]
|
731
|
+
else
|
732
|
+
content = @data['내용설정']['내용'][@content_soon][2]
|
733
|
+
@content_soon += 1
|
734
|
+
@content_soon = 0 if @content_soon >= @data['내용설정']['내용'].length
|
735
|
+
end
|
736
|
+
end
|
737
|
+
else
|
738
|
+
end
|
739
|
+
|
740
|
+
# 디엠 자동 변경이 체크된 경우 content를 변환
|
741
|
+
if @data['포스트설정']['내용자동변경'].checked?
|
742
|
+
change_memory = {}
|
743
|
+
@data['포스트설정']['내용자동변경값'].each do |key, v|
|
744
|
+
change_memory[key] = v.sample
|
745
|
+
end
|
746
|
+
@data['포스트설정']['내용자동변경값'].each do |key, _|
|
747
|
+
if content.include?(key)
|
748
|
+
content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
|
749
|
+
else
|
750
|
+
end
|
751
|
+
end
|
752
|
+
end
|
753
|
+
|
754
|
+
if option['ChatGPT사용'] == 'true'
|
755
|
+
pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
|
756
|
+
sleep(1)
|
757
|
+
|
758
|
+
puts "ChatGPT로 댓글을 만드는 중입니다."
|
759
|
+
@api_key = api_key
|
760
|
+
url = 'https://api.openai.com/v1/chat/completions'
|
761
|
+
headers = {
|
762
|
+
'Content-Type' => 'application/json',
|
763
|
+
'Authorization' => 'Bearer ' + @api_key
|
764
|
+
}
|
765
|
+
data = {
|
766
|
+
'model' => 'gpt-3.5-turbo',
|
767
|
+
'messages' => [
|
768
|
+
{ "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
|
769
|
+
{ "role" => "user", "content" => pcol1 } # pcol1 직접 사용
|
770
|
+
]
|
771
|
+
}
|
772
|
+
|
773
|
+
begin
|
774
|
+
req = HTTP.headers(headers).post(url, json: data)
|
775
|
+
puts "HTTP Status: #{req.status}" # 상태 코드 확인
|
776
|
+
response = JSON.parse(req.body.to_s)
|
777
|
+
puts "API Response: #{response}" # 전체 응답 출력
|
778
|
+
|
779
|
+
if req.status == 429
|
780
|
+
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
781
|
+
end
|
782
|
+
|
783
|
+
# 응답 데이터에서 안전하게 값 추출
|
784
|
+
raw_content = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
|
785
|
+
content = raw_content.gsub(/\. /, ".\n") # 줄바꿈 추가
|
786
|
+
|
787
|
+
rescue => e
|
788
|
+
puts "Error: #{e.message}"
|
789
|
+
content = "오류가 발생했습니다."
|
790
|
+
end
|
791
|
+
else
|
792
|
+
end
|
793
|
+
|
794
|
+
puts "#{index + 1}번째 댓글에 대댓글 작성 시작"
|
795
|
+
reply_button = original_comments[index].find_element(:css, 'a.comment_info_button')
|
796
|
+
reply_button.click
|
797
|
+
sleep(1.5)
|
798
|
+
|
799
|
+
textarea = @driver.find_element(:css, 'textarea.comment_inbox_text')
|
800
|
+
textarea.send_keys(content)
|
801
|
+
sleep(1)
|
802
|
+
|
803
|
+
if option['이모티콘자동삽입'] == 'true'
|
804
|
+
puts "이모티콘 자동 삽입 옵션 진행!!".cyan
|
805
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
806
|
+
reply_comments.each_with_index do |item, index|
|
807
|
+
begin
|
808
|
+
|
809
|
+
|
810
|
+
# 해당 대댓글 내부의 이모티콘 버튼 찾기
|
811
|
+
sticker_button = item.find_element(:css, 'a.button_sticker')
|
812
|
+
sticker_button.click
|
813
|
+
sleep(1)
|
814
|
+
|
815
|
+
rescue
|
816
|
+
end
|
817
|
+
end
|
818
|
+
|
819
|
+
begin
|
820
|
+
# 'se2_line_sticker_set' 클래스를 가진 <ul> 요소 안의 모든 <li> 요소 찾기
|
821
|
+
sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
|
822
|
+
|
823
|
+
# 16개 <li> 요소 중 랜덤으로 하나 선택하여 클릭
|
824
|
+
random_li = sticker_list_elements.sample
|
825
|
+
random_button = random_li.find_element(:tag_name, 'button') # <button> 태그 찾기
|
826
|
+
random_button.click
|
827
|
+
|
828
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
829
|
+
|
830
|
+
# 첫 번째 클릭한 <li> 내에서 버튼을 찾기
|
831
|
+
inner_buttons = random_li.find_elements(:tag_name, 'button')
|
832
|
+
|
833
|
+
# 20개 <button> 요소 중 랜덤으로 하나 선택하여 클릭
|
834
|
+
random_button_in_li = inner_buttons.sample
|
835
|
+
sleep(1)
|
836
|
+
random_button_in_li.click
|
837
|
+
|
838
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
839
|
+
|
840
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError => e
|
841
|
+
#puts "Stale element reference 오류 발생, 계속 진행: #{e.message}".yellow
|
842
|
+
# 오류 발생 시에도 계속 진행하려면 작업을 계속하도록 처리
|
843
|
+
# 예를 들어, continue, or next 등으로 다음 단계로 넘어갈 수 있습니다.
|
844
|
+
|
845
|
+
rescue => e
|
846
|
+
puts "기타 오류로 인해 이모티콘 삽입 안됨"
|
847
|
+
# 기타 오류 처리
|
848
|
+
# 여기에 추가적인 예외 처리 로직을 넣을 수 있습니다.
|
849
|
+
end
|
850
|
+
else
|
851
|
+
puts "이모티콘 자동 삽입 옵션이 비활성화됨."
|
852
|
+
end
|
853
|
+
|
854
|
+
# 이미지 자동 삽입
|
855
|
+
if option['이미지자동삽입'] == 'true'
|
856
|
+
puts "이미지 자동 상입 옵션 진행!!".cyan
|
857
|
+
|
858
|
+
# 아이프레임 요소가 나타날 때까지 기다립니다.
|
859
|
+
@image = image
|
860
|
+
image_path = image
|
861
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
862
|
+
|
863
|
+
reply_comments.each_with_index do |item, index|
|
864
|
+
begin
|
865
|
+
|
866
|
+
|
867
|
+
# 해당 대댓글 내부에서 for="attach2"인 라벨 클릭
|
868
|
+
attach_button = item.find_element(:xpath, './/*[@class="button_file"]')
|
869
|
+
attach_button.click
|
870
|
+
sleep(1)
|
871
|
+
|
872
|
+
rescue
|
873
|
+
end
|
874
|
+
end
|
875
|
+
key_stroke('escape')
|
876
|
+
# 파일 경로 자동 입력
|
877
|
+
file_input = @driver.find_element(:xpath, '//*[@title="사진첨부"]')
|
878
|
+
|
879
|
+
# send_keys로 파일 경로를 입력하여 이미지 업로드
|
880
|
+
file_input.send_keys(image_path)
|
881
|
+
sleep(2)
|
882
|
+
|
883
|
+
else
|
884
|
+
end
|
885
|
+
|
886
|
+
register_btn = @driver.find_element(:css, 'a.button.btn_register')
|
887
|
+
register_btn.click
|
888
|
+
sleep(2)
|
889
|
+
|
890
|
+
puts "#{index + 1}번째 댓글에 대댓글 작성 완료"
|
891
|
+
rescue => e
|
892
|
+
puts "댓글 인덱스 #{index + 1} 처리 중 오류 발생: #{e.message}"
|
893
|
+
end
|
894
|
+
else
|
895
|
+
puts "해당 인덱스(#{index + 1})의 답글쓰기 버튼이 없습니다."
|
896
|
+
end
|
897
|
+
|
898
|
+
else # 닉네임으로 찾기
|
899
|
+
comment_items = @driver.find_elements(:css, 'li.CommentItem')
|
900
|
+
original_comments = comment_items.select { |item| !item.attribute('class').include?('CommentItem--reply') }
|
901
|
+
|
902
|
+
matched = false
|
903
|
+
last_matched_item = nil # 마지막에 닉네임이 일치한 댓글 저장
|
904
|
+
|
905
|
+
original_comments.each_with_index do |item, idx|
|
906
|
+
begin
|
907
|
+
nickname_element = item.find_element(:css, 'a.comment_nickname')
|
908
|
+
nickname = nickname_element.text.strip
|
909
|
+
|
910
|
+
if nickname.include?(target)
|
911
|
+
puts "#{target} 닉네임이 포함된 댓글 발견 (#{idx + 1}번째)"
|
912
|
+
last_matched_item = item # 매번 갱신 → 마지막에 발견된 걸 저장
|
913
|
+
end
|
914
|
+
rescue => e
|
915
|
+
puts "닉네임 검사 중 오류 발생: #{e.message}"
|
916
|
+
next
|
917
|
+
end
|
918
|
+
end
|
919
|
+
|
920
|
+
# 루프 끝난 뒤 마지막 댓글에만 작업 실행
|
921
|
+
if last_matched_item
|
922
|
+
begin
|
923
|
+
|
924
|
+
if @data['포스트설정']['순서사용2'].checked?
|
925
|
+
@content_soon ||= 0 # 초기 한 번만 0으로 세팅
|
926
|
+
|
927
|
+
if @data['내용설정']['내용'].nil? || @data['내용설정']['내용'].empty?
|
928
|
+
content = ''
|
929
|
+
else
|
930
|
+
if @data.dig('내용설정', '랜덤사용')&.respond_to?(:checked?) && @data['내용설정']['랜덤사용'].checked?
|
931
|
+
content = @data['내용설정']['내용'].sample[2]
|
932
|
+
else
|
933
|
+
content = @data['내용설정']['내용'][@content_soon][2]
|
934
|
+
@content_soon += 1
|
935
|
+
@content_soon = 0 if @content_soon >= @data['내용설정']['내용'].length
|
936
|
+
end
|
937
|
+
end
|
938
|
+
else
|
939
|
+
end
|
940
|
+
|
941
|
+
# 디엠 자동 변경이 체크된 경우 content를 변환
|
942
|
+
if @data['포스트설정']['내용자동변경'].checked?
|
943
|
+
change_memory = {}
|
944
|
+
@data['포스트설정']['내용자동변경값'].each do |key, v|
|
945
|
+
change_memory[key] = v.sample
|
946
|
+
end
|
947
|
+
@data['포스트설정']['내용자동변경값'].each do |key, _|
|
948
|
+
if content.include?(key)
|
949
|
+
content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
|
950
|
+
else
|
951
|
+
end
|
952
|
+
end
|
953
|
+
end
|
954
|
+
|
955
|
+
if option['ChatGPT사용'] == 'true'
|
956
|
+
pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
|
957
|
+
sleep(1)
|
958
|
+
|
959
|
+
puts "ChatGPT로 댓글을 만드는 중입니다."
|
960
|
+
@api_key = api_key
|
961
|
+
url = 'https://api.openai.com/v1/chat/completions'
|
962
|
+
headers = {
|
963
|
+
'Content-Type' => 'application/json',
|
964
|
+
'Authorization' => 'Bearer ' + @api_key
|
965
|
+
}
|
966
|
+
data = {
|
967
|
+
'model' => 'gpt-3.5-turbo',
|
968
|
+
'messages' => [
|
969
|
+
{ "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
|
970
|
+
{ "role" => "user", "content" => pcol1 } # pcol1 직접 사용
|
971
|
+
]
|
972
|
+
}
|
973
|
+
|
974
|
+
begin
|
975
|
+
req = HTTP.headers(headers).post(url, json: data)
|
976
|
+
puts "HTTP Status: #{req.status}" # 상태 코드 확인
|
977
|
+
response = JSON.parse(req.body.to_s)
|
978
|
+
puts "API Response: #{response}" # 전체 응답 출력
|
979
|
+
|
980
|
+
if req.status == 429
|
981
|
+
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
982
|
+
end
|
983
|
+
|
984
|
+
# 응답 데이터에서 안전하게 값 추출
|
985
|
+
raw_content = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
|
986
|
+
content = raw_content.gsub(/\. /, ".\n") # 줄바꿈 추가
|
987
|
+
|
988
|
+
rescue => e
|
989
|
+
puts "Error: #{e.message}"
|
990
|
+
content = "오류가 발생했습니다."
|
991
|
+
end
|
992
|
+
else
|
993
|
+
end
|
994
|
+
|
995
|
+
reply_button = last_matched_item.find_element(:css, 'a.comment_info_button')
|
996
|
+
reply_button.click
|
997
|
+
sleep(1.5)
|
998
|
+
|
999
|
+
textarea = @driver.find_element(:css, 'textarea.comment_inbox_text')
|
1000
|
+
textarea.send_keys(content)
|
1001
|
+
sleep(1)
|
1002
|
+
|
1003
|
+
if option['이모티콘자동삽입'] == 'true'
|
1004
|
+
puts "이모티콘 자동 삽입 옵션 진행!!".cyan
|
1005
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
1006
|
+
reply_comments.each_with_index do |item, index|
|
1007
|
+
begin
|
1008
|
+
|
1009
|
+
sticker_button = item.find_element(:css, 'a.button_sticker')
|
1010
|
+
sticker_button.click
|
1011
|
+
sleep(1)
|
1012
|
+
rescue
|
1013
|
+
end
|
1014
|
+
end
|
1015
|
+
begin
|
1016
|
+
sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
|
1017
|
+
random_li = sticker_list_elements.sample
|
1018
|
+
random_button = random_li.find_element(:tag_name, 'button')
|
1019
|
+
random_button.click
|
1020
|
+
sleep(1)
|
1021
|
+
inner_buttons = random_li.find_elements(:tag_name, 'button')
|
1022
|
+
random_button_in_li = inner_buttons.sample
|
1023
|
+
sleep(1)
|
1024
|
+
random_button_in_li.click
|
1025
|
+
sleep(1)
|
1026
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError
|
1027
|
+
rescue => e
|
1028
|
+
puts "기타 오류로 인해 이모티콘 삽입 안됨"
|
1029
|
+
end
|
1030
|
+
else
|
1031
|
+
puts "이모티콘 자동 삽입 옵션이 비활성화됨."
|
1032
|
+
end
|
1033
|
+
|
1034
|
+
if option['이미지자동삽입'] == 'true'
|
1035
|
+
puts "이미지 자동 삽입 옵션 진행!!".cyan
|
1036
|
+
@image = image
|
1037
|
+
image_path = image
|
1038
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
1039
|
+
reply_comments.each_with_index do |item, index|
|
1040
|
+
begin
|
1041
|
+
|
1042
|
+
attach_button = item.find_element(:xpath, './/*[@class="button_file"]')
|
1043
|
+
attach_button.click
|
1044
|
+
sleep(1)
|
1045
|
+
rescue
|
1046
|
+
end
|
1047
|
+
end
|
1048
|
+
key_stroke('escape')
|
1049
|
+
file_input = @driver.find_element(:xpath, '//*[@title="사진첨부"]')
|
1050
|
+
file_input.send_keys(image_path)
|
1051
|
+
sleep(2)
|
1052
|
+
end
|
1053
|
+
|
1054
|
+
register_btn = @driver.find_element(:css, 'a.button.btn_register')
|
1055
|
+
register_btn.click
|
1056
|
+
sleep(2)
|
1057
|
+
|
1058
|
+
matched = true
|
1059
|
+
rescue => e
|
1060
|
+
puts "대댓글 등록 중 오류 발생: #{e.message}"
|
1061
|
+
end
|
1062
|
+
end
|
1063
|
+
|
1064
|
+
puts "닉네임 '#{target}'을 포함한 댓글을 찾지 못했습니다." unless matched
|
1065
|
+
|
1066
|
+
end
|
610
1067
|
end
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
1068
|
+
|
1069
|
+
end
|
1070
|
+
|
1071
|
+
elsif option['re_coment'] == 'false' # 대 댓글 아닐때
|
1072
|
+
if @data['포스트설정']['순서사용2'].checked?
|
1073
|
+
@content_soon ||= 0 # 초기 한 번만 0으로 세팅
|
1074
|
+
|
1075
|
+
if @data['내용설정']['내용'].nil? || @data['내용설정']['내용'].empty?
|
1076
|
+
content = ''
|
1077
|
+
else
|
1078
|
+
if @data.dig('내용설정', '랜덤사용')&.respond_to?(:checked?) && @data['내용설정']['랜덤사용'].checked?
|
1079
|
+
content = @data['내용설정']['내용'].sample[2]
|
1080
|
+
else
|
1081
|
+
content = @data['내용설정']['내용'][@content_soon][2]
|
1082
|
+
@content_soon += 1
|
1083
|
+
@content_soon = 0 if @content_soon >= @data['내용설정']['내용'].length
|
1084
|
+
end
|
1085
|
+
end
|
1086
|
+
else
|
1087
|
+
end
|
1088
|
+
|
1089
|
+
# 디엠 자동 변경이 체크된 경우 content를 변환
|
1090
|
+
if @data['포스트설정']['내용자동변경'].checked?
|
1091
|
+
change_memory = {}
|
1092
|
+
@data['포스트설정']['내용자동변경값'].each do |key, v|
|
1093
|
+
change_memory[key] = v.sample
|
1094
|
+
end
|
1095
|
+
@data['포스트설정']['내용자동변경값'].each do |key, _|
|
1096
|
+
if content.include?(key)
|
1097
|
+
content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
|
1098
|
+
else
|
1099
|
+
end
|
1100
|
+
end
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
if option['ChatGPT사용'] == 'true'
|
1104
|
+
pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
|
1105
|
+
sleep(1)
|
1106
|
+
|
1107
|
+
puts "ChatGPT로 댓글을 만드는 중입니다."
|
1108
|
+
@api_key = api_key
|
1109
|
+
url = 'https://api.openai.com/v1/chat/completions'
|
1110
|
+
headers = {
|
1111
|
+
'Content-Type' => 'application/json',
|
1112
|
+
'Authorization' => 'Bearer ' + @api_key
|
1113
|
+
}
|
1114
|
+
data = {
|
1115
|
+
'model' => 'gpt-3.5-turbo',
|
1116
|
+
'messages' => [
|
1117
|
+
{ "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
|
1118
|
+
{ "role" => "user", "content" => pcol1 } # pcol1 직접 사용
|
1119
|
+
]
|
1120
|
+
}
|
1121
|
+
|
1122
|
+
begin
|
1123
|
+
req = HTTP.headers(headers).post(url, json: data)
|
1124
|
+
puts "HTTP Status: #{req.status}" # 상태 코드 확인
|
1125
|
+
response = JSON.parse(req.body.to_s)
|
1126
|
+
puts "API Response: #{response}" # 전체 응답 출력
|
1127
|
+
|
1128
|
+
if req.status == 429
|
1129
|
+
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
1130
|
+
end
|
1131
|
+
|
1132
|
+
# 응답 데이터에서 안전하게 값 추출
|
1133
|
+
raw_content = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
|
1134
|
+
content = raw_content.gsub(/\. /, ".\n") # 줄바꿈 추가
|
1135
|
+
|
1136
|
+
rescue => e
|
1137
|
+
puts "Error: #{e.message}"
|
1138
|
+
content = "오류가 발생했습니다."
|
1139
|
+
end
|
1140
|
+
else
|
1141
|
+
end
|
1142
|
+
|
1143
|
+
wait = Selenium::WebDriver::Wait.new(timeout: 10)
|
1144
|
+
wait.until { @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]') }
|
1145
|
+
|
1146
|
+
element = @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]')
|
1147
|
+
@driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)
|
619
1148
|
sleep(1)
|
620
|
-
|
621
|
-
|
622
|
-
# 'se2_line_sticker_set' 클래스를 가진 <ul> 요소 안의 모든 <li> 요소 찾기
|
623
|
-
sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
|
624
|
-
|
625
|
-
# 16개 <li> 요소 중 랜덤으로 하나 선택하여 클릭
|
626
|
-
random_li = sticker_list_elements.sample
|
627
|
-
random_button = random_li.find_element(:tag_name, 'button') # <button> 태그 찾기
|
628
|
-
random_button.click
|
629
|
-
|
630
|
-
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
631
|
-
|
632
|
-
# 첫 번째 클릭한 <li> 내에서 버튼을 찾기
|
633
|
-
inner_buttons = random_li.find_elements(:tag_name, 'button')
|
634
|
-
|
635
|
-
# 20개 <button> 요소 중 랜덤으로 하나 선택하여 클릭
|
636
|
-
random_button_in_li = inner_buttons.sample
|
1149
|
+
|
1150
|
+
element.send_keys(content)
|
637
1151
|
sleep(1)
|
638
|
-
|
639
|
-
|
640
|
-
|
1152
|
+
|
1153
|
+
# 이모티콘 자동 삽입
|
1154
|
+
if option['이모티콘자동삽입'] == 'true'
|
1155
|
+
puts "이모티콘 자동 삽입 옵션 진행!!".cyan
|
1156
|
+
|
1157
|
+
# '이모티콘' 버튼 클릭
|
1158
|
+
@driver.find_element(:xpath, '//*[@class="button_sticker"]').click
|
1159
|
+
sleep(1)
|
1160
|
+
|
1161
|
+
begin
|
1162
|
+
# 'se2_line_sticker_set' 클래스를 가진 <ul> 요소 안의 모든 <li> 요소 찾기
|
1163
|
+
sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
|
1164
|
+
|
1165
|
+
# 16개 <li> 요소 중 랜덤으로 하나 선택하여 클릭
|
1166
|
+
random_li = sticker_list_elements.sample
|
1167
|
+
random_button = random_li.find_element(:tag_name, 'button') # <button> 태그 찾기
|
1168
|
+
random_button.click
|
1169
|
+
|
1170
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
1171
|
+
|
1172
|
+
# 첫 번째 클릭한 <li> 내에서 버튼을 찾기
|
1173
|
+
inner_buttons = random_li.find_elements(:tag_name, 'button')
|
1174
|
+
|
1175
|
+
# 20개 <button> 요소 중 랜덤으로 하나 선택하여 클릭
|
1176
|
+
random_button_in_li = inner_buttons.sample
|
1177
|
+
sleep(1)
|
1178
|
+
random_button_in_li.click
|
1179
|
+
|
1180
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
1181
|
+
|
1182
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError => e
|
1183
|
+
#puts "Stale element reference 오류 발생, 계속 진행: #{e.message}".yellow
|
1184
|
+
# 오류 발생 시에도 계속 진행하려면 작업을 계속하도록 처리
|
1185
|
+
# 예를 들어, continue, or next 등으로 다음 단계로 넘어갈 수 있습니다.
|
1186
|
+
|
1187
|
+
rescue => e
|
1188
|
+
puts "기타 오류로 인해 이모티콘 삽입 안됨"
|
1189
|
+
# 기타 오류 처리
|
1190
|
+
# 여기에 추가적인 예외 처리 로직을 넣을 수 있습니다.
|
1191
|
+
end
|
1192
|
+
else
|
1193
|
+
puts "이모티콘 자동 삽입 옵션이 비활성화됨."
|
1194
|
+
end
|
1195
|
+
|
1196
|
+
# 이미지 자동 삽입
|
1197
|
+
if option['이미지자동삽입'] == 'true'
|
1198
|
+
puts "이미지 자동 상입 옵션 진행!!".cyan
|
1199
|
+
|
1200
|
+
# 아이프레임 요소가 나타날 때까지 기다립니다.
|
1201
|
+
@image = image
|
1202
|
+
image_path = image
|
641
1203
|
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
1204
|
+
@driver.find_element(:xpath, '//*[@for="attach2"]').click
|
1205
|
+
sleep(1)
|
1206
|
+
key_stroke('escape')
|
1207
|
+
# 파일 경로 자동 입력
|
1208
|
+
file_input = @driver.find_element(:xpath, '//*[@class="button_file"]')
|
1209
|
+
|
1210
|
+
# send_keys로 파일 경로를 입력하여 이미지 업로드
|
1211
|
+
file_input.send_keys(image_path)
|
1212
|
+
sleep(2)
|
646
1213
|
|
647
|
-
|
648
|
-
puts "기타 오류로 인해 이모티콘 삽입 안됨"
|
649
|
-
# 기타 오류 처리
|
650
|
-
# 여기에 추가적인 예외 처리 로직을 넣을 수 있습니다.
|
1214
|
+
else
|
651
1215
|
end
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
puts "이미지 자동 상입 옵션 진행!!".cyan
|
659
|
-
|
660
|
-
# 아이프레임 요소가 나타날 때까지 기다립니다.
|
661
|
-
@image = image
|
662
|
-
image_path = image
|
663
|
-
|
664
|
-
@driver.find_element(:xpath, '//*[@for="attach2"]').click
|
665
|
-
sleep(1)
|
666
|
-
key_stroke('escape')
|
667
|
-
# 파일 경로 자동 입력
|
668
|
-
file_input = @driver.find_element(:xpath, '//*[@id="attach2"]')
|
669
|
-
|
670
|
-
# send_keys로 파일 경로를 입력하여 이미지 업로드
|
671
|
-
file_input.send_keys(image_path)
|
672
|
-
sleep(2)
|
673
|
-
|
674
|
-
else
|
1216
|
+
|
1217
|
+
|
1218
|
+
wait.until { @driver.find_element(:xpath, '//*[@class="button btn_register is_active"]') }
|
1219
|
+
@driver.find_element(:xpath, '//*[@class="button btn_register is_active"]').click
|
1220
|
+
puts "#{board_url} [댓글 작성 완료 !!]".cyan
|
1221
|
+
sleep(2)
|
675
1222
|
end
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
puts "#{board_url} [댓글 작성 완료 !!]".cyan
|
680
|
-
|
681
|
-
sleep(2)
|
1223
|
+
|
1224
|
+
|
1225
|
+
|
682
1226
|
begin
|
683
1227
|
@driver.switch_to.alert
|
684
1228
|
sleep(1)
|
@@ -720,7 +1264,7 @@ class Naver
|
|
720
1264
|
puts '-[√] 로그 파일 생성 완료.......'.yellow
|
721
1265
|
end
|
722
1266
|
end
|
723
|
-
|
1267
|
+
|
724
1268
|
@driver.switch_to.default_content() # 아이프레임 해제
|
725
1269
|
def sleep_with_progress(sleep_delay)
|
726
1270
|
print "[설정 딜레이 진행 중] "
|
@@ -739,175 +1283,713 @@ class Naver
|
|
739
1283
|
rescue => e
|
740
1284
|
puts "Error: #{e.message}"
|
741
1285
|
end
|
742
|
-
|
1286
|
+
end
|
743
1287
|
else
|
744
1288
|
end
|
745
1289
|
|
746
1290
|
################################################################################ 설정게시글사용 ################################################################################
|
747
1291
|
|
748
1292
|
if option['설정게시글사용'] == 'true'
|
749
|
-
|
1293
|
+
puts "게시판 list 기반으로 댓글 작업 옵션 진행!!".cyan
|
750
1294
|
|
751
1295
|
@driver.get(board_url) # 해당 URL로 이동
|
752
1296
|
begin
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
1297
|
+
# 아이프레임 요소가 나타날 때까지 기다립니다.
|
1298
|
+
wait = Selenium::WebDriver::Wait.new(:timeout => 20) # 아이프레임 선택
|
1299
|
+
wait.until { @driver.find_element(:xpath, '//*[@id="cafe_main"]') } # 아이프레임 선택
|
1300
|
+
sleep(1)
|
1301
|
+
@driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="cafe_main"]')) # 아이프레임 선택
|
758
1302
|
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
1303
|
+
|
1304
|
+
if option['좋아요'] == 'true'
|
1305
|
+
puts "좋아요 클릭 옵션 진행!!".cyan
|
1306
|
+
wait = Selenium::WebDriver::Wait.new(:timeout => 10)
|
1307
|
+
wait.until { @driver.find_element(:xpath, '//*[@class="u_ico _icon"]') }
|
1308
|
+
|
1309
|
+
# 댓글 입력
|
1310
|
+
element = @driver.find_element(:xpath, '//*[@class="u_ico _icon"]')
|
1311
|
+
@driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
|
1312
|
+
sleep(1)
|
1313
|
+
|
1314
|
+
# 좋아요 버튼을 찾기
|
1315
|
+
like_button = @driver.find_element(:xpath, '//div[@class="ReactionLikeIt u_likeit_list_module _cafeReactionModule"]//a[@role="button"]')
|
1316
|
+
|
1317
|
+
# aria-pressed 속성 값 확인
|
1318
|
+
aria_pressed = like_button.attribute('aria-pressed')
|
1319
|
+
|
1320
|
+
if aria_pressed == 'true'
|
1321
|
+
# 이미 좋아요를 누른 상태일 경우
|
1322
|
+
|
767
1323
|
else
|
768
|
-
|
769
|
-
|
770
|
-
|
1324
|
+
# 좋아요를 아직 누르지 않은 상태일 경우 클릭
|
1325
|
+
@driver.find_element(:xpath, '//*[@class="u_ico _icon"]').click
|
1326
|
+
sleep(2)
|
771
1327
|
end
|
1328
|
+
else
|
1329
|
+
end
|
1330
|
+
|
1331
|
+
|
1332
|
+
|
1333
|
+
if option['re_coment'] == 'true' # 대 댓글 작업때
|
1334
|
+
if @data['포스트설정']['전체대댓글'].checked?
|
1335
|
+
begin
|
1336
|
+
comment_items = @driver.find_elements(:css, 'li.CommentItem')
|
1337
|
+
original_comments = comment_items.select { |item| !item.attribute('class').include?('CommentItem--reply') }
|
1338
|
+
|
1339
|
+
original_comments.each_with_index do |item, index|
|
1340
|
+
|
1341
|
+
begin
|
1342
|
+
|
1343
|
+
if @data['포스트설정']['순서사용2'].checked?
|
1344
|
+
@content_soon ||= 0 # 초기 한 번만 0으로 세팅
|
1345
|
+
|
1346
|
+
if @data['내용설정']['내용'].nil? || @data['내용설정']['내용'].empty?
|
1347
|
+
content = ''
|
1348
|
+
else
|
1349
|
+
if @data.dig('내용설정', '랜덤사용')&.respond_to?(:checked?) && @data['내용설정']['랜덤사용'].checked?
|
1350
|
+
content = @data['내용설정']['내용'].sample[2]
|
1351
|
+
else
|
1352
|
+
content = @data['내용설정']['내용'][@content_soon][2]
|
1353
|
+
@content_soon += 1
|
1354
|
+
@content_soon = 0 if @content_soon >= @data['내용설정']['내용'].length
|
1355
|
+
end
|
1356
|
+
end
|
1357
|
+
else
|
1358
|
+
end
|
1359
|
+
|
1360
|
+
# 디엠 자동 변경이 체크된 경우 content를 변환
|
1361
|
+
if @data['포스트설정']['내용자동변경'].checked?
|
1362
|
+
change_memory = {}
|
1363
|
+
@data['포스트설정']['내용자동변경값'].each do |key, v|
|
1364
|
+
change_memory[key] = v.sample
|
1365
|
+
end
|
1366
|
+
@data['포스트설정']['내용자동변경값'].each do |key, _|
|
1367
|
+
if content.include?(key)
|
1368
|
+
content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
|
1369
|
+
else
|
1370
|
+
end
|
1371
|
+
end
|
1372
|
+
end
|
1373
|
+
|
1374
|
+
if option['ChatGPT사용'] == 'true'
|
1375
|
+
pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
|
1376
|
+
sleep(1)
|
1377
|
+
|
1378
|
+
puts "ChatGPT로 댓글을 만드는 중입니다."
|
1379
|
+
@api_key = api_key
|
1380
|
+
url = 'https://api.openai.com/v1/chat/completions'
|
1381
|
+
headers = {
|
1382
|
+
'Content-Type' => 'application/json',
|
1383
|
+
'Authorization' => 'Bearer ' + @api_key
|
1384
|
+
}
|
1385
|
+
data = {
|
1386
|
+
'model' => 'gpt-3.5-turbo',
|
1387
|
+
'messages' => [
|
1388
|
+
{ "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
|
1389
|
+
{ "role" => "user", "content" => pcol1 } # pcol1 직접 사용
|
1390
|
+
]
|
1391
|
+
}
|
1392
|
+
|
1393
|
+
begin
|
1394
|
+
req = HTTP.headers(headers).post(url, json: data)
|
1395
|
+
puts "HTTP Status: #{req.status}" # 상태 코드 확인
|
1396
|
+
response = JSON.parse(req.body.to_s)
|
1397
|
+
puts "API Response: #{response}" # 전체 응답 출력
|
1398
|
+
|
1399
|
+
if req.status == 429
|
1400
|
+
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
1401
|
+
end
|
1402
|
+
|
1403
|
+
# 응답 데이터에서 안전하게 값 추출
|
1404
|
+
raw_content = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
|
1405
|
+
content = raw_content.gsub(/\. /, ".\n") # 줄바꿈 추가
|
1406
|
+
|
1407
|
+
rescue => e
|
1408
|
+
puts "Error: #{e.message}"
|
1409
|
+
content = "오류가 발생했습니다."
|
1410
|
+
end
|
1411
|
+
else
|
1412
|
+
end
|
1413
|
+
|
1414
|
+
reply_button = item.find_element(:css, 'a.comment_info_button')
|
1415
|
+
puts "대댓글 #{index + 1} 작성 중..."
|
1416
|
+
reply_button.click
|
1417
|
+
sleep(1.5)
|
1418
|
+
|
1419
|
+
textarea = @driver.find_element(:css, 'textarea.comment_inbox_text')
|
1420
|
+
textarea.send_keys(content)
|
1421
|
+
sleep(1)
|
1422
|
+
|
1423
|
+
if option['이모티콘자동삽입'] == 'true'
|
1424
|
+
puts "이모티콘 자동 삽입 옵션 진행!!".cyan
|
1425
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
1426
|
+
reply_comments.each_with_index do |item, index|
|
1427
|
+
begin
|
1428
|
+
|
1429
|
+
|
1430
|
+
# 해당 대댓글 내부의 이모티콘 버튼 찾기
|
1431
|
+
sticker_button = item.find_element(:css, 'a.button_sticker')
|
1432
|
+
sticker_button.click
|
1433
|
+
sleep(1)
|
1434
|
+
|
1435
|
+
rescue
|
1436
|
+
end
|
1437
|
+
end
|
1438
|
+
begin
|
1439
|
+
# 'se2_line_sticker_set' 클래스를 가진 <ul> 요소 안의 모든 <li> 요소 찾기
|
1440
|
+
sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
|
1441
|
+
|
1442
|
+
# 16개 <li> 요소 중 랜덤으로 하나 선택하여 클릭
|
1443
|
+
random_li = sticker_list_elements.sample
|
1444
|
+
random_button = random_li.find_element(:tag_name, 'button') # <button> 태그 찾기
|
1445
|
+
random_button.click
|
1446
|
+
|
1447
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
1448
|
+
|
1449
|
+
# 첫 번째 클릭한 <li> 내에서 버튼을 찾기
|
1450
|
+
inner_buttons = random_li.find_elements(:tag_name, 'button')
|
1451
|
+
|
1452
|
+
# 20개 <button> 요소 중 랜덤으로 하나 선택하여 클릭
|
1453
|
+
random_button_in_li = inner_buttons.sample
|
1454
|
+
sleep(1)
|
1455
|
+
random_button_in_li.click
|
1456
|
+
|
1457
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
1458
|
+
|
1459
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError => e
|
1460
|
+
#puts "Stale element reference 오류 발생, 계속 진행: #{e.message}".yellow
|
1461
|
+
# 오류 발생 시에도 계속 진행하려면 작업을 계속하도록 처리
|
1462
|
+
# 예를 들어, continue, or next 등으로 다음 단계로 넘어갈 수 있습니다.
|
1463
|
+
|
1464
|
+
rescue => e
|
1465
|
+
puts "기타 오류로 인해 이모티콘 삽입 안됨"
|
1466
|
+
# 기타 오류 처리
|
1467
|
+
# 여기에 추가적인 예외 처리 로직을 넣을 수 있습니다.
|
1468
|
+
end
|
1469
|
+
else
|
1470
|
+
puts "이모티콘 자동 삽입 옵션이 비활성화됨."
|
1471
|
+
end
|
1472
|
+
|
1473
|
+
# 이미지 자동 삽입
|
1474
|
+
if option['이미지자동삽입'] == 'true'
|
1475
|
+
puts "이미지 자동 상입 옵션 진행!!".cyan
|
1476
|
+
|
1477
|
+
# 아이프레임 요소가 나타날 때까지 기다립니다.
|
1478
|
+
@image = image
|
1479
|
+
image_path = image
|
1480
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
1481
|
+
|
1482
|
+
reply_comments.each_with_index do |item, index|
|
1483
|
+
begin
|
1484
|
+
|
1485
|
+
|
1486
|
+
# 해당 대댓글 내부에서 for="attach2"인 라벨 클릭
|
1487
|
+
attach_button = item.find_element(:xpath, './/*[@class="button_file"]')
|
1488
|
+
attach_button.click
|
1489
|
+
sleep(1)
|
1490
|
+
|
1491
|
+
rescue
|
1492
|
+
end
|
1493
|
+
end
|
1494
|
+
key_stroke('escape')
|
1495
|
+
# 파일 경로 자동 입력
|
1496
|
+
file_input = @driver.find_element(:xpath, '//*[@title="사진첨부"]')
|
1497
|
+
|
1498
|
+
# send_keys로 파일 경로를 입력하여 이미지 업로드
|
1499
|
+
file_input.send_keys(image_path)
|
1500
|
+
sleep(2)
|
1501
|
+
|
1502
|
+
else
|
1503
|
+
end
|
1504
|
+
|
1505
|
+
register_btn = @driver.find_element(:css, 'a.button.btn_register')
|
1506
|
+
register_btn.click
|
1507
|
+
sleep(2)
|
1508
|
+
|
1509
|
+
rescue => e
|
1510
|
+
puts "대댓글 #{index + 1} 처리 중 오류 발생: #{e.message}"
|
1511
|
+
next
|
1512
|
+
end
|
1513
|
+
end
|
1514
|
+
rescue => e
|
1515
|
+
puts "전체대댓글 처리 중 예외 발생: #{e.message}"
|
772
1516
|
end
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
1517
|
+
|
1518
|
+
elsif @data['포스트설정']['지정대댓글'].checked?
|
1519
|
+
targets = @data['포스트설정']['nik_or_number'].text.to_s.force_encoding('utf-8').split(',').map(&:strip)
|
1520
|
+
targets.each do |target|
|
1521
|
+
if target.match?(/^\d+$/)
|
1522
|
+
index = target.to_i - 1
|
1523
|
+
comment_items = @driver.find_elements(:css, 'li.CommentItem')
|
1524
|
+
original_comments = comment_items.select { |item| !item.attribute('class').include?('CommentItem--reply') }
|
1525
|
+
|
1526
|
+
if original_comments[index]
|
1527
|
+
begin
|
1528
|
+
|
1529
|
+
if @data['포스트설정']['순서사용2'].checked?
|
1530
|
+
@content_soon ||= 0 # 초기 한 번만 0으로 세팅
|
1531
|
+
|
1532
|
+
if @data['내용설정']['내용'].nil? || @data['내용설정']['내용'].empty?
|
1533
|
+
content = ''
|
1534
|
+
else
|
1535
|
+
if @data.dig('내용설정', '랜덤사용')&.respond_to?(:checked?) && @data['내용설정']['랜덤사용'].checked?
|
1536
|
+
content = @data['내용설정']['내용'].sample[2]
|
1537
|
+
else
|
1538
|
+
content = @data['내용설정']['내용'][@content_soon][2]
|
1539
|
+
@content_soon += 1
|
1540
|
+
@content_soon = 0 if @content_soon >= @data['내용설정']['내용'].length
|
1541
|
+
end
|
1542
|
+
end
|
1543
|
+
else
|
1544
|
+
end
|
1545
|
+
|
1546
|
+
# 디엠 자동 변경이 체크된 경우 content를 변환
|
1547
|
+
if @data['포스트설정']['내용자동변경'].checked?
|
1548
|
+
change_memory = {}
|
1549
|
+
@data['포스트설정']['내용자동변경값'].each do |key, v|
|
1550
|
+
change_memory[key] = v.sample
|
1551
|
+
end
|
1552
|
+
@data['포스트설정']['내용자동변경값'].each do |key, _|
|
1553
|
+
if content.include?(key)
|
1554
|
+
content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
|
1555
|
+
else
|
1556
|
+
end
|
1557
|
+
end
|
1558
|
+
end
|
1559
|
+
|
1560
|
+
if option['ChatGPT사용'] == 'true'
|
1561
|
+
pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
|
1562
|
+
sleep(1)
|
1563
|
+
|
1564
|
+
puts "ChatGPT로 댓글을 만드는 중입니다."
|
1565
|
+
@api_key = api_key
|
1566
|
+
url = 'https://api.openai.com/v1/chat/completions'
|
1567
|
+
headers = {
|
1568
|
+
'Content-Type' => 'application/json',
|
1569
|
+
'Authorization' => 'Bearer ' + @api_key
|
1570
|
+
}
|
1571
|
+
data = {
|
1572
|
+
'model' => 'gpt-3.5-turbo',
|
1573
|
+
'messages' => [
|
1574
|
+
{ "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
|
1575
|
+
{ "role" => "user", "content" => pcol1 } # pcol1 직접 사용
|
1576
|
+
]
|
1577
|
+
}
|
1578
|
+
|
1579
|
+
begin
|
1580
|
+
req = HTTP.headers(headers).post(url, json: data)
|
1581
|
+
puts "HTTP Status: #{req.status}" # 상태 코드 확인
|
1582
|
+
response = JSON.parse(req.body.to_s)
|
1583
|
+
puts "API Response: #{response}" # 전체 응답 출력
|
1584
|
+
|
1585
|
+
if req.status == 429
|
1586
|
+
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
1587
|
+
end
|
1588
|
+
|
1589
|
+
# 응답 데이터에서 안전하게 값 추출
|
1590
|
+
raw_content = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
|
1591
|
+
content = raw_content.gsub(/\. /, ".\n") # 줄바꿈 추가
|
1592
|
+
|
1593
|
+
rescue => e
|
1594
|
+
puts "Error: #{e.message}"
|
1595
|
+
content = "오류가 발생했습니다."
|
1596
|
+
end
|
1597
|
+
else
|
1598
|
+
end
|
1599
|
+
|
1600
|
+
puts "#{index + 1}번째 댓글에 대댓글 작성 시작"
|
1601
|
+
reply_button = original_comments[index].find_element(:css, 'a.comment_info_button')
|
1602
|
+
reply_button.click
|
1603
|
+
sleep(1.5)
|
1604
|
+
|
1605
|
+
textarea = @driver.find_element(:css, 'textarea.comment_inbox_text')
|
1606
|
+
textarea.send_keys(content)
|
1607
|
+
sleep(1)
|
1608
|
+
|
1609
|
+
if option['이모티콘자동삽입'] == 'true'
|
1610
|
+
puts "이모티콘 자동 삽입 옵션 진행!!".cyan
|
1611
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
1612
|
+
reply_comments.each_with_index do |item, index|
|
1613
|
+
begin
|
1614
|
+
|
1615
|
+
|
1616
|
+
# 해당 대댓글 내부의 이모티콘 버튼 찾기
|
1617
|
+
sticker_button = item.find_element(:css, 'a.button_sticker')
|
1618
|
+
sticker_button.click
|
1619
|
+
sleep(1)
|
1620
|
+
|
1621
|
+
rescue
|
1622
|
+
end
|
1623
|
+
end
|
1624
|
+
|
1625
|
+
begin
|
1626
|
+
# 'se2_line_sticker_set' 클래스를 가진 <ul> 요소 안의 모든 <li> 요소 찾기
|
1627
|
+
sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
|
1628
|
+
|
1629
|
+
# 16개 <li> 요소 중 랜덤으로 하나 선택하여 클릭
|
1630
|
+
random_li = sticker_list_elements.sample
|
1631
|
+
random_button = random_li.find_element(:tag_name, 'button') # <button> 태그 찾기
|
1632
|
+
random_button.click
|
1633
|
+
|
1634
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
1635
|
+
|
1636
|
+
# 첫 번째 클릭한 <li> 내에서 버튼을 찾기
|
1637
|
+
inner_buttons = random_li.find_elements(:tag_name, 'button')
|
1638
|
+
|
1639
|
+
# 20개 <button> 요소 중 랜덤으로 하나 선택하여 클릭
|
1640
|
+
random_button_in_li = inner_buttons.sample
|
1641
|
+
sleep(1)
|
1642
|
+
random_button_in_li.click
|
1643
|
+
|
1644
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
1645
|
+
|
1646
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError => e
|
1647
|
+
#puts "Stale element reference 오류 발생, 계속 진행: #{e.message}".yellow
|
1648
|
+
# 오류 발생 시에도 계속 진행하려면 작업을 계속하도록 처리
|
1649
|
+
# 예를 들어, continue, or next 등으로 다음 단계로 넘어갈 수 있습니다.
|
1650
|
+
|
1651
|
+
rescue => e
|
1652
|
+
puts "기타 오류로 인해 이모티콘 삽입 안됨"
|
1653
|
+
# 기타 오류 처리
|
1654
|
+
# 여기에 추가적인 예외 처리 로직을 넣을 수 있습니다.
|
1655
|
+
end
|
1656
|
+
else
|
1657
|
+
puts "이모티콘 자동 삽입 옵션이 비활성화됨."
|
1658
|
+
end
|
1659
|
+
|
1660
|
+
# 이미지 자동 삽입
|
1661
|
+
if option['이미지자동삽입'] == 'true'
|
1662
|
+
puts "이미지 자동 상입 옵션 진행!!".cyan
|
1663
|
+
|
1664
|
+
# 아이프레임 요소가 나타날 때까지 기다립니다.
|
1665
|
+
@image = image
|
1666
|
+
image_path = image
|
1667
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
1668
|
+
|
1669
|
+
reply_comments.each_with_index do |item, index|
|
1670
|
+
begin
|
1671
|
+
|
1672
|
+
|
1673
|
+
# 해당 대댓글 내부에서 for="attach2"인 라벨 클릭
|
1674
|
+
attach_button = item.find_element(:xpath, './/*[@class="button_file"]')
|
1675
|
+
attach_button.click
|
1676
|
+
sleep(1)
|
1677
|
+
|
1678
|
+
rescue
|
1679
|
+
end
|
1680
|
+
end
|
1681
|
+
key_stroke('escape')
|
1682
|
+
# 파일 경로 자동 입력
|
1683
|
+
file_input = @driver.find_element(:xpath, '//*[@title="사진첨부"]')
|
1684
|
+
|
1685
|
+
# send_keys로 파일 경로를 입력하여 이미지 업로드
|
1686
|
+
file_input.send_keys(image_path)
|
1687
|
+
sleep(2)
|
1688
|
+
|
1689
|
+
else
|
1690
|
+
end
|
1691
|
+
|
1692
|
+
register_btn = @driver.find_element(:css, 'a.button.btn_register')
|
1693
|
+
register_btn.click
|
1694
|
+
sleep(2)
|
1695
|
+
|
1696
|
+
puts "#{index + 1}번째 댓글에 대댓글 작성 완료"
|
1697
|
+
rescue => e
|
1698
|
+
puts "댓글 인덱스 #{index + 1} 처리 중 오류 발생: #{e.message}"
|
1699
|
+
end
|
1700
|
+
else
|
1701
|
+
puts "해당 인덱스(#{index + 1})의 답글쓰기 버튼이 없습니다."
|
1702
|
+
end
|
1703
|
+
|
1704
|
+
else # 닉네임으로 찾기
|
1705
|
+
comment_items = @driver.find_elements(:css, 'li.CommentItem')
|
1706
|
+
original_comments = comment_items.select { |item| !item.attribute('class').include?('CommentItem--reply') }
|
1707
|
+
|
1708
|
+
matched = false
|
1709
|
+
last_matched_item = nil # 마지막에 닉네임이 일치한 댓글 저장
|
1710
|
+
|
1711
|
+
original_comments.each_with_index do |item, idx|
|
1712
|
+
begin
|
1713
|
+
nickname_element = item.find_element(:css, 'a.comment_nickname')
|
1714
|
+
nickname = nickname_element.text.strip
|
1715
|
+
|
1716
|
+
if nickname.include?(target)
|
1717
|
+
puts "#{target} 닉네임이 포함된 댓글 발견 (#{idx + 1}번째)"
|
1718
|
+
last_matched_item = item # 매번 갱신 → 마지막에 발견된 걸 저장
|
1719
|
+
end
|
1720
|
+
rescue => e
|
1721
|
+
puts "닉네임 검사 중 오류 발생: #{e.message}"
|
1722
|
+
next
|
1723
|
+
end
|
1724
|
+
end
|
1725
|
+
|
1726
|
+
# 루프 끝난 뒤 마지막 댓글에만 작업 실행
|
1727
|
+
if last_matched_item
|
1728
|
+
begin
|
1729
|
+
|
1730
|
+
if @data['포스트설정']['순서사용2'].checked?
|
1731
|
+
@content_soon ||= 0 # 초기 한 번만 0으로 세팅
|
1732
|
+
|
1733
|
+
if @data['내용설정']['내용'].nil? || @data['내용설정']['내용'].empty?
|
1734
|
+
content = ''
|
1735
|
+
else
|
1736
|
+
if @data.dig('내용설정', '랜덤사용')&.respond_to?(:checked?) && @data['내용설정']['랜덤사용'].checked?
|
1737
|
+
content = @data['내용설정']['내용'].sample[2]
|
1738
|
+
else
|
1739
|
+
content = @data['내용설정']['내용'][@content_soon][2]
|
1740
|
+
@content_soon += 1
|
1741
|
+
@content_soon = 0 if @content_soon >= @data['내용설정']['내용'].length
|
1742
|
+
end
|
1743
|
+
end
|
1744
|
+
else
|
1745
|
+
end
|
1746
|
+
|
1747
|
+
# 디엠 자동 변경이 체크된 경우 content를 변환
|
1748
|
+
if @data['포스트설정']['내용자동변경'].checked?
|
1749
|
+
change_memory = {}
|
1750
|
+
@data['포스트설정']['내용자동변경값'].each do |key, v|
|
1751
|
+
change_memory[key] = v.sample
|
1752
|
+
end
|
1753
|
+
@data['포스트설정']['내용자동변경값'].each do |key, _|
|
1754
|
+
if content.include?(key)
|
1755
|
+
content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
|
1756
|
+
else
|
1757
|
+
end
|
1758
|
+
end
|
1759
|
+
end
|
1760
|
+
|
1761
|
+
if option['ChatGPT사용'] == 'true'
|
1762
|
+
pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
|
1763
|
+
sleep(1)
|
1764
|
+
|
1765
|
+
puts "ChatGPT로 댓글을 만드는 중입니다."
|
1766
|
+
@api_key = api_key
|
1767
|
+
url = 'https://api.openai.com/v1/chat/completions'
|
1768
|
+
headers = {
|
1769
|
+
'Content-Type' => 'application/json',
|
1770
|
+
'Authorization' => 'Bearer ' + @api_key
|
1771
|
+
}
|
1772
|
+
data = {
|
1773
|
+
'model' => 'gpt-3.5-turbo',
|
1774
|
+
'messages' => [
|
1775
|
+
{ "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
|
1776
|
+
{ "role" => "user", "content" => pcol1 } # pcol1 직접 사용
|
1777
|
+
]
|
1778
|
+
}
|
1779
|
+
|
1780
|
+
begin
|
1781
|
+
req = HTTP.headers(headers).post(url, json: data)
|
1782
|
+
puts "HTTP Status: #{req.status}" # 상태 코드 확인
|
1783
|
+
response = JSON.parse(req.body.to_s)
|
1784
|
+
puts "API Response: #{response}" # 전체 응답 출력
|
1785
|
+
|
1786
|
+
if req.status == 429
|
1787
|
+
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
1788
|
+
end
|
1789
|
+
|
1790
|
+
# 응답 데이터에서 안전하게 값 추출
|
1791
|
+
raw_content = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
|
1792
|
+
content = raw_content.gsub(/\. /, ".\n") # 줄바꿈 추가
|
1793
|
+
|
1794
|
+
rescue => e
|
1795
|
+
puts "Error: #{e.message}"
|
1796
|
+
content = "오류가 발생했습니다."
|
1797
|
+
end
|
1798
|
+
else
|
1799
|
+
end
|
1800
|
+
|
1801
|
+
reply_button = last_matched_item.find_element(:css, 'a.comment_info_button')
|
1802
|
+
reply_button.click
|
1803
|
+
sleep(1.5)
|
1804
|
+
|
1805
|
+
textarea = @driver.find_element(:css, 'textarea.comment_inbox_text')
|
1806
|
+
textarea.send_keys(content)
|
1807
|
+
sleep(1)
|
1808
|
+
|
1809
|
+
if option['이모티콘자동삽입'] == 'true'
|
1810
|
+
puts "이모티콘 자동 삽입 옵션 진행!!".cyan
|
1811
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
1812
|
+
reply_comments.each_with_index do |item, index|
|
1813
|
+
begin
|
1814
|
+
|
1815
|
+
sticker_button = item.find_element(:css, 'a.button_sticker')
|
1816
|
+
sticker_button.click
|
1817
|
+
sleep(1)
|
1818
|
+
rescue
|
1819
|
+
end
|
1820
|
+
end
|
1821
|
+
begin
|
1822
|
+
sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
|
1823
|
+
random_li = sticker_list_elements.sample
|
1824
|
+
random_button = random_li.find_element(:tag_name, 'button')
|
1825
|
+
random_button.click
|
1826
|
+
sleep(1)
|
1827
|
+
inner_buttons = random_li.find_elements(:tag_name, 'button')
|
1828
|
+
random_button_in_li = inner_buttons.sample
|
1829
|
+
sleep(1)
|
1830
|
+
random_button_in_li.click
|
1831
|
+
sleep(1)
|
1832
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError
|
1833
|
+
rescue => e
|
1834
|
+
puts "기타 오류로 인해 이모티콘 삽입 안됨"
|
1835
|
+
end
|
1836
|
+
else
|
1837
|
+
puts "이모티콘 자동 삽입 옵션이 비활성화됨."
|
1838
|
+
end
|
1839
|
+
|
1840
|
+
if option['이미지자동삽입'] == 'true'
|
1841
|
+
puts "이미지 자동 삽입 옵션 진행!!".cyan
|
1842
|
+
@image = image
|
1843
|
+
image_path = image
|
1844
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
1845
|
+
reply_comments.each_with_index do |item, index|
|
1846
|
+
begin
|
1847
|
+
|
1848
|
+
attach_button = item.find_element(:xpath, './/*[@class="button_file"]')
|
1849
|
+
attach_button.click
|
1850
|
+
sleep(1)
|
1851
|
+
rescue
|
1852
|
+
end
|
1853
|
+
end
|
1854
|
+
key_stroke('escape')
|
1855
|
+
file_input = @driver.find_element(:xpath, '//*[@title="사진첨부"]')
|
1856
|
+
file_input.send_keys(image_path)
|
1857
|
+
sleep(2)
|
1858
|
+
end
|
1859
|
+
|
1860
|
+
register_btn = @driver.find_element(:css, 'a.button.btn_register')
|
1861
|
+
register_btn.click
|
1862
|
+
sleep(2)
|
1863
|
+
|
1864
|
+
matched = true
|
1865
|
+
rescue => e
|
1866
|
+
puts "대댓글 등록 중 오류 발생: #{e.message}"
|
1867
|
+
end
|
1868
|
+
end
|
1869
|
+
|
1870
|
+
puts "닉네임 '#{target}'을 포함한 댓글을 찾지 못했습니다." unless matched
|
1871
|
+
|
786
1872
|
end
|
787
1873
|
end
|
788
|
-
end
|
789
1874
|
|
1875
|
+
end
|
790
1876
|
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
1877
|
+
elsif option['re_coment'] == 'false' # 대 댓글 아닐때
|
1878
|
+
if @data['포스트설정']['순서사용2'].checked?
|
1879
|
+
@content_soon ||= 0 # 초기 한 번만 0으로 세팅
|
1880
|
+
|
1881
|
+
if @data['내용설정']['내용'].nil? || @data['내용설정']['내용'].empty?
|
1882
|
+
content = ''
|
1883
|
+
else
|
1884
|
+
if @data.dig('내용설정', '랜덤사용')&.respond_to?(:checked?) && @data['내용설정']['랜덤사용'].checked?
|
1885
|
+
content = @data['내용설정']['내용'].sample[2]
|
1886
|
+
else
|
1887
|
+
content = @data['내용설정']['내용'][@content_soon][2]
|
1888
|
+
@content_soon += 1
|
1889
|
+
@content_soon = 0 if @content_soon >= @data['내용설정']['내용'].length
|
1890
|
+
end
|
1891
|
+
end
|
1892
|
+
else
|
1893
|
+
end
|
1894
|
+
|
1895
|
+
# 디엠 자동 변경이 체크된 경우 content를 변환
|
1896
|
+
if @data['포스트설정']['내용자동변경'].checked?
|
1897
|
+
change_memory = {}
|
1898
|
+
@data['포스트설정']['내용자동변경값'].each do |key, v|
|
1899
|
+
change_memory[key] = v.sample
|
1900
|
+
end
|
1901
|
+
@data['포스트설정']['내용자동변경값'].each do |key, _|
|
1902
|
+
if content.include?(key)
|
1903
|
+
content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
|
1904
|
+
else
|
1905
|
+
end
|
1906
|
+
end
|
1907
|
+
end
|
1908
|
+
|
1909
|
+
if option['ChatGPT사용'] == 'true'
|
1910
|
+
pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
|
1911
|
+
sleep(1)
|
1912
|
+
|
1913
|
+
puts "ChatGPT로 댓글을 만드는 중입니다."
|
1914
|
+
@api_key = api_key
|
1915
|
+
url = 'https://api.openai.com/v1/chat/completions'
|
1916
|
+
headers = {
|
1917
|
+
'Content-Type' => 'application/json',
|
1918
|
+
'Authorization' => 'Bearer ' + @api_key
|
1919
|
+
}
|
1920
|
+
data = {
|
1921
|
+
'model' => 'gpt-3.5-turbo',
|
1922
|
+
'messages' => [
|
1923
|
+
{ "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
|
1924
|
+
{ "role" => "user", "content" => pcol1 } # pcol1 직접 사용
|
1925
|
+
]
|
1926
|
+
}
|
1927
|
+
|
1928
|
+
begin
|
1929
|
+
req = HTTP.headers(headers).post(url, json: data)
|
1930
|
+
puts "HTTP Status: #{req.status}" # 상태 코드 확인
|
1931
|
+
response = JSON.parse(req.body.to_s)
|
1932
|
+
puts "API Response: #{response}" # 전체 응답 출력
|
1933
|
+
|
1934
|
+
if req.status == 429
|
1935
|
+
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
1936
|
+
end
|
1937
|
+
|
1938
|
+
# 응답 데이터에서 안전하게 값 추출
|
1939
|
+
raw_content = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
|
1940
|
+
content = raw_content.gsub(/\. /, ".\n") # 줄바꿈 추가
|
1941
|
+
|
1942
|
+
rescue => e
|
1943
|
+
puts "Error: #{e.message}"
|
1944
|
+
content = "오류가 발생했습니다."
|
1945
|
+
end
|
810
1946
|
else
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
end
|
815
|
-
else
|
816
|
-
end
|
817
|
-
|
818
|
-
|
819
|
-
begin
|
820
|
-
wait = Selenium::WebDriver::Wait.new(:timeout => 10)
|
1947
|
+
end
|
1948
|
+
|
1949
|
+
wait = Selenium::WebDriver::Wait.new(timeout: 10)
|
821
1950
|
wait.until { @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]') }
|
822
|
-
|
823
|
-
# 댓글 입력
|
1951
|
+
|
824
1952
|
element = @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]')
|
825
|
-
@driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)
|
1953
|
+
@driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)
|
826
1954
|
sleep(1)
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
puts "ChatGPT로 댓글을 만드는 중입니다."
|
832
|
-
@api_key = api_key
|
833
|
-
url = 'https://api.openai.com/v1/chat/completions'
|
834
|
-
headers = {
|
835
|
-
'Content-Type' => 'application/json',
|
836
|
-
'Authorization' => 'Bearer ' + @api_key
|
837
|
-
}
|
838
|
-
data = {
|
839
|
-
'model' => 'gpt-3.5-turbo',
|
840
|
-
'messages' => [
|
841
|
-
{ "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
|
842
|
-
{ "role" => "user", "content" => pcol1 } # pcol1 직접 사용
|
843
|
-
]
|
844
|
-
}
|
845
|
-
|
846
|
-
begin
|
847
|
-
req = HTTP.headers(headers).post(url, json: data)
|
848
|
-
puts "HTTP Status: #{req.status}" # 상태 코드 확인
|
849
|
-
response = JSON.parse(req.body.to_s)
|
850
|
-
puts "API Response: #{response}" # 전체 응답 출력
|
851
|
-
|
852
|
-
if req.status == 429
|
853
|
-
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
854
|
-
end
|
855
|
-
|
856
|
-
# 응답 데이터에서 안전하게 값 추출
|
857
|
-
raw_answer = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
|
858
|
-
answer = raw_answer.gsub(/\. /, ".\n") # 줄바꿈 추가
|
859
|
-
|
860
|
-
rescue => e
|
861
|
-
puts "Error: #{e.message}"
|
862
|
-
answer = "오류가 발생했습니다."
|
863
|
-
end
|
864
|
-
|
865
|
-
# 댓글 입력
|
866
|
-
@driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]').send_keys(answer)
|
867
|
-
sleep(1)
|
868
|
-
else
|
869
|
-
begin
|
870
|
-
puts (content)
|
871
|
-
@driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]').send_keys(content)
|
872
|
-
sleep(1)
|
873
|
-
rescue
|
874
|
-
end
|
875
|
-
end
|
876
|
-
|
1955
|
+
|
1956
|
+
element.send_keys(content)
|
1957
|
+
sleep(1)
|
1958
|
+
|
877
1959
|
# 이모티콘 자동 삽입
|
878
1960
|
if option['이모티콘자동삽입'] == 'true'
|
879
1961
|
puts "이모티콘 자동 삽입 옵션 진행!!".cyan
|
880
|
-
|
1962
|
+
|
881
1963
|
# '이모티콘' 버튼 클릭
|
882
1964
|
@driver.find_element(:xpath, '//*[@class="button_sticker"]').click
|
883
1965
|
sleep(1)
|
884
|
-
|
1966
|
+
|
885
1967
|
begin
|
886
1968
|
# 'se2_line_sticker_set' 클래스를 가진 <ul> 요소 안의 모든 <li> 요소 찾기
|
887
1969
|
sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
|
888
|
-
|
1970
|
+
|
889
1971
|
# 16개 <li> 요소 중 랜덤으로 하나 선택하여 클릭
|
890
1972
|
random_li = sticker_list_elements.sample
|
891
1973
|
random_button = random_li.find_element(:tag_name, 'button') # <button> 태그 찾기
|
892
1974
|
random_button.click
|
893
|
-
|
894
|
-
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
895
1975
|
|
1976
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
1977
|
+
|
896
1978
|
# 첫 번째 클릭한 <li> 내에서 버튼을 찾기
|
897
1979
|
inner_buttons = random_li.find_elements(:tag_name, 'button')
|
898
|
-
|
1980
|
+
|
899
1981
|
# 20개 <button> 요소 중 랜덤으로 하나 선택하여 클릭
|
900
1982
|
random_button_in_li = inner_buttons.sample
|
901
1983
|
sleep(1)
|
902
1984
|
random_button_in_li.click
|
903
|
-
|
904
|
-
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
905
1985
|
|
1986
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
1987
|
+
|
906
1988
|
rescue Selenium::WebDriver::Error::StaleElementReferenceError => e
|
907
1989
|
#puts "Stale element reference 오류 발생, 계속 진행: #{e.message}".yellow
|
908
1990
|
# 오류 발생 시에도 계속 진행하려면 작업을 계속하도록 처리
|
909
1991
|
# 예를 들어, continue, or next 등으로 다음 단계로 넘어갈 수 있습니다.
|
910
|
-
|
1992
|
+
|
911
1993
|
rescue => e
|
912
1994
|
puts "기타 오류로 인해 이모티콘 삽입 안됨"
|
913
1995
|
# 기타 오류 처리
|
@@ -916,34 +1998,37 @@ class Naver
|
|
916
1998
|
else
|
917
1999
|
puts "이모티콘 자동 삽입 옵션이 비활성화됨."
|
918
2000
|
end
|
919
|
-
|
2001
|
+
|
920
2002
|
# 이미지 자동 삽입
|
921
2003
|
if option['이미지자동삽입'] == 'true'
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
2004
|
+
puts "이미지 자동 상입 옵션 진행!!".cyan
|
2005
|
+
|
2006
|
+
# 아이프레임 요소가 나타날 때까지 기다립니다.
|
2007
|
+
@image = image
|
2008
|
+
image_path = image
|
2009
|
+
|
2010
|
+
@driver.find_element(:xpath, '//*[@for="attach2"]').click
|
2011
|
+
sleep(1)
|
2012
|
+
key_stroke('escape')
|
2013
|
+
# 파일 경로 자동 입력
|
2014
|
+
file_input = @driver.find_element(:xpath, '//*[@class="button_file"]')
|
2015
|
+
|
2016
|
+
# send_keys로 파일 경로를 입력하여 이미지 업로드
|
2017
|
+
file_input.send_keys(image_path)
|
2018
|
+
sleep(2)
|
2019
|
+
|
938
2020
|
else
|
939
2021
|
end
|
940
2022
|
|
941
|
-
|
2023
|
+
|
942
2024
|
wait.until { @driver.find_element(:xpath, '//*[@class="button btn_register is_active"]') }
|
943
2025
|
@driver.find_element(:xpath, '//*[@class="button btn_register is_active"]').click
|
944
2026
|
puts "#{board_url} [댓글 작성 완료 !!]".cyan
|
945
|
-
|
946
2027
|
sleep(2)
|
2028
|
+
end
|
2029
|
+
|
2030
|
+
|
2031
|
+
|
947
2032
|
begin
|
948
2033
|
@driver.switch_to.alert
|
949
2034
|
sleep(1)
|
@@ -984,28 +2069,28 @@ class Naver
|
|
984
2069
|
ff.close()
|
985
2070
|
puts '-[√] 로그 파일 생성 완료.......'.yellow
|
986
2071
|
end
|
987
|
-
end
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
end
|
998
|
-
puts "\n"
|
2072
|
+
end
|
2073
|
+
|
2074
|
+
@driver.switch_to.default_content() # 아이프레임 해제
|
2075
|
+
def sleep_with_progress(sleep_delay)
|
2076
|
+
print "[설정 딜레이 진행 중] "
|
2077
|
+
steps = (sleep_delay.to_f / 0.5).to_i
|
2078
|
+
steps.times do
|
2079
|
+
print "."
|
2080
|
+
STDOUT.flush
|
2081
|
+
sleep(1)
|
999
2082
|
end
|
1000
|
-
|
1001
|
-
|
2083
|
+
puts "\n"
|
2084
|
+
end
|
1002
2085
|
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
end
|
2086
|
+
sleep_with_progress(sleep_delay)
|
2087
|
+
|
2088
|
+
|
2089
|
+
rescue => e
|
2090
|
+
puts "Error: #{e.message}"
|
2091
|
+
end
|
2092
|
+
else
|
2093
|
+
end
|
1009
2094
|
################################################################################ 키워드검색사용 ################################################################################
|
1010
2095
|
if option['키워드검색사용'] == 'true'
|
1011
2096
|
puts "키워드 검색 기반으로 댓글 작업 옵션 진행!!".cyan
|
@@ -1097,203 +2182,744 @@ class Naver
|
|
1097
2182
|
puts "수집한 URL들: #{collected_urls}"
|
1098
2183
|
|
1099
2184
|
|
1100
|
-
collected_urls.first(counts_number).each do |url|
|
1101
|
-
@driver.get(url) # 해당 URL로 이동
|
1102
|
-
sleep(1)
|
1103
|
-
wait = Selenium::WebDriver::Wait.new(:timeout => 20) # 아이프레임 선택
|
1104
|
-
wait.until { @driver.find_element(:xpath, '//*[@id="cafe_main"]') } # 아이프레임 선택
|
1105
|
-
sleep(1)
|
1106
|
-
@driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="cafe_main"]')) # 아이프레임 선택
|
2185
|
+
collected_urls.first(counts_number).each do |url|
|
2186
|
+
@driver.get(url) # 해당 URL로 이동
|
2187
|
+
sleep(1)
|
2188
|
+
wait = Selenium::WebDriver::Wait.new(:timeout => 20) # 아이프레임 선택
|
2189
|
+
wait.until { @driver.find_element(:xpath, '//*[@id="cafe_main"]') } # 아이프레임 선택
|
2190
|
+
sleep(1)
|
2191
|
+
@driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="cafe_main"]')) # 아이프레임 선택
|
2192
|
+
|
2193
|
+
|
2194
|
+
if option['좋아요'] == 'true'
|
2195
|
+
puts "좋아요 클릭 옵션 진행!!".cyan
|
2196
|
+
wait = Selenium::WebDriver::Wait.new(:timeout => 10)
|
2197
|
+
wait.until { @driver.find_element(:xpath, '//*[@class="u_ico _icon"]') }
|
2198
|
+
|
2199
|
+
# 댓글 입력
|
2200
|
+
element = @driver.find_element(:xpath, '//*[@class="u_ico _icon"]')
|
2201
|
+
@driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
|
2202
|
+
sleep(1)
|
2203
|
+
|
2204
|
+
# 좋아요 버튼을 찾기
|
2205
|
+
like_button = @driver.find_element(:xpath, '//div[@class="ReactionLikeIt u_likeit_list_module _cafeReactionModule"]//a[@role="button"]')
|
2206
|
+
|
2207
|
+
# aria-pressed 속성 값 확인
|
2208
|
+
aria_pressed = like_button.attribute('aria-pressed')
|
2209
|
+
|
2210
|
+
if aria_pressed == 'true'
|
2211
|
+
# 이미 좋아요를 누른 상태일 경우
|
2212
|
+
|
2213
|
+
else
|
2214
|
+
# 좋아요를 아직 누르지 않은 상태일 경우 클릭
|
2215
|
+
@driver.find_element(:xpath, '//*[@class="u_ico _icon"]').click
|
2216
|
+
sleep(2)
|
2217
|
+
end
|
2218
|
+
else
|
2219
|
+
end
|
2220
|
+
|
2221
|
+
|
2222
|
+
|
2223
|
+
if option['re_coment'] == 'true' # 대 댓글 작업때
|
2224
|
+
if @data['포스트설정']['전체대댓글'].checked?
|
2225
|
+
begin
|
2226
|
+
comment_items = @driver.find_elements(:css, 'li.CommentItem')
|
2227
|
+
original_comments = comment_items.select { |item| !item.attribute('class').include?('CommentItem--reply') }
|
2228
|
+
|
2229
|
+
original_comments.each_with_index do |item, index|
|
2230
|
+
|
2231
|
+
begin
|
2232
|
+
|
2233
|
+
if @data['포스트설정']['순서사용2'].checked?
|
2234
|
+
@content_soon ||= 0 # 초기 한 번만 0으로 세팅
|
2235
|
+
|
2236
|
+
if @data['내용설정']['내용'].nil? || @data['내용설정']['내용'].empty?
|
2237
|
+
content = ''
|
2238
|
+
else
|
2239
|
+
if @data.dig('내용설정', '랜덤사용')&.respond_to?(:checked?) && @data['내용설정']['랜덤사용'].checked?
|
2240
|
+
content = @data['내용설정']['내용'].sample[2]
|
2241
|
+
else
|
2242
|
+
content = @data['내용설정']['내용'][@content_soon][2]
|
2243
|
+
@content_soon += 1
|
2244
|
+
@content_soon = 0 if @content_soon >= @data['내용설정']['내용'].length
|
2245
|
+
end
|
2246
|
+
end
|
2247
|
+
else
|
2248
|
+
end
|
2249
|
+
|
2250
|
+
# 디엠 자동 변경이 체크된 경우 content를 변환
|
2251
|
+
if @data['포스트설정']['내용자동변경'].checked?
|
2252
|
+
change_memory = {}
|
2253
|
+
@data['포스트설정']['내용자동변경값'].each do |key, v|
|
2254
|
+
change_memory[key] = v.sample
|
2255
|
+
end
|
2256
|
+
@data['포스트설정']['내용자동변경값'].each do |key, _|
|
2257
|
+
if content.include?(key)
|
2258
|
+
content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
|
2259
|
+
else
|
2260
|
+
end
|
2261
|
+
end
|
2262
|
+
end
|
2263
|
+
|
2264
|
+
if option['ChatGPT사용'] == 'true'
|
2265
|
+
pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
|
2266
|
+
sleep(1)
|
2267
|
+
|
2268
|
+
puts "ChatGPT로 댓글을 만드는 중입니다."
|
2269
|
+
@api_key = api_key
|
2270
|
+
url = 'https://api.openai.com/v1/chat/completions'
|
2271
|
+
headers = {
|
2272
|
+
'Content-Type' => 'application/json',
|
2273
|
+
'Authorization' => 'Bearer ' + @api_key
|
2274
|
+
}
|
2275
|
+
data = {
|
2276
|
+
'model' => 'gpt-3.5-turbo',
|
2277
|
+
'messages' => [
|
2278
|
+
{ "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
|
2279
|
+
{ "role" => "user", "content" => pcol1 } # pcol1 직접 사용
|
2280
|
+
]
|
2281
|
+
}
|
2282
|
+
|
2283
|
+
begin
|
2284
|
+
req = HTTP.headers(headers).post(url, json: data)
|
2285
|
+
puts "HTTP Status: #{req.status}" # 상태 코드 확인
|
2286
|
+
response = JSON.parse(req.body.to_s)
|
2287
|
+
puts "API Response: #{response}" # 전체 응답 출력
|
2288
|
+
|
2289
|
+
if req.status == 429
|
2290
|
+
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
2291
|
+
end
|
2292
|
+
|
2293
|
+
# 응답 데이터에서 안전하게 값 추출
|
2294
|
+
raw_content = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
|
2295
|
+
content = raw_content.gsub(/\. /, ".\n") # 줄바꿈 추가
|
2296
|
+
|
2297
|
+
rescue => e
|
2298
|
+
puts "Error: #{e.message}"
|
2299
|
+
content = "오류가 발생했습니다."
|
2300
|
+
end
|
2301
|
+
else
|
2302
|
+
end
|
2303
|
+
|
2304
|
+
reply_button = item.find_element(:css, 'a.comment_info_button')
|
2305
|
+
puts "대댓글 #{index + 1} 작성 중..."
|
2306
|
+
reply_button.click
|
2307
|
+
sleep(1.5)
|
2308
|
+
|
2309
|
+
textarea = @driver.find_element(:css, 'textarea.comment_inbox_text')
|
2310
|
+
textarea.send_keys(content)
|
2311
|
+
sleep(1)
|
2312
|
+
|
2313
|
+
if option['이모티콘자동삽입'] == 'true'
|
2314
|
+
puts "이모티콘 자동 삽입 옵션 진행!!".cyan
|
2315
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
2316
|
+
reply_comments.each_with_index do |item, index|
|
2317
|
+
begin
|
2318
|
+
|
2319
|
+
|
2320
|
+
# 해당 대댓글 내부의 이모티콘 버튼 찾기
|
2321
|
+
sticker_button = item.find_element(:css, 'a.button_sticker')
|
2322
|
+
sticker_button.click
|
2323
|
+
sleep(1)
|
2324
|
+
|
2325
|
+
rescue
|
2326
|
+
end
|
2327
|
+
end
|
2328
|
+
begin
|
2329
|
+
# 'se2_line_sticker_set' 클래스를 가진 <ul> 요소 안의 모든 <li> 요소 찾기
|
2330
|
+
sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
|
2331
|
+
|
2332
|
+
# 16개 <li> 요소 중 랜덤으로 하나 선택하여 클릭
|
2333
|
+
random_li = sticker_list_elements.sample
|
2334
|
+
random_button = random_li.find_element(:tag_name, 'button') # <button> 태그 찾기
|
2335
|
+
random_button.click
|
2336
|
+
|
2337
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
2338
|
+
|
2339
|
+
# 첫 번째 클릭한 <li> 내에서 버튼을 찾기
|
2340
|
+
inner_buttons = random_li.find_elements(:tag_name, 'button')
|
2341
|
+
|
2342
|
+
# 20개 <button> 요소 중 랜덤으로 하나 선택하여 클릭
|
2343
|
+
random_button_in_li = inner_buttons.sample
|
2344
|
+
sleep(1)
|
2345
|
+
random_button_in_li.click
|
2346
|
+
|
2347
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
2348
|
+
|
2349
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError => e
|
2350
|
+
#puts "Stale element reference 오류 발생, 계속 진행: #{e.message}".yellow
|
2351
|
+
# 오류 발생 시에도 계속 진행하려면 작업을 계속하도록 처리
|
2352
|
+
# 예를 들어, continue, or next 등으로 다음 단계로 넘어갈 수 있습니다.
|
2353
|
+
|
2354
|
+
rescue => e
|
2355
|
+
puts "기타 오류로 인해 이모티콘 삽입 안됨"
|
2356
|
+
# 기타 오류 처리
|
2357
|
+
# 여기에 추가적인 예외 처리 로직을 넣을 수 있습니다.
|
2358
|
+
end
|
2359
|
+
else
|
2360
|
+
puts "이모티콘 자동 삽입 옵션이 비활성화됨."
|
2361
|
+
end
|
2362
|
+
|
2363
|
+
# 이미지 자동 삽입
|
2364
|
+
if option['이미지자동삽입'] == 'true'
|
2365
|
+
puts "이미지 자동 상입 옵션 진행!!".cyan
|
2366
|
+
|
2367
|
+
# 아이프레임 요소가 나타날 때까지 기다립니다.
|
2368
|
+
@image = image
|
2369
|
+
image_path = image
|
2370
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
2371
|
+
|
2372
|
+
reply_comments.each_with_index do |item, index|
|
2373
|
+
begin
|
2374
|
+
|
2375
|
+
|
2376
|
+
# 해당 대댓글 내부에서 for="attach2"인 라벨 클릭
|
2377
|
+
attach_button = item.find_element(:xpath, './/*[@class="button_file"]')
|
2378
|
+
attach_button.click
|
2379
|
+
sleep(1)
|
2380
|
+
|
2381
|
+
rescue
|
2382
|
+
end
|
2383
|
+
end
|
2384
|
+
key_stroke('escape')
|
2385
|
+
# 파일 경로 자동 입력
|
2386
|
+
file_input = @driver.find_element(:xpath, '//*[@title="사진첨부"]')
|
2387
|
+
|
2388
|
+
# send_keys로 파일 경로를 입력하여 이미지 업로드
|
2389
|
+
file_input.send_keys(image_path)
|
2390
|
+
sleep(2)
|
2391
|
+
|
2392
|
+
else
|
2393
|
+
end
|
2394
|
+
|
2395
|
+
register_btn = @driver.find_element(:css, 'a.button.btn_register')
|
2396
|
+
register_btn.click
|
2397
|
+
sleep(2)
|
2398
|
+
|
2399
|
+
rescue => e
|
2400
|
+
puts "대댓글 #{index + 1} 처리 중 오류 발생: #{e.message}"
|
2401
|
+
next
|
2402
|
+
end
|
2403
|
+
end
|
2404
|
+
rescue => e
|
2405
|
+
puts "전체대댓글 처리 중 예외 발생: #{e.message}"
|
2406
|
+
end
|
2407
|
+
|
2408
|
+
elsif @data['포스트설정']['지정대댓글'].checked?
|
2409
|
+
targets = @data['포스트설정']['nik_or_number'].text.to_s.force_encoding('utf-8').split(',').map(&:strip)
|
2410
|
+
targets.each do |target|
|
2411
|
+
if target.match?(/^\d+$/)
|
2412
|
+
index = target.to_i - 1
|
2413
|
+
comment_items = @driver.find_elements(:css, 'li.CommentItem')
|
2414
|
+
original_comments = comment_items.select { |item| !item.attribute('class').include?('CommentItem--reply') }
|
2415
|
+
|
2416
|
+
if original_comments[index]
|
2417
|
+
begin
|
2418
|
+
|
2419
|
+
if @data['포스트설정']['순서사용2'].checked?
|
2420
|
+
@content_soon ||= 0 # 초기 한 번만 0으로 세팅
|
2421
|
+
|
2422
|
+
if @data['내용설정']['내용'].nil? || @data['내용설정']['내용'].empty?
|
2423
|
+
content = ''
|
2424
|
+
else
|
2425
|
+
if @data.dig('내용설정', '랜덤사용')&.respond_to?(:checked?) && @data['내용설정']['랜덤사용'].checked?
|
2426
|
+
content = @data['내용설정']['내용'].sample[2]
|
2427
|
+
else
|
2428
|
+
content = @data['내용설정']['내용'][@content_soon][2]
|
2429
|
+
@content_soon += 1
|
2430
|
+
@content_soon = 0 if @content_soon >= @data['내용설정']['내용'].length
|
2431
|
+
end
|
2432
|
+
end
|
2433
|
+
else
|
2434
|
+
end
|
2435
|
+
|
2436
|
+
# 디엠 자동 변경이 체크된 경우 content를 변환
|
2437
|
+
if @data['포스트설정']['내용자동변경'].checked?
|
2438
|
+
change_memory = {}
|
2439
|
+
@data['포스트설정']['내용자동변경값'].each do |key, v|
|
2440
|
+
change_memory[key] = v.sample
|
2441
|
+
end
|
2442
|
+
@data['포스트설정']['내용자동변경값'].each do |key, _|
|
2443
|
+
if content.include?(key)
|
2444
|
+
content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
|
2445
|
+
else
|
2446
|
+
end
|
2447
|
+
end
|
2448
|
+
end
|
2449
|
+
|
2450
|
+
if option['ChatGPT사용'] == 'true'
|
2451
|
+
pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
|
2452
|
+
sleep(1)
|
2453
|
+
|
2454
|
+
puts "ChatGPT로 댓글을 만드는 중입니다."
|
2455
|
+
@api_key = api_key
|
2456
|
+
url = 'https://api.openai.com/v1/chat/completions'
|
2457
|
+
headers = {
|
2458
|
+
'Content-Type' => 'application/json',
|
2459
|
+
'Authorization' => 'Bearer ' + @api_key
|
2460
|
+
}
|
2461
|
+
data = {
|
2462
|
+
'model' => 'gpt-3.5-turbo',
|
2463
|
+
'messages' => [
|
2464
|
+
{ "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
|
2465
|
+
{ "role" => "user", "content" => pcol1 } # pcol1 직접 사용
|
2466
|
+
]
|
2467
|
+
}
|
2468
|
+
|
2469
|
+
begin
|
2470
|
+
req = HTTP.headers(headers).post(url, json: data)
|
2471
|
+
puts "HTTP Status: #{req.status}" # 상태 코드 확인
|
2472
|
+
response = JSON.parse(req.body.to_s)
|
2473
|
+
puts "API Response: #{response}" # 전체 응답 출력
|
2474
|
+
|
2475
|
+
if req.status == 429
|
2476
|
+
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
2477
|
+
end
|
2478
|
+
|
2479
|
+
# 응답 데이터에서 안전하게 값 추출
|
2480
|
+
raw_content = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
|
2481
|
+
content = raw_content.gsub(/\. /, ".\n") # 줄바꿈 추가
|
2482
|
+
|
2483
|
+
rescue => e
|
2484
|
+
puts "Error: #{e.message}"
|
2485
|
+
content = "오류가 발생했습니다."
|
2486
|
+
end
|
2487
|
+
else
|
2488
|
+
end
|
2489
|
+
|
2490
|
+
puts "#{index + 1}번째 댓글에 대댓글 작성 시작"
|
2491
|
+
reply_button = original_comments[index].find_element(:css, 'a.comment_info_button')
|
2492
|
+
reply_button.click
|
2493
|
+
sleep(1.5)
|
2494
|
+
|
2495
|
+
textarea = @driver.find_element(:css, 'textarea.comment_inbox_text')
|
2496
|
+
textarea.send_keys(content)
|
2497
|
+
sleep(1)
|
2498
|
+
|
2499
|
+
if option['이모티콘자동삽입'] == 'true'
|
2500
|
+
puts "이모티콘 자동 삽입 옵션 진행!!".cyan
|
2501
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
2502
|
+
reply_comments.each_with_index do |item, index|
|
2503
|
+
begin
|
2504
|
+
|
2505
|
+
|
2506
|
+
# 해당 대댓글 내부의 이모티콘 버튼 찾기
|
2507
|
+
sticker_button = item.find_element(:css, 'a.button_sticker')
|
2508
|
+
sticker_button.click
|
2509
|
+
sleep(1)
|
2510
|
+
|
2511
|
+
rescue
|
2512
|
+
end
|
2513
|
+
end
|
2514
|
+
|
2515
|
+
begin
|
2516
|
+
# 'se2_line_sticker_set' 클래스를 가진 <ul> 요소 안의 모든 <li> 요소 찾기
|
2517
|
+
sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
|
2518
|
+
|
2519
|
+
# 16개 <li> 요소 중 랜덤으로 하나 선택하여 클릭
|
2520
|
+
random_li = sticker_list_elements.sample
|
2521
|
+
random_button = random_li.find_element(:tag_name, 'button') # <button> 태그 찾기
|
2522
|
+
random_button.click
|
2523
|
+
|
2524
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
2525
|
+
|
2526
|
+
# 첫 번째 클릭한 <li> 내에서 버튼을 찾기
|
2527
|
+
inner_buttons = random_li.find_elements(:tag_name, 'button')
|
2528
|
+
|
2529
|
+
# 20개 <button> 요소 중 랜덤으로 하나 선택하여 클릭
|
2530
|
+
random_button_in_li = inner_buttons.sample
|
2531
|
+
sleep(1)
|
2532
|
+
random_button_in_li.click
|
2533
|
+
|
2534
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
2535
|
+
|
2536
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError => e
|
2537
|
+
#puts "Stale element reference 오류 발생, 계속 진행: #{e.message}".yellow
|
2538
|
+
# 오류 발생 시에도 계속 진행하려면 작업을 계속하도록 처리
|
2539
|
+
# 예를 들어, continue, or next 등으로 다음 단계로 넘어갈 수 있습니다.
|
2540
|
+
|
2541
|
+
rescue => e
|
2542
|
+
puts "기타 오류로 인해 이모티콘 삽입 안됨"
|
2543
|
+
# 기타 오류 처리
|
2544
|
+
# 여기에 추가적인 예외 처리 로직을 넣을 수 있습니다.
|
2545
|
+
end
|
2546
|
+
else
|
2547
|
+
puts "이모티콘 자동 삽입 옵션이 비활성화됨."
|
2548
|
+
end
|
2549
|
+
|
2550
|
+
# 이미지 자동 삽입
|
2551
|
+
if option['이미지자동삽입'] == 'true'
|
2552
|
+
puts "이미지 자동 상입 옵션 진행!!".cyan
|
2553
|
+
|
2554
|
+
# 아이프레임 요소가 나타날 때까지 기다립니다.
|
2555
|
+
@image = image
|
2556
|
+
image_path = image
|
2557
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
2558
|
+
|
2559
|
+
reply_comments.each_with_index do |item, index|
|
2560
|
+
begin
|
2561
|
+
|
2562
|
+
|
2563
|
+
# 해당 대댓글 내부에서 for="attach2"인 라벨 클릭
|
2564
|
+
attach_button = item.find_element(:xpath, './/*[@class="button_file"]')
|
2565
|
+
attach_button.click
|
2566
|
+
sleep(1)
|
2567
|
+
|
2568
|
+
rescue
|
2569
|
+
end
|
2570
|
+
end
|
2571
|
+
key_stroke('escape')
|
2572
|
+
# 파일 경로 자동 입력
|
2573
|
+
file_input = @driver.find_element(:xpath, '//*[@title="사진첨부"]')
|
2574
|
+
|
2575
|
+
# send_keys로 파일 경로를 입력하여 이미지 업로드
|
2576
|
+
file_input.send_keys(image_path)
|
2577
|
+
sleep(2)
|
2578
|
+
|
2579
|
+
else
|
2580
|
+
end
|
2581
|
+
|
2582
|
+
register_btn = @driver.find_element(:css, 'a.button.btn_register')
|
2583
|
+
register_btn.click
|
2584
|
+
sleep(2)
|
2585
|
+
|
2586
|
+
puts "#{index + 1}번째 댓글에 대댓글 작성 완료"
|
2587
|
+
rescue => e
|
2588
|
+
puts "댓글 인덱스 #{index + 1} 처리 중 오류 발생: #{e.message}"
|
2589
|
+
end
|
2590
|
+
else
|
2591
|
+
puts "해당 인덱스(#{index + 1})의 답글쓰기 버튼이 없습니다."
|
2592
|
+
end
|
2593
|
+
|
2594
|
+
else # 닉네임으로 찾기
|
2595
|
+
comment_items = @driver.find_elements(:css, 'li.CommentItem')
|
2596
|
+
original_comments = comment_items.select { |item| !item.attribute('class').include?('CommentItem--reply') }
|
2597
|
+
|
2598
|
+
matched = false
|
2599
|
+
last_matched_item = nil # 마지막에 닉네임이 일치한 댓글 저장
|
2600
|
+
|
2601
|
+
original_comments.each_with_index do |item, idx|
|
2602
|
+
begin
|
2603
|
+
nickname_element = item.find_element(:css, 'a.comment_nickname')
|
2604
|
+
nickname = nickname_element.text.strip
|
2605
|
+
|
2606
|
+
if nickname.include?(target)
|
2607
|
+
puts "#{target} 닉네임이 포함된 댓글 발견 (#{idx + 1}번째)"
|
2608
|
+
last_matched_item = item # 매번 갱신 → 마지막에 발견된 걸 저장
|
2609
|
+
end
|
2610
|
+
rescue => e
|
2611
|
+
puts "닉네임 검사 중 오류 발생: #{e.message}"
|
2612
|
+
next
|
2613
|
+
end
|
2614
|
+
end
|
2615
|
+
|
2616
|
+
# 루프 끝난 뒤 마지막 댓글에만 작업 실행
|
2617
|
+
if last_matched_item
|
2618
|
+
begin
|
2619
|
+
|
2620
|
+
if @data['포스트설정']['순서사용2'].checked?
|
2621
|
+
@content_soon ||= 0 # 초기 한 번만 0으로 세팅
|
2622
|
+
|
2623
|
+
if @data['내용설정']['내용'].nil? || @data['내용설정']['내용'].empty?
|
2624
|
+
content = ''
|
2625
|
+
else
|
2626
|
+
if @data.dig('내용설정', '랜덤사용')&.respond_to?(:checked?) && @data['내용설정']['랜덤사용'].checked?
|
2627
|
+
content = @data['내용설정']['내용'].sample[2]
|
2628
|
+
else
|
2629
|
+
content = @data['내용설정']['내용'][@content_soon][2]
|
2630
|
+
@content_soon += 1
|
2631
|
+
@content_soon = 0 if @content_soon >= @data['내용설정']['내용'].length
|
2632
|
+
end
|
2633
|
+
end
|
2634
|
+
else
|
2635
|
+
end
|
2636
|
+
|
2637
|
+
# 디엠 자동 변경이 체크된 경우 content를 변환
|
2638
|
+
if @data['포스트설정']['내용자동변경'].checked?
|
2639
|
+
change_memory = {}
|
2640
|
+
@data['포스트설정']['내용자동변경값'].each do |key, v|
|
2641
|
+
change_memory[key] = v.sample
|
2642
|
+
end
|
2643
|
+
@data['포스트설정']['내용자동변경값'].each do |key, _|
|
2644
|
+
if content.include?(key)
|
2645
|
+
content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
|
2646
|
+
else
|
2647
|
+
end
|
2648
|
+
end
|
2649
|
+
end
|
1107
2650
|
|
1108
|
-
|
1109
|
-
|
2651
|
+
if option['ChatGPT사용'] == 'true'
|
2652
|
+
pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
|
2653
|
+
sleep(1)
|
2654
|
+
|
2655
|
+
puts "ChatGPT로 댓글을 만드는 중입니다."
|
2656
|
+
@api_key = api_key
|
2657
|
+
url = 'https://api.openai.com/v1/chat/completions'
|
2658
|
+
headers = {
|
2659
|
+
'Content-Type' => 'application/json',
|
2660
|
+
'Authorization' => 'Bearer ' + @api_key
|
2661
|
+
}
|
2662
|
+
data = {
|
2663
|
+
'model' => 'gpt-3.5-turbo',
|
2664
|
+
'messages' => [
|
2665
|
+
{ "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
|
2666
|
+
{ "role" => "user", "content" => pcol1 } # pcol1 직접 사용
|
2667
|
+
]
|
2668
|
+
}
|
2669
|
+
|
2670
|
+
begin
|
2671
|
+
req = HTTP.headers(headers).post(url, json: data)
|
2672
|
+
puts "HTTP Status: #{req.status}" # 상태 코드 확인
|
2673
|
+
response = JSON.parse(req.body.to_s)
|
2674
|
+
puts "API Response: #{response}" # 전체 응답 출력
|
2675
|
+
|
2676
|
+
if req.status == 429
|
2677
|
+
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
2678
|
+
end
|
2679
|
+
|
2680
|
+
# 응답 데이터에서 안전하게 값 추출
|
2681
|
+
raw_content = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
|
2682
|
+
content = raw_content.gsub(/\. /, ".\n") # 줄바꿈 추가
|
2683
|
+
|
2684
|
+
rescue => e
|
2685
|
+
puts "Error: #{e.message}"
|
2686
|
+
content = "오류가 발생했습니다."
|
2687
|
+
end
|
2688
|
+
else
|
2689
|
+
end
|
2690
|
+
|
2691
|
+
reply_button = last_matched_item.find_element(:css, 'a.comment_info_button')
|
2692
|
+
reply_button.click
|
2693
|
+
sleep(1.5)
|
2694
|
+
|
2695
|
+
textarea = @driver.find_element(:css, 'textarea.comment_inbox_text')
|
2696
|
+
textarea.send_keys(content)
|
2697
|
+
sleep(1)
|
2698
|
+
|
2699
|
+
if option['이모티콘자동삽입'] == 'true'
|
2700
|
+
puts "이모티콘 자동 삽입 옵션 진행!!".cyan
|
2701
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
2702
|
+
reply_comments.each_with_index do |item, index|
|
2703
|
+
begin
|
2704
|
+
|
2705
|
+
sticker_button = item.find_element(:css, 'a.button_sticker')
|
2706
|
+
sticker_button.click
|
2707
|
+
sleep(1)
|
2708
|
+
rescue
|
2709
|
+
end
|
2710
|
+
end
|
2711
|
+
begin
|
2712
|
+
sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
|
2713
|
+
random_li = sticker_list_elements.sample
|
2714
|
+
random_button = random_li.find_element(:tag_name, 'button')
|
2715
|
+
random_button.click
|
2716
|
+
sleep(1)
|
2717
|
+
inner_buttons = random_li.find_elements(:tag_name, 'button')
|
2718
|
+
random_button_in_li = inner_buttons.sample
|
2719
|
+
sleep(1)
|
2720
|
+
random_button_in_li.click
|
2721
|
+
sleep(1)
|
2722
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError
|
2723
|
+
rescue => e
|
2724
|
+
puts "기타 오류로 인해 이모티콘 삽입 안됨"
|
2725
|
+
end
|
2726
|
+
else
|
2727
|
+
puts "이모티콘 자동 삽입 옵션이 비활성화됨."
|
2728
|
+
end
|
1110
2729
|
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
end
|
1131
|
-
@data['포스트설정']['내용자동변경값'].each do |key, _|
|
1132
|
-
if content.include?(key)
|
1133
|
-
content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
|
1134
|
-
else
|
1135
|
-
end
|
1136
|
-
end
|
1137
|
-
end
|
2730
|
+
if option['이미지자동삽입'] == 'true'
|
2731
|
+
puts "이미지 자동 삽입 옵션 진행!!".cyan
|
2732
|
+
@image = image
|
2733
|
+
image_path = image
|
2734
|
+
reply_comments = @driver.find_elements(:css, 'li.CommentItem.CommentItem--reply')
|
2735
|
+
reply_comments.each_with_index do |item, index|
|
2736
|
+
begin
|
2737
|
+
|
2738
|
+
attach_button = item.find_element(:xpath, './/*[@class="button_file"]')
|
2739
|
+
attach_button.click
|
2740
|
+
sleep(1)
|
2741
|
+
rescue
|
2742
|
+
end
|
2743
|
+
end
|
2744
|
+
key_stroke('escape')
|
2745
|
+
file_input = @driver.find_element(:xpath, '//*[@title="사진첨부"]')
|
2746
|
+
file_input.send_keys(image_path)
|
2747
|
+
sleep(2)
|
2748
|
+
end
|
1138
2749
|
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
wait.until { @driver.find_element(:xpath, '//*[@class="u_ico _icon"]') }
|
2750
|
+
register_btn = @driver.find_element(:css, 'a.button.btn_register')
|
2751
|
+
register_btn.click
|
2752
|
+
sleep(2)
|
1143
2753
|
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
2754
|
+
matched = true
|
2755
|
+
rescue => e
|
2756
|
+
puts "대댓글 등록 중 오류 발생: #{e.message}"
|
2757
|
+
end
|
2758
|
+
end
|
2759
|
+
|
2760
|
+
puts "닉네임 '#{target}'을 포함한 댓글을 찾지 못했습니다." unless matched
|
1148
2761
|
|
1149
|
-
|
1150
|
-
|
2762
|
+
end
|
2763
|
+
end
|
1151
2764
|
|
1152
|
-
|
1153
|
-
aria_pressed = like_button.attribute('aria-pressed')
|
2765
|
+
end
|
1154
2766
|
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
else
|
1159
|
-
# 좋아요를 아직 누르지 않은 상태일 경우 클릭
|
1160
|
-
@driver.find_element(:xpath, '//*[@class="u_ico _icon"]').click
|
1161
|
-
sleep(2)
|
1162
|
-
end
|
1163
|
-
else
|
1164
|
-
end
|
2767
|
+
elsif option['re_coment'] == 'false' # 대 댓글 아닐때
|
2768
|
+
if @data['포스트설정']['순서사용2'].checked?
|
2769
|
+
@content_soon ||= 0 # 초기 한 번만 0으로 세팅
|
1165
2770
|
|
1166
|
-
|
1167
|
-
|
2771
|
+
if @data['내용설정']['내용'].nil? || @data['내용설정']['내용'].empty?
|
2772
|
+
content = ''
|
2773
|
+
else
|
2774
|
+
if @data.dig('내용설정', '랜덤사용')&.respond_to?(:checked?) && @data['내용설정']['랜덤사용'].checked?
|
2775
|
+
content = @data['내용설정']['내용'].sample[2]
|
2776
|
+
else
|
2777
|
+
content = @data['내용설정']['내용'][@content_soon][2]
|
2778
|
+
@content_soon += 1
|
2779
|
+
@content_soon = 0 if @content_soon >= @data['내용설정']['내용'].length
|
2780
|
+
end
|
2781
|
+
end
|
2782
|
+
else
|
2783
|
+
end
|
2784
|
+
|
2785
|
+
# 디엠 자동 변경이 체크된 경우 content를 변환
|
2786
|
+
if @data['포스트설정']['내용자동변경'].checked?
|
2787
|
+
change_memory = {}
|
2788
|
+
@data['포스트설정']['내용자동변경값'].each do |key, v|
|
2789
|
+
change_memory[key] = v.sample
|
2790
|
+
end
|
2791
|
+
@data['포스트설정']['내용자동변경값'].each do |key, _|
|
2792
|
+
if content.include?(key)
|
2793
|
+
content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
|
2794
|
+
else
|
2795
|
+
end
|
2796
|
+
end
|
2797
|
+
end
|
1168
2798
|
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
2799
|
+
if option['ChatGPT사용'] == 'true'
|
2800
|
+
pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
|
2801
|
+
sleep(1)
|
2802
|
+
|
2803
|
+
puts "ChatGPT로 댓글을 만드는 중입니다."
|
2804
|
+
@api_key = api_key
|
2805
|
+
url = 'https://api.openai.com/v1/chat/completions'
|
2806
|
+
headers = {
|
2807
|
+
'Content-Type' => 'application/json',
|
2808
|
+
'Authorization' => 'Bearer ' + @api_key
|
2809
|
+
}
|
2810
|
+
data = {
|
2811
|
+
'model' => 'gpt-3.5-turbo',
|
2812
|
+
'messages' => [
|
2813
|
+
{ "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
|
2814
|
+
{ "role" => "user", "content" => pcol1 } # pcol1 직접 사용
|
2815
|
+
]
|
2816
|
+
}
|
2817
|
+
|
2818
|
+
begin
|
2819
|
+
req = HTTP.headers(headers).post(url, json: data)
|
2820
|
+
puts "HTTP Status: #{req.status}" # 상태 코드 확인
|
2821
|
+
response = JSON.parse(req.body.to_s)
|
2822
|
+
puts "API Response: #{response}" # 전체 응답 출력
|
2823
|
+
|
2824
|
+
if req.status == 429
|
2825
|
+
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
2826
|
+
end
|
2827
|
+
|
2828
|
+
# 응답 데이터에서 안전하게 값 추출
|
2829
|
+
raw_content = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
|
2830
|
+
content = raw_content.gsub(/\. /, ".\n") # 줄바꿈 추가
|
2831
|
+
|
2832
|
+
rescue => e
|
2833
|
+
puts "Error: #{e.message}"
|
2834
|
+
content = "오류가 발생했습니다."
|
2835
|
+
end
|
2836
|
+
else
|
2837
|
+
end
|
1172
2838
|
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
|
1179
|
-
sleep(1)
|
1180
|
-
|
1181
|
-
puts "ChatGPT로 댓글을 만드는 중입니다."
|
1182
|
-
@api_key = api_key
|
1183
|
-
url = 'https://api.openai.com/v1/chat/completions'
|
1184
|
-
headers = {
|
1185
|
-
'Content-Type' => 'application/json',
|
1186
|
-
'Authorization' => 'Bearer ' + @api_key
|
1187
|
-
}
|
1188
|
-
data = {
|
1189
|
-
'model' => 'gpt-3.5-turbo',
|
1190
|
-
'messages' => [
|
1191
|
-
{ "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
|
1192
|
-
{ "role" => "user", "content" => pcol1 } # pcol1 직접 사용
|
1193
|
-
]
|
1194
|
-
}
|
1195
|
-
|
1196
|
-
begin
|
1197
|
-
req = HTTP.headers(headers).post(url, json: data)
|
1198
|
-
puts "HTTP Status: #{req.status}" # 상태 코드 확인
|
1199
|
-
response = JSON.parse(req.body.to_s)
|
1200
|
-
puts "API Response: #{response}" # 전체 응답 출력
|
1201
|
-
|
1202
|
-
if req.status == 429
|
1203
|
-
return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
|
1204
|
-
end
|
1205
|
-
|
1206
|
-
# 응답 데이터에서 안전하게 값 추출
|
1207
|
-
raw_answer = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
|
1208
|
-
answer = raw_answer.gsub(/\. /, ".\n") # 줄바꿈 추가
|
1209
|
-
|
1210
|
-
rescue => e
|
1211
|
-
puts "Error: #{e.message}"
|
1212
|
-
answer = "오류가 발생했습니다."
|
1213
|
-
end
|
1214
|
-
|
1215
|
-
# 댓글 입력
|
1216
|
-
@driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]').send_keys(answer)
|
1217
|
-
sleep(1)
|
1218
|
-
else
|
1219
|
-
begin
|
1220
|
-
puts (content)
|
1221
|
-
@driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]').send_keys(content)
|
2839
|
+
wait = Selenium::WebDriver::Wait.new(timeout: 10)
|
2840
|
+
wait.until { @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]') }
|
2841
|
+
|
2842
|
+
element = @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]')
|
2843
|
+
@driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)
|
1222
2844
|
sleep(1)
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
2845
|
+
|
2846
|
+
element.send_keys(content)
|
2847
|
+
sleep(1)
|
2848
|
+
|
2849
|
+
# 이모티콘 자동 삽입
|
2850
|
+
if option['이모티콘자동삽입'] == 'true'
|
2851
|
+
puts "이모티콘 자동 삽입 옵션 진행!!".cyan
|
2852
|
+
|
2853
|
+
# '이모티콘' 버튼 클릭
|
2854
|
+
@driver.find_element(:xpath, '//*[@class="button_sticker"]').click
|
2855
|
+
sleep(1)
|
2856
|
+
|
2857
|
+
begin
|
2858
|
+
# 'se2_line_sticker_set' 클래스를 가진 <ul> 요소 안의 모든 <li> 요소 찾기
|
2859
|
+
sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
|
2860
|
+
|
2861
|
+
# 16개 <li> 요소 중 랜덤으로 하나 선택하여 클릭
|
2862
|
+
random_li = sticker_list_elements.sample
|
2863
|
+
random_button = random_li.find_element(:tag_name, 'button') # <button> 태그 찾기
|
2864
|
+
random_button.click
|
2865
|
+
|
2866
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
2867
|
+
|
2868
|
+
# 첫 번째 클릭한 <li> 내에서 버튼을 찾기
|
2869
|
+
inner_buttons = random_li.find_elements(:tag_name, 'button')
|
2870
|
+
|
2871
|
+
# 20개 <button> 요소 중 랜덤으로 하나 선택하여 클릭
|
2872
|
+
random_button_in_li = inner_buttons.sample
|
2873
|
+
sleep(1)
|
2874
|
+
random_button_in_li.click
|
2875
|
+
|
2876
|
+
sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
|
2877
|
+
|
2878
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError => e
|
2879
|
+
#puts "Stale element reference 오류 발생, 계속 진행: #{e.message}".yellow
|
2880
|
+
# 오류 발생 시에도 계속 진행하려면 작업을 계속하도록 처리
|
2881
|
+
# 예를 들어, continue, or next 등으로 다음 단계로 넘어갈 수 있습니다.
|
2882
|
+
|
2883
|
+
rescue => e
|
2884
|
+
puts "기타 오류로 인해 이모티콘 삽입 안됨"
|
2885
|
+
# 기타 오류 처리
|
2886
|
+
# 여기에 추가적인 예외 처리 로직을 넣을 수 있습니다.
|
2887
|
+
end
|
2888
|
+
else
|
2889
|
+
puts "이모티콘 자동 삽입 옵션이 비활성화됨."
|
2890
|
+
end
|
1243
2891
|
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
inner_buttons = random_li.find_elements(:tag_name, 'button')
|
2892
|
+
# 이미지 자동 삽입
|
2893
|
+
if option['이미지자동삽입'] == 'true'
|
2894
|
+
puts "이미지 자동 상입 옵션 진행!!".cyan
|
1248
2895
|
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
2896
|
+
# 아이프레임 요소가 나타날 때까지 기다립니다.
|
2897
|
+
@image = image
|
2898
|
+
image_path = image
|
2899
|
+
|
2900
|
+
@driver.find_element(:xpath, '//*[@for="attach2"]').click
|
2901
|
+
sleep(1)
|
2902
|
+
key_stroke('escape')
|
2903
|
+
# 파일 경로 자동 입력
|
2904
|
+
file_input = @driver.find_element(:xpath, '//*[@class="button_file"]')
|
1253
2905
|
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
rescue => e
|
1262
|
-
puts "기타 오류로 인해 이모티콘 삽입 안됨"
|
1263
|
-
# 기타 오류 처리
|
1264
|
-
# 여기에 추가적인 예외 처리 로직을 넣을 수 있습니다.
|
1265
|
-
end
|
1266
|
-
else
|
1267
|
-
puts "이모티콘 자동 삽입 옵션이 비활성화됨."
|
1268
|
-
end
|
1269
|
-
|
1270
|
-
# 이미지 자동 삽입
|
1271
|
-
if option['이미지자동삽입'] == 'true'
|
1272
|
-
puts "이미지 자동 상입 옵션 진행!!".cyan
|
2906
|
+
# send_keys로 파일 경로를 입력하여 이미지 업로드
|
2907
|
+
file_input.send_keys(image_path)
|
2908
|
+
sleep(2)
|
2909
|
+
|
2910
|
+
else
|
2911
|
+
end
|
1273
2912
|
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
# 파일 경로 자동 입력
|
1282
|
-
file_input = @driver.find_element(:xpath, '//*[@id="attach2"]')
|
2913
|
+
|
2914
|
+
wait.until { @driver.find_element(:xpath, '//*[@class="button btn_register is_active"]') }
|
2915
|
+
@driver.find_element(:xpath, '//*[@class="button btn_register is_active"]').click
|
2916
|
+
sleep(2)
|
2917
|
+
posting_url = @driver.current_url
|
2918
|
+
puts "#{posting_url} [댓글 진행 완료 !!]".cyan
|
2919
|
+
end
|
1283
2920
|
|
1284
|
-
# send_keys로 파일 경로를 입력하여 이미지 업로드
|
1285
|
-
file_input.send_keys(image_path)
|
1286
|
-
sleep(2)
|
1287
2921
|
|
1288
|
-
else
|
1289
|
-
end
|
1290
2922
|
|
1291
|
-
|
1292
|
-
|
1293
|
-
wait.until { @driver.find_element(:xpath, '//*[@class="button btn_register is_active"]') }
|
1294
|
-
@driver.find_element(:xpath, '//*[@class="button btn_register is_active"]').click
|
1295
|
-
puts "#{board_url} [댓글 작성 완료 !!]".cyan
|
1296
|
-
sleep(2)
|
1297
2923
|
begin
|
1298
2924
|
@driver.switch_to.alert
|
1299
2925
|
sleep(1)
|
@@ -1334,26 +2960,28 @@ class Naver
|
|
1334
2960
|
ff.close()
|
1335
2961
|
puts '-[√] 로그 파일 생성 완료.......'.yellow
|
1336
2962
|
end
|
1337
|
-
end
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
2963
|
+
end
|
2964
|
+
|
2965
|
+
|
2966
|
+
@driver.switch_to.default_content() # 아이프레임 해제
|
2967
|
+
def sleep_with_progress(sleep_delay)
|
2968
|
+
print "[설정 딜레이 진행 중] "
|
2969
|
+
steps = (sleep_delay.to_f / 0.5).to_i
|
2970
|
+
steps.times do
|
2971
|
+
print "."
|
2972
|
+
STDOUT.flush
|
2973
|
+
sleep(1)
|
2974
|
+
end
|
2975
|
+
puts "\n"
|
1347
2976
|
end
|
1348
|
-
puts "\n"
|
1349
|
-
end
|
1350
|
-
sleep_with_progress(sleep_delay)
|
1351
|
-
|
1352
2977
|
|
1353
|
-
|
2978
|
+
sleep_with_progress(sleep_delay)
|
2979
|
+
|
2980
|
+
|
2981
|
+
rescue => e
|
1354
2982
|
puts "Error: #{e.message}"
|
1355
|
-
|
1356
|
-
end
|
2983
|
+
end
|
2984
|
+
end
|
1357
2985
|
else
|
1358
2986
|
end
|
1359
2987
|
|
@@ -1500,7 +3128,7 @@ end
|
|
1500
3128
|
# 상태 표시 퍼샌테이지 아래 [7]넘버는 게이지바에 맞게 넘버를 넣어줘야 작동됨
|
1501
3129
|
while true
|
1502
3130
|
for n in 0..@data['table'].length-1
|
1503
|
-
@data['table'][n][
|
3131
|
+
@data['table'][n][8] = 0
|
1504
3132
|
end
|
1505
3133
|
|
1506
3134
|
while true
|
@@ -1513,7 +3141,18 @@ end
|
|
1513
3141
|
next
|
1514
3142
|
end
|
1515
3143
|
|
1516
|
-
|
3144
|
+
if table[4] == true
|
3145
|
+
option['re_coment'] = 'true'
|
3146
|
+
if @data['포스트설정']['전체대댓글'].checked?
|
3147
|
+
|
3148
|
+
elsif @data['포스트설정']['지정대댓글'].checked?
|
3149
|
+
nik_or_number = @data['포스트설정']['nik_or_number'].text.to_s.force_encoding('utf-8')
|
3150
|
+
puts nik_or_number
|
3151
|
+
else
|
3152
|
+
end
|
3153
|
+
else
|
3154
|
+
option['re_coment'] = 'false'
|
3155
|
+
end
|
1517
3156
|
|
1518
3157
|
|
1519
3158
|
option['proxy'] = ''
|
@@ -1525,7 +3164,7 @@ end
|
|
1525
3164
|
end
|
1526
3165
|
end
|
1527
3166
|
|
1528
|
-
if table[
|
3167
|
+
if table[7].to_i > table[8].to_i #시작 부분 설정을 맞게해줘야 실행이 됨
|
1529
3168
|
#if table[6].to_i #시작 부분 설정을 맞게해줘야 실행이 됨
|
1530
3169
|
|
1531
3170
|
if @data['포스트설정']['테더링'].checked?
|
@@ -1860,15 +3499,15 @@ end
|
|
1860
3499
|
# p option
|
1861
3500
|
|
1862
3501
|
# 댓글 설정 수 카운트
|
1863
|
-
counts_number = @data['table'][index][
|
3502
|
+
counts_number = @data['table'][index][6].to_i
|
1864
3503
|
api_key = @data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8')
|
1865
|
-
sleep_delay = @data['table'][index][
|
3504
|
+
sleep_delay = @data['table'][index][5].to_i
|
1866
3505
|
naver.update(content,board_url,nickname,image,option,counts_number,keyword,api_key,sleep_delay)
|
1867
3506
|
|
1868
3507
|
|
1869
3508
|
|
1870
3509
|
#완료했으니 수량 카운터
|
1871
|
-
@data['table'][index][
|
3510
|
+
@data['table'][index][8] = @data['table'][index][8].to_i + 1
|
1872
3511
|
@data['table'][index][-1] = 100
|
1873
3512
|
@data['table'] << []
|
1874
3513
|
@data['table'].pop
|
@@ -2243,8 +3882,8 @@ end
|
|
2243
3882
|
button(' 댓글 등록 ID 추가 '){
|
2244
3883
|
|
2245
3884
|
on_clicked {
|
2246
|
-
@data['table'] << [false, @data['admin_list1'].text,@data['admin_list2'].text,@data['proxy'].text, 1, 2, 1,0,0]
|
2247
|
-
@data['table'] << [false, @data['admin_list1'].text,@data['admin_list2'].text,@data['proxy'].text, 1, 2, 1,0,0]
|
3885
|
+
@data['table'] << [false, @data['admin_list1'].text,@data['admin_list2'].text,@data['proxy'].text,false, 1, 2, 1,0,0]
|
3886
|
+
@data['table'] << [false, @data['admin_list1'].text,@data['admin_list2'].text,@data['proxy'].text,false, 1, 2, 1,0,0]
|
2248
3887
|
@data['table'].pop
|
2249
3888
|
}
|
2250
3889
|
}
|
@@ -2257,8 +3896,8 @@ end
|
|
2257
3896
|
file_data.split("\n").each do |i|
|
2258
3897
|
i3 = i.to_s.force_encoding('utf-8').to_s
|
2259
3898
|
i2 = i3.split(',')
|
2260
|
-
@data['table'] << [false, i2[0].to_s, i2[1].to_s,i2[2].to_s, 1,2,1,0,0]
|
2261
|
-
@data['table'] << [false, i2[0].to_s, i2[1].to_s, 1,2,1,0,0]
|
3899
|
+
@data['table'] << [false, i2[0].to_s, i2[1].to_s,i2[2].to_s,['1', 'true'].include?(i2[3].to_s.strip.downcase), 1,2,1,0,0]
|
3900
|
+
@data['table'] << [false, i2[0].to_s, i2[1].to_s, false, 1,2,1,0,0]
|
2262
3901
|
@data['table'].pop
|
2263
3902
|
end
|
2264
3903
|
end
|
@@ -2284,6 +3923,10 @@ end
|
|
2284
3923
|
text_column('프록시'){
|
2285
3924
|
editable true
|
2286
3925
|
}
|
3926
|
+
|
3927
|
+
checkbox_column('대댓글작업') {
|
3928
|
+
editable true
|
3929
|
+
}
|
2287
3930
|
|
2288
3931
|
text_column('딜레이'){
|
2289
3932
|
editable true
|
@@ -2378,9 +4021,9 @@ end
|
|
2378
4021
|
table_counter_again = @data['table_counter_again'].text.to_i
|
2379
4022
|
# @data['table']의 각 항목을 업데이트
|
2380
4023
|
@data['table'].map! do |row|
|
2381
|
-
row[
|
2382
|
-
row[
|
2383
|
-
row[
|
4024
|
+
row[5] = table_delay_input
|
4025
|
+
row[6] = table_counter_input
|
4026
|
+
row[7] = table_counter_again
|
2384
4027
|
row # 수정된 row를 반환
|
2385
4028
|
end
|
2386
4029
|
}
|
@@ -3172,6 +4815,33 @@ end
|
|
3172
4815
|
end
|
3173
4816
|
}
|
3174
4817
|
}
|
4818
|
+
@data['포스트설정']['전체대댓글'] = checkbox('대 댓글 전체 타겟(옵션1) '){
|
4819
|
+
top 1
|
4820
|
+
left 3
|
4821
|
+
on_toggled{
|
4822
|
+
if @data['포스트설정']['전체대댓글'].checked?
|
4823
|
+
@data['포스트설정']['지정대댓글'].checked = false
|
4824
|
+
end
|
4825
|
+
}
|
4826
|
+
}
|
4827
|
+
@data['포스트설정']['지정대댓글'] = checkbox('대 댓글 지정 타겟(옵션2)'){
|
4828
|
+
top 1
|
4829
|
+
left 4
|
4830
|
+
on_toggled{
|
4831
|
+
if @data['포스트설정']['지정대댓글'].checked?
|
4832
|
+
@data['포스트설정']['전체대댓글'].checked = false
|
4833
|
+
end
|
4834
|
+
}
|
4835
|
+
}
|
4836
|
+
@data['포스트설정']['nik_or_number'] = entry(){
|
4837
|
+
top 1
|
4838
|
+
left 5
|
4839
|
+
text '예)마루 or 예)1(댓글넘버)'
|
4840
|
+
}
|
4841
|
+
label('콤마로 추가 가능 예)마루,강쥐 or 예)1,3'){
|
4842
|
+
top 1
|
4843
|
+
left 6
|
4844
|
+
}
|
3175
4845
|
|
3176
4846
|
}
|
3177
4847
|
}
|