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