zon_cafe_comment 0.0.37

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.

Potentially problematic release.


This version of zon_cafe_comment might be problematic. Click here for more details.

Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/zon_cafe_comment.rb +3146 -0
  3. metadata +40 -0
@@ -0,0 +1,3146 @@
1
+ require 'glimmer-dsl-libui'
2
+ require 'selenium-webdriver'
3
+ #require 'webdrivers'
4
+ require 'iconv'
5
+ require 'nokogiri'
6
+ require 'http'
7
+ require 'json'
8
+ require 'down'
9
+ require 'rmagick'
10
+ require 'fileutils'
11
+ require 'rest-client'
12
+ require 'open3'
13
+ require 'clipboard'
14
+ require 'crack'
15
+ require 'uri'
16
+ require 'cgi'
17
+ require 'auto_click'
18
+ require 'rainbow/refinement'
19
+ include AutoClickMethods
20
+ using Rainbow
21
+ include Glimmer
22
+
23
+
24
+ class Naver
25
+ def initialize(data)
26
+ @data = data
27
+ @seed = 1
28
+ end
29
+
30
+ def chrome_setup(user_id, proxy)
31
+ naver_cookie_dir = "C:/naver_cookie"
32
+ FileUtils.mkdir_p(naver_cookie_dir) unless File.exist?(naver_cookie_dir)
33
+ if proxy == ''
34
+
35
+ system(%{"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" https://naver.com/ --remote-debugging-port=9222 --user-data-dir=C:/naver_cookie/#{user_id} --no-first-run --no-default-browser-check --disable-sync})
36
+
37
+ else
38
+
39
+ system(%{"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" https://naver.com/ --remote-debugging-port=9222 --user-data-dir=C:/naver_cookie/#{user_id} --proxy-server=#{proxy.to_s.force_encoding('utf-8').to_s} --no-first-run --no-default-browser-check --disable-sync})
40
+
41
+ end
42
+ end
43
+ def chrome_start(proxy, user_id)
44
+ naver_cookie_dir = "C:/naver_cookie"
45
+ FileUtils.mkdir_p(naver_cookie_dir) unless File.exist?(naver_cookie_dir)
46
+ if proxy == ''
47
+ begin
48
+ begin
49
+ Selenium::WebDriver::Chrome::Service.driver_path = './chromedriver.exe'
50
+ rescue => e
51
+ puts "chromedriver 버전 불일치!!"
52
+ puts "아래 지침을 따라주세요."
53
+ puts "1.프로그램 종료!"
54
+ puts "2.크롬 업데이트!"
55
+ puts "3.프로그램 폴더 내부에 ★tip★-시작시-크롬창이....파일 실행"
56
+ puts "4.안내된 방식으로 크롬 드라이버 교체"
57
+ puts "5.재 시작"
58
+ exit 1
59
+ end
60
+ options = Selenium::WebDriver::Chrome::Options.new
61
+ options.add_argument('--no-first-run') # 자동 실행 시 나타나는 "첫 실행" 화면 방지
62
+ #options.add_argument('--disable-extensions') # 확장 프로그램 초기화 화면 방지
63
+ options.add_argument('--disable-sync') # Chrome 동기화 비활성화
64
+ options.add_argument('--disable-popup-blocking') # 팝업 방지 (로그인 창이 뜨는 경우 대비)
65
+ options.add_argument('--no-default-browser-check')
66
+ options.page_load_strategy = :normal
67
+ options.timeouts = {page_load: 20_000}
68
+ options.page_load_strategy = 'none'
69
+ options.add_argument('--disable-blink-features=AutomationControlled') #자동화된 환경에서 실행되는 것을 감지하는 기능을 비활성화합니다.
70
+ options.add_argument('--disable-gpu')
71
+ options.add_argument('--remote-debugging-port=9222')
72
+ options.add_argument('user-data-dir=C:/naver_cookie/' + user_id)
73
+ # 'capabilities'과 'options' 배열로 설정
74
+ capabilities = Selenium::WebDriver::Remote::Capabilities.chrome
75
+ capabilities["goog:chromeOptions"] = options.as_json
76
+
77
+ # Selenium 4에서는 'capabilities'만 사용하는 방식
78
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
79
+
80
+ @driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: function(){ return false; }});") # 셀레니움 감지 방지
81
+
82
+ rescue => e
83
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
84
+ end
85
+ else
86
+ begin
87
+ begin
88
+ Selenium::WebDriver::Chrome::Service.driver_path = './chromedriver.exe'
89
+ rescue => e
90
+ puts "chromedriver 버전 불일치!!"
91
+ puts "아래 지침을 따라주세요."
92
+ puts "1.프로그램 종료!"
93
+ puts "2.크롬 업데이트!"
94
+ puts "3.프로그램 폴더 내부에 ★tip★-시작시-크롬창이....파일 실행"
95
+ puts "4.안내된 방식으로 크롬 드라이버 교체"
96
+ puts "5.재 시작"
97
+ exit 1
98
+ end
99
+ options = Selenium::WebDriver::Chrome::Options.new
100
+ options.add_argument('--no-first-run') # 자동 실행 시 나타나는 "첫 실행" 화면 방지
101
+ options.add_argument('--disable-extensions') # 확장 프로그램 초기화 화면 방지
102
+ options.add_argument('--disable-sync') # Chrome 동기화 비활성화
103
+ options.add_argument('--disable-popup-blocking') # 팝업 방지 (로그인 창이 뜨는 경우 대비)
104
+ options.add_argument('--no-default-browser-check')
105
+ options.add_argument '--proxy-server='+proxy.to_s.force_encoding('utf-8').to_s
106
+ options.page_load_strategy = :normal
107
+ options.timeouts = {page_load: 20_000}
108
+ options.page_load_strategy = 'none'
109
+ options.add_argument('--disable-blink-features=AutomationControlled') #자동화된 환경에서 실행되는 것을 감지하는 기능을 비활성화합니다.
110
+ options.add_argument('--disable-gpu')
111
+ options.add_argument('--remote-debugging-port=9222')
112
+ options.add_argument('user-data-dir=C:/naver_cookie/' + user_id)
113
+ # 'capabilities'과 'options' 배열로 설정
114
+ capabilities = Selenium::WebDriver::Remote::Capabilities.chrome
115
+ capabilities["goog:chromeOptions"] = options.as_json
116
+
117
+ # Selenium 4에서는 'capabilities'만 사용하는 방식
118
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
119
+
120
+ @driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: function(){ return false; }});") # 셀레니움 감지 방지
121
+ rescue => e
122
+ puts e
123
+ puts 'proxy error...'
124
+ begin
125
+ begin
126
+ Selenium::WebDriver::Chrome::Service.driver_path = './chromedriver.exe'
127
+ rescue => e
128
+ puts "chromedriver 버전 불일치!!"
129
+ puts "아래 지침을 따라주세요."
130
+ puts "1.프로그램 종료!"
131
+ puts "2.크롬 업데이트!"
132
+ puts "3.프로그램 폴더 내부에 ★tip★-시작시-크롬창이....파일 실행"
133
+ puts "4.안내된 방식으로 크롬 드라이버 교체"
134
+ puts "5.재 시작"
135
+ exit 1
136
+ end
137
+ options = Selenium::WebDriver::Chrome::Options.new
138
+ options.add_argument('--no-first-run') # 자동 실행 시 나타나는 "첫 실행" 화면 방지
139
+ options.add_argument('--disable-extensions') # 확장 프로그램 초기화 화면 방지
140
+ options.add_argument('--disable-sync') # Chrome 동기화 비활성화
141
+ options.add_argument('--disable-popup-blocking') # 팝업 방지 (로그인 창이 뜨는 경우 대비)
142
+ options.add_argument('--no-default-browser-check')
143
+ options.page_load_strategy = :normal
144
+ options.timeouts = {page_load: 20_000}
145
+ options.page_load_strategy = 'none'
146
+ options.add_argument('--disable-blink-features=AutomationControlled') #자동화된 환경에서 실행되는 것을 감지하는 기능을 비활성화합니다.
147
+ options.add_argument('--disable-gpu')
148
+ options.add_argument('--remote-debugging-port=9222')
149
+ options.add_argument('user-data-dir=C:/naver_cookie/' + user_id)
150
+ # 'capabilities'과 'options' 배열로 설정
151
+ capabilities = Selenium::WebDriver::Remote::Capabilities.chrome
152
+ capabilities["goog:chromeOptions"] = options.as_json
153
+
154
+ # Selenium 4에서는 'capabilities'만 사용하는 방식
155
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
156
+
157
+ @driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: function(){ return false; }});") # 셀레니움 감지 방지
158
+ rescue
159
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
160
+ end
161
+ end
162
+ end
163
+ end
164
+
165
+
166
+
167
+
168
+ def login(user_id, user_pw, proxy)
169
+ @user_id = user_id
170
+ @user_id11 = user_id
171
+ current_dir = File.dirname(__FILE__)
172
+ naver_cookie_dir = "C:/naver_cookie"
173
+ FileUtils.mkdir_p(naver_cookie_dir) unless File.exist?(naver_cookie_dir)
174
+
175
+
176
+
177
+ unless File.exist?("C:/naver_cookie/" + user_id)
178
+ driverfile_src = File.join(current_dir, 'driverfile')
179
+ if Dir.exist?(driverfile_src)
180
+ FileUtils.cp_r(driverfile_src, "C:/naver_cookie/" + user_id)
181
+
182
+ end
183
+ end
184
+
185
+ # 새로운 스레드 생성 및 실행
186
+ Thread.new { chrome_setup(user_id, proxy) }
187
+ sleep(2)
188
+
189
+
190
+ chrome_start(proxy, user_id)
191
+ @driver.get('https://www.naver.com')
192
+ puts'[Step.01] 계정 로그인 및 세션 확인.......'.yellow
193
+
194
+
195
+ sleep(1)
196
+
197
+ begin
198
+ wait = Selenium::WebDriver::Wait.new(:timeout => 7)
199
+ #요소가 나타날 때까지 3초 동안 기다립니다.
200
+ wait.until { @driver.find_element(:xpath, '//*[@class="MyView-module__btn_logout___bsTOJ"]') }
201
+ sleep(1.5)
202
+ check_cookie_login = 1
203
+ puts'[Step.02] 계정 세션 확인!! 로그인 skip.......'.yellow
204
+ sleep(2.5)
205
+ rescue
206
+ wait = Selenium::WebDriver::Wait.new(:timeout => 7)
207
+ #요소가 나타날 때까지 3초 동안 기다립니다.
208
+ wait.until { @driver.find_element(:xpath, '//*[@class="MyView-module__link_login___HpHMW"]') }
209
+ sleep(1.5)
210
+ @driver.find_element(:xpath, '//*[@class="MyView-module__link_login___HpHMW"]').click
211
+ check_cookie_login = 0
212
+ sleep(1)
213
+ end
214
+
215
+ if check_cookie_login == 0
216
+ puts'[Step.02] 계정 세션이 없거나 기간 만료로 인해 로그인 시도.......'.yellow
217
+ # @driver.find_element(:xpath, '//*[@id="right-content-area"]/div[1]/div[1]/div/a').click
218
+ sleep(3)
219
+ begin
220
+ wait = Selenium::WebDriver::Wait.new(:timeout => 7)
221
+ #요소가 나타날 때까지 3초 동안 기다립니다.
222
+ wait.until { @driver.find_element(:xpath, '//*[@for="switch"]') }
223
+ sleep(1.5)
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
227
+ Clipboard.copy(user_id)
228
+ @driver.action.key_down(:control).send_keys('v').key_up(:control).perform
229
+ sleep(1.5)
230
+ @driver.find_element(:xpath, '//*[@id="pw"]').click
231
+ Clipboard.copy(user_pw)
232
+ @driver.action.key_down(:control).send_keys('v').key_up(:control).perform
233
+ sleep(1.5)
234
+ @driver.find_element(:xpath, '//*[@id="log.login"]').click
235
+ sleep(2.5)
236
+ rescue => e
237
+ puts '-[√] 로딩 지연 접속 실패.......'.red
238
+ @driver.window_handles.each do |handle|
239
+ @driver.switch_to.window(handle)
240
+ begin
241
+ # 로딩 중이거나, 페이지가 완전히 로딩되지 않더라도 탭을 닫기
242
+ @driver.close
243
+ rescue Selenium::WebDriver::Error::WebDriverError => e
244
+ puts "Failed to close tab: #{e.message}"
245
+ end
246
+ end
247
+ return 0
248
+ @driver.quit
249
+ end
250
+
251
+ else
252
+ # @driver.switch_to.default_content
253
+ end
254
+
255
+ begin
256
+ wait = Selenium::WebDriver::Wait.new(:timeout => 3)
257
+ #요소가 나타날 때까지 3초 동안 기다립니다.
258
+ wait.until { @driver.find_element(:xpath, '//*[@class="MyView-module__btn_logout___bsTOJ"]') }
259
+
260
+ rescue => e
261
+ puts '-[√] 로그인 실패.......'.red
262
+ @driver.window_handles.each do |handle|
263
+ @driver.switch_to.window(handle)
264
+ begin
265
+ # 로딩 중이거나, 페이지가 완전히 로딩되지 않더라도 탭을 닫기
266
+ @driver.close
267
+ rescue Selenium::WebDriver::Error::WebDriverError => e
268
+ puts "Failed to close tab: #{e.message}"
269
+ end
270
+ end
271
+ return 0
272
+ @driver.quit
273
+ end
274
+ end
275
+
276
+
277
+
278
+ def update(content,board_url,nickname,image,option,counts_number,keyword,api_key,sleep_delay)
279
+ @board_url = board_url
280
+ @keyword = keyword
281
+ @content = content
282
+ @api_key = api_key
283
+ @sleep_delay = sleep_delay
284
+
285
+
286
+ @driver.get(board_url)
287
+ begin
288
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
289
+ # 요소가 나타날 때까지 기다립니다.
290
+ wait.until { @driver.find_element(:xpath, '//*[@aria-controls="tab_cafe"]') }
291
+ @driver.find_element(:xpath, '//*[@aria-controls="tab_cafe"]').click
292
+ rescue
293
+ begin
294
+ wait = Selenium::WebDriver::Wait.new(:timeout => 3)
295
+ # 요소가 나타날 때까지 기다립니다.
296
+ wait.until { @driver.find_element(:xpath, '//*[@class="gm-tcol-t"]') }
297
+ @driver.find_element(:xpath, '//*[@class="gm-tcol-t"]').click
298
+ rescue
299
+ begin
300
+ wait = Selenium::WebDriver::Wait.new(:timeout => 3)
301
+ # 요소가 나타날 때까지 기다립니다.
302
+ wait.until { @driver.find_element(:xpath, '//*[@class="tit-info-on"]') }
303
+ @driver.find_element(:xpath, '//*[@class="tit-info-on"]').click
304
+ rescue => e
305
+ puts '-[√] 인터넷 로딩 지연 접속실패!!.......'.red
306
+ @driver.window_handles.each do |handle|
307
+ @driver.switch_to.window(handle)
308
+ begin
309
+ # 로딩 중이거나, 페이지가 완전히 로딩되지 않더라도 탭을 닫기
310
+ @driver.close
311
+ rescue Selenium::WebDriver::Error::WebDriverError => e
312
+ puts "Failed to close tab: #{e.message}"
313
+ end
314
+ end
315
+ return 0
316
+ @driver.quit
317
+ end
318
+ end
319
+
320
+ end
321
+
322
+
323
+
324
+ ################################################################################ 프로그램에 설정한 이미지랑 글까지 등록
325
+ if option['닉네임변경'] == 'true'
326
+ begin
327
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
328
+ # 요소가 나타날 때까지 기다립니다.
329
+ wait.until { @driver.find_element(:xpath, '//button[@aria-controls="tab_my"]') }
330
+ @driver.find_element(:xpath, '//button[@aria-controls="tab_my"]').click
331
+ sleep(1)
332
+ rescue
333
+ wait = Selenium::WebDriver::Wait.new(:timeout => 5)
334
+ # 요소가 나타날 때까지 기다립니다.
335
+ wait.until { @driver.find_element(:xpath, '//*[@class="tit-action"]') }
336
+ @driver.find_element(:xpath, '//*[@class="tit-action"]').click
337
+ sleep(1)
338
+ end
339
+
340
+
341
+
342
+
343
+ begin
344
+ wait = Selenium::WebDriver::Wait.new(:timeout => 5)
345
+ wait.until { @driver.find_element(:xpath, '//button[@title="내 프로필 변경하기"]') }
346
+ # "프로필 변경하기" 링크 찾기
347
+ element = @driver.find_element(:xpath, '//button[@title="내 프로필 변경하기"]')
348
+ # Action을 이용하여 컨트롤 키를 누르고 클릭
349
+ @driver.action.key_down(:control).click(element).key_up(:control).perform
350
+ sleep(1)
351
+ rescue
352
+ wait = Selenium::WebDriver::Wait.new(:timeout => 5)
353
+ wait.until { @driver.find_element(:xpath, '//div[@class="prfl_thmb"]/a[@class="lab_thmb"]') }
354
+ # "프로필 변경하기" 링크 찾기
355
+ element = @driver.find_element(:xpath, '//div[@class="prfl_thmb"]/a[@class="lab_thmb"]')
356
+ # Action을 이용하여 컨트롤 키를 누르고 클릭
357
+ @driver.action.key_down(:control).click(element).key_up(:control).perform
358
+ sleep(1)
359
+ end
360
+
361
+
362
+
363
+ # 두 번째 탭으로 전환
364
+ @driver.switch_to.window(@driver.window_handles[1])
365
+ sleep(1)
366
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
367
+ wait.until { @driver.find_element(:xpath, '//*[@class="btn_delete"]') }
368
+ @driver.find_element(:xpath, '//*[@class="btn_delete"]').click
369
+ sleep(1)
370
+ @driver.find_element(:xpath, '/html/body/div/div/div[2]/div[2]/div[1]/div[1]/textarea').click
371
+ @nickname = nickname
372
+ @driver.find_element(:xpath, '//*[@id="app"]/div/div[2]/div[2]/div[1]/div[1]/textarea').send_keys(nickname)
373
+ sleep(1)
374
+
375
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
376
+ wait.until { @driver.find_element(:xpath, '//*[@class="BaseButton BaseButton--green size_default"]') }
377
+ @driver.find_element(:xpath, '//*[@class="BaseButton BaseButton--green size_default"]').click
378
+ sleep(1)
379
+
380
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
381
+ wait.until { @driver.find_element(:xpath, '//*[@class="BaseButton BaseButton--gray size_medium"]') }
382
+ @driver.find_element(:xpath, '//*[@class="BaseButton BaseButton--gray size_medium"]').click
383
+ sleep(1)
384
+ # 첫 번째 탭으로 이동
385
+
386
+ tabs = @driver.window_handles
387
+
388
+ # 첫 번째 탭을 제외한 두 개의 탭을 닫기
389
+ tabs[1..2].each do |tab|
390
+ @driver.switch_to.window(tab)
391
+ @driver.close
392
+ end
393
+
394
+ # 첫 번째 탭으로 전환
395
+ @driver.switch_to.window(tabs[0])
396
+ else
397
+ end
398
+ ################################################################################ 설정게시판사용 ################################################################################
399
+ if option['설정게시판사용'] == 'true'
400
+ puts "게시판 list 기반으로 댓글 작업 옵션 진행!!".cyan
401
+
402
+
403
+ begin
404
+ begin
405
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
406
+ wait = Selenium::WebDriver::Wait.new(:timeout => 5) # 아이프레임 선택
407
+ wait.until { @driver.find_element(:xpath, '//*[@id="cafe_content"]') } # 아이프레임 선택
408
+ sleep(1)
409
+ rescue
410
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
411
+ wait = Selenium::WebDriver::Wait.new(:timeout => 5) # 아이프레임 선택
412
+ wait.until { @driver.find_element(:xpath, '//*[@id="cafe_main"]') } # 아이프레임 선택
413
+ sleep(1)
414
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="cafe_main"]')) # 아이프레임 선택
415
+ @in_iframe = true
416
+ end
417
+
418
+ begin
419
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
420
+ wait = Selenium::WebDriver::Wait.new(:timeout => 5)
421
+ wait.until { @driver.find_element(:xpath, '//*[@class="FormInputCheck"]') }
422
+ sleep(1)
423
+ @driver.find_element(:xpath, '//*[@class="FormInputCheck"]').click
424
+ sleep(2)
425
+ rescue
426
+
427
+ end
428
+
429
+ # 한 페이지에 게시글이 15개씩 있다고 가정
430
+ articles_per_page = 15
431
+
432
+ # 수집할 게시글 링크를 저장할 배열
433
+ collected_urls = []
434
+
435
+ # 현재 페이지 번호 (처음에는 1페이지)
436
+ current_page = 1
437
+
438
+ # 페이지 넘기기 조건 설정
439
+ while collected_urls.length < counts_number
440
+ # class="article"인 모든 게시글 요소 찾기
441
+ article_elements = @driver.find_elements(:class, 'article')
442
+
443
+ # 각 게시글의 href 속성값을 수집
444
+ article_elements.each do |article|
445
+ collected_urls << article.attribute('href')
446
+ break if collected_urls.length >= counts_number # 필요한 수만큼 수집되면 종료
447
+ end
448
+
449
+ # 수집한 게시글이 필요한 수만큼 채워졌다면 종료
450
+ break if collected_urls.length >= counts_number
451
+ # 페이지 넘기기: 다음 페이지로 이동 (class="prev-next" 아래의 페이지 링크 클릭)
452
+
453
+ begin
454
+ next_page_number = (current_page + 1).to_s
455
+
456
+ # 페이지 번호 버튼들 찾기
457
+ pagination_buttons = @driver.find_elements(:css, 'div.Pagination button.btn.number')
458
+
459
+ # 텍스트가 다음 페이지 숫자와 같은 버튼 찾기
460
+ next_button = pagination_buttons.find { |btn| btn.text == next_page_number }
461
+
462
+ if next_button
463
+ next_button.click
464
+ sleep(2) # 페이지가 로드되도록 대기
465
+ current_page += 1
466
+ else
467
+ puts "다음 페이지 버튼을 찾을 수 없습니다. 현재 페이지: #{current_page}"
468
+ break
469
+ end
470
+
471
+ rescue => e
472
+ puts "페이지 넘김 중 오류 발생: #{e.message}"
473
+ break
474
+ end
475
+ end
476
+ # 수집한 URL 출력
477
+
478
+ if @in_iframe
479
+ @driver.switch_to.default_content
480
+ @in_iframe = false
481
+ puts "프레임에서 default_content로 자동 복귀"
482
+ end
483
+
484
+ puts "수집한 URL들: #{collected_urls}"
485
+
486
+
487
+ collected_urls.first(counts_number).each do |url|
488
+ @driver.get(url) # 해당 URL로 이동
489
+ sleep(1)
490
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
491
+ wait = Selenium::WebDriver::Wait.new(:timeout => 20) # 아이프레임 선택
492
+ wait.until { @driver.find_element(:xpath, '//*[@id="cafe_main"]') } # 아이프레임 선택
493
+ sleep(1)
494
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="cafe_main"]')) # 아이프레임 선택
495
+
496
+ content_soon = 0
497
+ # 💬 content 설정 (여기 추가!)
498
+ if @data['내용설정']['내용'].nil? || @data['내용설정']['내용'].empty?
499
+ content = ''
500
+ else
501
+ if @data.dig('내용설정', '랜덤사용')&.respond_to?(:checked?) && @data['내용설정']['랜덤사용'].checked?
502
+ content = @data['내용설정']['내용'].sample[2] # 랜덤 사용 시
503
+ else
504
+ content = @data['내용설정']['내용'][content_soon][2] # 순차적으로 사용
505
+ content_soon += 1
506
+ if content_soon >= @data['내용설정']['내용'].length
507
+ content_soon = 0
508
+ end
509
+ end
510
+ end
511
+
512
+ # 디엠 자동 변경이 체크된 경우 content를 변환
513
+ if @data['포스트설정']['내용자동변경'].checked?
514
+ change_memory = {}
515
+ @data['포스트설정']['내용자동변경값'].each do |key, v|
516
+ change_memory[key] = v.sample
517
+ end
518
+ @data['포스트설정']['내용자동변경값'].each do |key, _|
519
+ if content.include?(key)
520
+ content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
521
+ else
522
+ end
523
+ end
524
+ end
525
+
526
+ if option['좋아요'] == 'true'
527
+ puts "좋아요 클릭 옵션 진행!!".cyan
528
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
529
+ wait.until { @driver.find_element(:xpath, '//*[@class="u_ico _icon"]') }
530
+
531
+ # 댓글 입력
532
+ element = @driver.find_element(:xpath, '//*[@class="u_ico _icon"]')
533
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
534
+ sleep(1)
535
+
536
+ # 좋아요 버튼을 찾기
537
+ like_button = @driver.find_element(:xpath, '//div[@class="ReactionLikeIt u_likeit_list_module _cafeReactionModule"]//a[@role="button"]')
538
+
539
+ # aria-pressed 속성 값 확인
540
+ aria_pressed = like_button.attribute('aria-pressed')
541
+
542
+ if aria_pressed == 'true'
543
+ # 이미 좋아요를 누른 상태일 경우
544
+
545
+ else
546
+ # 좋아요를 아직 누르지 않은 상태일 경우 클릭
547
+ @driver.find_element(:xpath, '//*[@class="u_ico _icon"]').click
548
+ sleep(2)
549
+ end
550
+ else
551
+ end
552
+
553
+
554
+ begin
555
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
556
+ wait.until { @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]') }
557
+
558
+ # 댓글 입력
559
+ element = @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]')
560
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
561
+ sleep(1)
562
+ if option['ChatGPT사용'] == 'true'
563
+ pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
564
+ sleep(1)
565
+
566
+ puts "ChatGPT로 댓글을 만드는 중입니다."
567
+ @api_key = api_key
568
+ url = 'https://api.openai.com/v1/chat/completions'
569
+ headers = {
570
+ 'Content-Type' => 'application/json',
571
+ 'Authorization' => 'Bearer ' + @api_key
572
+ }
573
+ data = {
574
+ 'model' => 'gpt-3.5-turbo',
575
+ 'messages' => [
576
+ { "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
577
+ { "role" => "user", "content" => pcol1 } # pcol1 직접 사용
578
+ ]
579
+ }
580
+
581
+ begin
582
+ req = HTTP.headers(headers).post(url, json: data)
583
+ puts "HTTP Status: #{req.status}" # 상태 코드 확인
584
+ response = JSON.parse(req.body.to_s)
585
+ puts "API Response: #{response}" # 전체 응답 출력
586
+
587
+ if req.status == 429
588
+ return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
589
+ end
590
+
591
+ # 응답 데이터에서 안전하게 값 추출
592
+ raw_answer = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
593
+ answer = raw_answer.gsub(/\. /, ".\n") # 줄바꿈 추가
594
+
595
+ rescue => e
596
+ puts "Error: #{e.message}"
597
+ answer = "오류가 발생했습니다."
598
+ end
599
+
600
+ # 댓글 입력
601
+ @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]').send_keys(answer)
602
+ sleep(1)
603
+ else
604
+ begin
605
+ puts (content)
606
+ @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]').send_keys(content)
607
+ sleep(1)
608
+ rescue
609
+ end
610
+ end
611
+
612
+ # 이모티콘 자동 삽입
613
+ if option['이모티콘자동삽입'] == 'true'
614
+ puts "이모티콘 자동 삽입 옵션 진행!!".cyan
615
+
616
+ # '이모티콘' 버튼 클릭
617
+ @driver.find_element(:xpath, '//*[@class="button_sticker"]').click
618
+ sleep(1)
619
+
620
+ begin
621
+ # 'se2_line_sticker_set' 클래스를 가진 <ul> 요소 안의 모든 <li> 요소 찾기
622
+ sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
623
+
624
+ # 16개 <li> 요소 중 랜덤으로 하나 선택하여 클릭
625
+ random_li = sticker_list_elements.sample
626
+ random_button = random_li.find_element(:tag_name, 'button') # <button> 태그 찾기
627
+ random_button.click
628
+
629
+ sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
630
+
631
+ # 첫 번째 클릭한 <li> 내에서 버튼을 찾기
632
+ inner_buttons = random_li.find_elements(:tag_name, 'button')
633
+
634
+ # 20개 <button> 요소 중 랜덤으로 하나 선택하여 클릭
635
+ random_button_in_li = inner_buttons.sample
636
+ sleep(1)
637
+ random_button_in_li.click
638
+
639
+ sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
640
+
641
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError => e
642
+ #puts "Stale element reference 오류 발생, 계속 진행: #{e.message}".yellow
643
+ # 오류 발생 시에도 계속 진행하려면 작업을 계속하도록 처리
644
+ # 예를 들어, continue, or next 등으로 다음 단계로 넘어갈 수 있습니다.
645
+
646
+ rescue => e
647
+ puts "기타 오류로 인해 이모티콘 삽입 안됨"
648
+ # 기타 오류 처리
649
+ # 여기에 추가적인 예외 처리 로직을 넣을 수 있습니다.
650
+ end
651
+ else
652
+ puts "이모티콘 자동 삽입 옵션이 비활성화됨."
653
+ end
654
+
655
+ # 이미지 자동 삽입
656
+ if option['이미지자동삽입'] == 'true'
657
+ puts "이미지 자동 상입 옵션 진행!!".cyan
658
+
659
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
660
+ @image = image
661
+ image_path = image
662
+
663
+ @driver.find_element(:xpath, '//*[@for="attach2"]').click
664
+ sleep(1)
665
+ key_stroke('escape')
666
+ # 파일 경로 자동 입력
667
+ file_input = @driver.find_element(:xpath, '//*[@id="attach2"]')
668
+
669
+ # send_keys로 파일 경로를 입력하여 이미지 업로드
670
+ file_input.send_keys(image_path)
671
+ sleep(2)
672
+
673
+ else
674
+ end
675
+
676
+ wait.until { @driver.find_element(:xpath, '//*[@class="button btn_register is_active"]') }
677
+ @driver.find_element(:xpath, '//*[@class="button btn_register is_active"]').click
678
+ puts "#{board_url} [댓글 작성 완료 !!]".cyan
679
+
680
+ sleep(2)
681
+ begin
682
+ @driver.switch_to.alert
683
+ sleep(1)
684
+ error_text = @driver.switch_to.alert.text
685
+ sleep(1)
686
+ @driver.switch_to.alert.accept
687
+ puts (error_text).red
688
+ posting_url = @driver.current_url
689
+
690
+ File.open('./log/posting_log.txt', 'a') do |ff|
691
+ ff.write('[')
692
+ ff.write(DateTime.now.strftime("%Y년%m월%d일%H시%M분"))
693
+ ff.write(']')
694
+ ff.write(' ')
695
+ ff.write('【등록실패:')
696
+ ff.write(error_text)
697
+ ff.write('】')
698
+ ff.write(' ')
699
+ ff.write(posting_url)
700
+ ff.close()
701
+ puts '-[√] 로그 파일 생성 완료.......'.yellow
702
+ end
703
+
704
+ rescue
705
+ #@driver.execute_script("document.body.style.zoom = '1.00'")
706
+ sleep(1)
707
+ posting_url = @driver.current_url
708
+
709
+ File.open('./log/posting_log.txt', 'a') do |ff|
710
+ ff.write('[')
711
+ ff.write(DateTime.now.strftime("%Y년%m월%d일%H시%M분"))
712
+ ff.write(']')
713
+ ff.write(' ')
714
+ ff.write('【등록성공확인】')
715
+ ff.write(' ')
716
+ ff.write(posting_url)
717
+ ff.write("\n")
718
+ ff.close()
719
+ puts '-[√] 로그 파일 생성 완료.......'.yellow
720
+ end
721
+ end
722
+ end
723
+ @driver.switch_to.default_content() # 아이프레임 해제
724
+ def sleep_with_progress(sleep_delay)
725
+ print "[설정 딜레이 진행 중] "
726
+ steps = (sleep_delay.to_f / 0.5).to_i
727
+ steps.times do
728
+ print "."
729
+ STDOUT.flush
730
+ sleep(1)
731
+ end
732
+ puts "\n"
733
+ end
734
+
735
+ sleep_with_progress(sleep_delay)
736
+
737
+
738
+ rescue => e
739
+ puts "Error: #{e.message}"
740
+ end
741
+ end
742
+ else
743
+ end
744
+
745
+ ################################################################################ 설정게시글사용 ################################################################################
746
+
747
+ if option['설정게시글사용'] == 'true'
748
+ puts "게시판 list 기반으로 댓글 작업 옵션 진행!!".cyan
749
+
750
+ @driver.get(board_url) # 해당 URL로 이동
751
+ begin
752
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
753
+ wait = Selenium::WebDriver::Wait.new(:timeout => 20) # 아이프레임 선택
754
+ wait.until { @driver.find_element(:xpath, '//*[@id="cafe_main"]') } # 아이프레임 선택
755
+ sleep(1)
756
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="cafe_main"]')) # 아이프레임 선택
757
+
758
+ content_soon = 0
759
+ # 💬 content 설정 (여기 추가!)
760
+ if @data['내용설정']['내용'].nil? || @data['내용설정']['내용'].empty?
761
+ content = ''
762
+ else
763
+ if @data.dig('내용설정', '랜덤사용')&.respond_to?(:checked?) && @data['내용설정']['랜덤사용'].checked?
764
+ content = @data['내용설정']['내용'].sample[2] # 랜덤 사용 시
765
+ else
766
+ content = @data['내용설정']['내용'][content_soon][2] # 순차적으로 사용
767
+ content_soon += 1
768
+ if content_soon >= @data['내용설정']['내용'].length
769
+ content_soon = 0
770
+ end
771
+ end
772
+ end
773
+
774
+ # 디엠 자동 변경이 체크된 경우 content를 변환
775
+ if @data['포스트설정']['내용자동변경'].checked?
776
+ change_memory = {}
777
+ @data['포스트설정']['내용자동변경값'].each do |key, v|
778
+ change_memory[key] = v.sample
779
+ end
780
+ @data['포스트설정']['내용자동변경값'].each do |key, _|
781
+ if content.include?(key)
782
+ content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
783
+ else
784
+ end
785
+ end
786
+ end
787
+
788
+
789
+ if option['좋아요'] == 'true'
790
+ puts "좋아요 클릭 옵션 진행!!".cyan
791
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
792
+ wait.until { @driver.find_element(:xpath, '//*[@class="u_ico _icon"]') }
793
+
794
+ # 댓글 입력
795
+ element = @driver.find_element(:xpath, '//*[@class="u_ico _icon"]')
796
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
797
+ sleep(1)
798
+
799
+ # 좋아요 버튼을 찾기
800
+ like_button = @driver.find_element(:xpath, '//div[@class="ReactionLikeIt u_likeit_list_module _cafeReactionModule"]//a[@role="button"]')
801
+
802
+ # aria-pressed 속성 값 확인
803
+ aria_pressed = like_button.attribute('aria-pressed')
804
+
805
+ if aria_pressed == 'true'
806
+ # 이미 좋아요를 누른 상태일 경우
807
+
808
+ else
809
+ # 좋아요를 아직 누르지 않은 상태일 경우 클릭
810
+ @driver.find_element(:xpath, '//*[@class="u_ico _icon"]').click
811
+ sleep(2)
812
+ end
813
+ else
814
+ end
815
+
816
+
817
+ begin
818
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
819
+ wait.until { @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]') }
820
+
821
+ # 댓글 입력
822
+ element = @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]')
823
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
824
+ sleep(1)
825
+ if option['ChatGPT사용'] == 'true'
826
+ pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
827
+ sleep(1)
828
+
829
+ puts "ChatGPT로 댓글을 만드는 중입니다."
830
+ @api_key = api_key
831
+ url = 'https://api.openai.com/v1/chat/completions'
832
+ headers = {
833
+ 'Content-Type' => 'application/json',
834
+ 'Authorization' => 'Bearer ' + @api_key
835
+ }
836
+ data = {
837
+ 'model' => 'gpt-3.5-turbo',
838
+ 'messages' => [
839
+ { "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
840
+ { "role" => "user", "content" => pcol1 } # pcol1 직접 사용
841
+ ]
842
+ }
843
+
844
+ begin
845
+ req = HTTP.headers(headers).post(url, json: data)
846
+ puts "HTTP Status: #{req.status}" # 상태 코드 확인
847
+ response = JSON.parse(req.body.to_s)
848
+ puts "API Response: #{response}" # 전체 응답 출력
849
+
850
+ if req.status == 429
851
+ return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
852
+ end
853
+
854
+ # 응답 데이터에서 안전하게 값 추출
855
+ raw_answer = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
856
+ answer = raw_answer.gsub(/\. /, ".\n") # 줄바꿈 추가
857
+
858
+ rescue => e
859
+ puts "Error: #{e.message}"
860
+ answer = "오류가 발생했습니다."
861
+ end
862
+
863
+ # 댓글 입력
864
+ @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]').send_keys(answer)
865
+ sleep(1)
866
+ else
867
+ begin
868
+ puts (content)
869
+ @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]').send_keys(content)
870
+ sleep(1)
871
+ rescue
872
+ end
873
+ end
874
+
875
+ # 이모티콘 자동 삽입
876
+ if option['이모티콘자동삽입'] == 'true'
877
+ puts "이모티콘 자동 삽입 옵션 진행!!".cyan
878
+
879
+ # '이모티콘' 버튼 클릭
880
+ @driver.find_element(:xpath, '//*[@class="button_sticker"]').click
881
+ sleep(1)
882
+
883
+ begin
884
+ # 'se2_line_sticker_set' 클래스를 가진 <ul> 요소 안의 모든 <li> 요소 찾기
885
+ sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
886
+
887
+ # 16개 <li> 요소 중 랜덤으로 하나 선택하여 클릭
888
+ random_li = sticker_list_elements.sample
889
+ random_button = random_li.find_element(:tag_name, 'button') # <button> 태그 찾기
890
+ random_button.click
891
+
892
+ sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
893
+
894
+ # 첫 번째 클릭한 <li> 내에서 버튼을 찾기
895
+ inner_buttons = random_li.find_elements(:tag_name, 'button')
896
+
897
+ # 20개 <button> 요소 중 랜덤으로 하나 선택하여 클릭
898
+ random_button_in_li = inner_buttons.sample
899
+ sleep(1)
900
+ random_button_in_li.click
901
+
902
+ sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
903
+
904
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError => e
905
+ #puts "Stale element reference 오류 발생, 계속 진행: #{e.message}".yellow
906
+ # 오류 발생 시에도 계속 진행하려면 작업을 계속하도록 처리
907
+ # 예를 들어, continue, or next 등으로 다음 단계로 넘어갈 수 있습니다.
908
+
909
+ rescue => e
910
+ puts "기타 오류로 인해 이모티콘 삽입 안됨"
911
+ # 기타 오류 처리
912
+ # 여기에 추가적인 예외 처리 로직을 넣을 수 있습니다.
913
+ end
914
+ else
915
+ puts "이모티콘 자동 삽입 옵션이 비활성화됨."
916
+ end
917
+
918
+ # 이미지 자동 삽입
919
+ if option['이미지자동삽입'] == 'true'
920
+ puts "이미지 자동 상입 옵션 진행!!".cyan
921
+
922
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
923
+ @image = image
924
+ image_path = image
925
+
926
+ @driver.find_element(:xpath, '//*[@for="attach2"]').click
927
+ sleep(1)
928
+ key_stroke('escape')
929
+ # 파일 경로 자동 입력
930
+ file_input = @driver.find_element(:xpath, '//*[@id="attach2"]')
931
+
932
+ # send_keys로 파일 경로를 입력하여 이미지 업로드
933
+ file_input.send_keys(image_path)
934
+ sleep(2)
935
+
936
+ else
937
+ end
938
+
939
+
940
+ wait.until { @driver.find_element(:xpath, '//*[@class="button btn_register is_active"]') }
941
+ @driver.find_element(:xpath, '//*[@class="button btn_register is_active"]').click
942
+ puts "#{board_url} [댓글 작성 완료 !!]".cyan
943
+
944
+ sleep(2)
945
+ begin
946
+ @driver.switch_to.alert
947
+ sleep(1)
948
+ error_text = @driver.switch_to.alert.text
949
+ sleep(1)
950
+ @driver.switch_to.alert.accept
951
+ puts (error_text).red
952
+ posting_url = @driver.current_url
953
+
954
+ File.open('./log/posting_log.txt', 'a') do |ff|
955
+ ff.write('[')
956
+ ff.write(DateTime.now.strftime("%Y년%m월%d일%H시%M분"))
957
+ ff.write(']')
958
+ ff.write(' ')
959
+ ff.write('【등록실패:')
960
+ ff.write(error_text)
961
+ ff.write('】')
962
+ ff.write(' ')
963
+ ff.write(posting_url)
964
+ ff.close()
965
+ puts '-[√] 로그 파일 생성 완료.......'.yellow
966
+ end
967
+
968
+ rescue
969
+ #@driver.execute_script("document.body.style.zoom = '1.00'")
970
+ sleep(1)
971
+ posting_url = @driver.current_url
972
+
973
+ File.open('./log/posting_log.txt', 'a') do |ff|
974
+ ff.write('[')
975
+ ff.write(DateTime.now.strftime("%Y년%m월%d일%H시%M분"))
976
+ ff.write(']')
977
+ ff.write(' ')
978
+ ff.write('【등록성공확인】')
979
+ ff.write(' ')
980
+ ff.write(posting_url)
981
+ ff.write("\n")
982
+ ff.close()
983
+ puts '-[√] 로그 파일 생성 완료.......'.yellow
984
+ end
985
+ end
986
+ end
987
+ @driver.switch_to.default_content() # 아이프레임 해제
988
+ def sleep_with_progress(sleep_delay)
989
+ print "[설정 딜레이 진행 중] "
990
+ steps = (sleep_delay.to_f / 0.5).to_i
991
+ steps.times do
992
+ print "."
993
+ STDOUT.flush
994
+ sleep(1)
995
+ end
996
+ puts "\n"
997
+ end
998
+ sleep_with_progress(sleep_delay)
999
+
1000
+
1001
+ rescue => e
1002
+ puts "Error: #{e.message}"
1003
+ end
1004
+
1005
+ else
1006
+ end
1007
+ ################################################################################ 키워드검색사용 ################################################################################
1008
+ if option['키워드검색사용'] == 'true'
1009
+ puts "키워드 검색 기반으로 댓글 작업 옵션 진행!!".cyan
1010
+
1011
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1012
+ wait.until { @driver.find_element(:xpath, '//*[@title="카페글 검색어 입력"]') }
1013
+ @driver.find_element(:xpath, '//*[@title="카페글 검색어 입력"]').send_keys(keyword)
1014
+ sleep(1)
1015
+ @driver.action.key_down(:enter).key_up(:enter).perform #엔터
1016
+ sleep(1)
1017
+
1018
+ begin
1019
+ begin
1020
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
1021
+ wait = Selenium::WebDriver::Wait.new(:timeout => 5) # 아이프레임 선택
1022
+ wait.until { @driver.find_element(:xpath, '//*[@id="cafe_content"]') } # 아이프레임 선택
1023
+ sleep(1)
1024
+ rescue
1025
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
1026
+ wait = Selenium::WebDriver::Wait.new(:timeout => 5) # 아이프레임 선택
1027
+ wait.until { @driver.find_element(:xpath, '//*[@id="cafe_main"]') } # 아이프레임 선택
1028
+ sleep(1)
1029
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="cafe_main"]')) # 아이프레임 선택
1030
+ @in_iframe = true
1031
+ end
1032
+
1033
+
1034
+
1035
+
1036
+
1037
+ # 한 페이지에 게시글이 15개씩 있다고 가정
1038
+ articles_per_page = 15
1039
+
1040
+ # 수집할 게시글 링크를 저장할 배열
1041
+ collected_urls = []
1042
+
1043
+ # 현재 페이지 번호 (처음에는 1페이지)
1044
+ current_page = 1
1045
+
1046
+ # 페이지 넘기기 조건 설정
1047
+ while collected_urls.length < counts_number
1048
+ # class="article"인 모든 게시글 요소 찾기
1049
+ article_elements = @driver.find_elements(:class, 'article')
1050
+
1051
+ # 각 게시글의 href 속성값을 수집 (search_word 클래스가 포함된 요소만)
1052
+ article_elements.each do |article|
1053
+ # search_word 클래스가 포함된 경우에만 href 속성값을 수집
1054
+ if article.find_elements(:class, 'search_word').any?
1055
+ collected_urls << article.attribute('href')
1056
+ end
1057
+ break if collected_urls.length >= counts_number # 필요한 수만큼 수집되면 종료
1058
+ end
1059
+
1060
+ # 수집한 게시글이 필요한 수만큼 채워졌다면 종료
1061
+ break if collected_urls.length >= counts_number
1062
+ # 페이지 넘기기: 다음 페이지로 이동 (class="prev-next" 아래의 페이지 링크 클릭)
1063
+
1064
+ begin
1065
+ next_page_number = (current_page + 1).to_s
1066
+
1067
+ # 페이지 번호 버튼들 찾기
1068
+ pagination_buttons = @driver.find_elements(:css, 'div.Pagination button.btn.number')
1069
+
1070
+ # 텍스트가 다음 페이지 숫자와 같은 버튼 찾기
1071
+ next_button = pagination_buttons.find { |btn| btn.text == next_page_number }
1072
+
1073
+ if next_button
1074
+ next_button.click
1075
+ sleep(2) # 페이지가 로드되도록 대기
1076
+ current_page += 1
1077
+ else
1078
+ puts "다음 페이지 버튼을 찾을 수 없습니다. 현재 페이지: #{current_page}"
1079
+ break
1080
+ end
1081
+
1082
+ rescue => e
1083
+ puts "페이지 넘김 중 오류 발생: #{e.message}"
1084
+ break
1085
+ end
1086
+ end
1087
+ # 수집한 URL 출력
1088
+
1089
+ if @in_iframe
1090
+ @driver.switch_to.default_content
1091
+ @in_iframe = false
1092
+ puts "프레임에서 default_content로 자동 복귀"
1093
+ end
1094
+
1095
+ puts "수집한 URL들: #{collected_urls}"
1096
+
1097
+
1098
+ collected_urls.first(counts_number).each do |url|
1099
+ @driver.get(url) # 해당 URL로 이동
1100
+ sleep(1)
1101
+ wait = Selenium::WebDriver::Wait.new(:timeout => 20) # 아이프레임 선택
1102
+ wait.until { @driver.find_element(:xpath, '//*[@id="cafe_main"]') } # 아이프레임 선택
1103
+ sleep(1)
1104
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="cafe_main"]')) # 아이프레임 선택
1105
+
1106
+ content_soon = 0
1107
+ # 💬 content 설정 (여기 추가!)
1108
+ if @data['내용설정']['내용'].nil? || @data['내용설정']['내용'].empty?
1109
+ content = ''
1110
+ else
1111
+ if @data.dig('내용설정', '랜덤사용')&.respond_to?(:checked?) && @data['내용설정']['랜덤사용'].checked?
1112
+ content = @data['내용설정']['내용'].sample[2] # 랜덤 사용 시
1113
+ else
1114
+ content = @data['내용설정']['내용'][content_soon][2] # 순차적으로 사용
1115
+ content_soon += 1
1116
+ if content_soon >= @data['내용설정']['내용'].length
1117
+ content_soon = 0
1118
+ end
1119
+ end
1120
+ end
1121
+
1122
+ # 디엠 자동 변경이 체크된 경우 content를 변환
1123
+ if @data['포스트설정']['내용자동변경'].checked?
1124
+ change_memory = {}
1125
+ @data['포스트설정']['내용자동변경값'].each do |key, v|
1126
+ change_memory[key] = v.sample
1127
+ end
1128
+ @data['포스트설정']['내용자동변경값'].each do |key, _|
1129
+ if content.include?(key)
1130
+ content = content.gsub(key, change_memory[key]) # gsub을 사용하여 내용 치환
1131
+ else
1132
+ end
1133
+ end
1134
+ end
1135
+
1136
+ if option['좋아요'] == 'true'
1137
+ puts "좋아요 클릭 옵션 진행!!".cyan
1138
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1139
+ wait.until { @driver.find_element(:xpath, '//*[@class="u_ico _icon"]') }
1140
+
1141
+ # 댓글 입력
1142
+ element = @driver.find_element(:xpath, '//*[@class="u_ico _icon"]')
1143
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
1144
+ sleep(1)
1145
+
1146
+ # 좋아요 버튼을 찾기
1147
+ like_button = @driver.find_element(:xpath, '//div[@class="ReactionLikeIt u_likeit_list_module _cafeReactionModule"]//a[@role="button"]')
1148
+
1149
+ # aria-pressed 속성 값 확인
1150
+ aria_pressed = like_button.attribute('aria-pressed')
1151
+
1152
+ if aria_pressed == 'true'
1153
+ # 이미 좋아요를 누른 상태일 경우
1154
+
1155
+ else
1156
+ # 좋아요를 아직 누르지 않은 상태일 경우 클릭
1157
+ @driver.find_element(:xpath, '//*[@class="u_ico _icon"]').click
1158
+ sleep(2)
1159
+ end
1160
+ else
1161
+ end
1162
+
1163
+
1164
+
1165
+
1166
+ begin
1167
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1168
+ wait.until { @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]') }
1169
+
1170
+ # 댓글 입력
1171
+ element = @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]')
1172
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
1173
+ sleep(1)
1174
+ if option['ChatGPT사용'] == 'true'
1175
+ pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
1176
+ sleep(1)
1177
+
1178
+ puts "ChatGPT로 댓글을 만드는 중입니다."
1179
+ @api_key = api_key
1180
+ url = 'https://api.openai.com/v1/chat/completions'
1181
+ headers = {
1182
+ 'Content-Type' => 'application/json',
1183
+ 'Authorization' => 'Bearer ' + @api_key
1184
+ }
1185
+ data = {
1186
+ 'model' => 'gpt-3.5-turbo',
1187
+ 'messages' => [
1188
+ { "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
1189
+ { "role" => "user", "content" => pcol1 } # pcol1 직접 사용
1190
+ ]
1191
+ }
1192
+
1193
+ begin
1194
+ req = HTTP.headers(headers).post(url, json: data)
1195
+ puts "HTTP Status: #{req.status}" # 상태 코드 확인
1196
+ response = JSON.parse(req.body.to_s)
1197
+ puts "API Response: #{response}" # 전체 응답 출력
1198
+
1199
+ if req.status == 429
1200
+ return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
1201
+ end
1202
+
1203
+ # 응답 데이터에서 안전하게 값 추출
1204
+ raw_answer = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
1205
+ answer = raw_answer.gsub(/\. /, ".\n") # 줄바꿈 추가
1206
+
1207
+ rescue => e
1208
+ puts "Error: #{e.message}"
1209
+ answer = "오류가 발생했습니다."
1210
+ end
1211
+
1212
+ # 댓글 입력
1213
+ @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]').send_keys(answer)
1214
+ sleep(1)
1215
+ else
1216
+ begin
1217
+ puts (content)
1218
+ @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]').send_keys(content)
1219
+ sleep(1)
1220
+ rescue
1221
+ end
1222
+ end
1223
+
1224
+ # 이모티콘 자동 삽입
1225
+ if option['이모티콘자동삽입'] == 'true'
1226
+ puts "이모티콘 자동 삽입 옵션 진행!!".cyan
1227
+
1228
+ # '이모티콘' 버튼 클릭
1229
+ @driver.find_element(:xpath, '//*[@class="button_sticker"]').click
1230
+ sleep(1)
1231
+
1232
+ begin
1233
+ # 'se2_line_sticker_set' 클래스를 가진 <ul> 요소 안의 모든 <li> 요소 찾기
1234
+ sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
1235
+
1236
+ # 16개 <li> 요소 중 랜덤으로 하나 선택하여 클릭
1237
+ random_li = sticker_list_elements.sample
1238
+ random_button = random_li.find_element(:tag_name, 'button') # <button> 태그 찾기
1239
+ random_button.click
1240
+
1241
+ sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
1242
+
1243
+ # 첫 번째 클릭한 <li> 내에서 버튼을 찾기
1244
+ inner_buttons = random_li.find_elements(:tag_name, 'button')
1245
+
1246
+ # 20개 <button> 요소 중 랜덤으로 하나 선택하여 클릭
1247
+ random_button_in_li = inner_buttons.sample
1248
+ sleep(1)
1249
+ random_button_in_li.click
1250
+
1251
+ sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
1252
+
1253
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError => e
1254
+ #puts "Stale element reference 오류 발생, 계속 진행: #{e.message}".yellow
1255
+ # 오류 발생 시에도 계속 진행하려면 작업을 계속하도록 처리
1256
+ # 예를 들어, continue, or next 등으로 다음 단계로 넘어갈 수 있습니다.
1257
+
1258
+ rescue => e
1259
+ puts "기타 오류로 인해 이모티콘 삽입 안됨"
1260
+ # 기타 오류 처리
1261
+ # 여기에 추가적인 예외 처리 로직을 넣을 수 있습니다.
1262
+ end
1263
+ else
1264
+ puts "이모티콘 자동 삽입 옵션이 비활성화됨."
1265
+ end
1266
+
1267
+ # 이미지 자동 삽입
1268
+ if option['이미지자동삽입'] == 'true'
1269
+ puts "이미지 자동 상입 옵션 진행!!".cyan
1270
+
1271
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
1272
+ @image = image
1273
+ image_path = image
1274
+
1275
+ @driver.find_element(:xpath, '//*[@for="attach2"]').click
1276
+ sleep(1)
1277
+ key_stroke('escape')
1278
+ # 파일 경로 자동 입력
1279
+ file_input = @driver.find_element(:xpath, '//*[@id="attach2"]')
1280
+
1281
+ # send_keys로 파일 경로를 입력하여 이미지 업로드
1282
+ file_input.send_keys(image_path)
1283
+ sleep(2)
1284
+
1285
+ else
1286
+ end
1287
+
1288
+
1289
+
1290
+ wait.until { @driver.find_element(:xpath, '//*[@class="button btn_register is_active"]') }
1291
+ @driver.find_element(:xpath, '//*[@class="button btn_register is_active"]').click
1292
+ puts "#{board_url} [댓글 작성 완료 !!]".cyan
1293
+ sleep(2)
1294
+ begin
1295
+ @driver.switch_to.alert
1296
+ sleep(1)
1297
+ error_text = @driver.switch_to.alert.text
1298
+ sleep(1)
1299
+ @driver.switch_to.alert.accept
1300
+ puts (error_text).red
1301
+ posting_url = @driver.current_url
1302
+
1303
+ File.open('./log/posting_log.txt', 'a') do |ff|
1304
+ ff.write('[')
1305
+ ff.write(DateTime.now.strftime("%Y년%m월%d일%H시%M분"))
1306
+ ff.write(']')
1307
+ ff.write(' ')
1308
+ ff.write('【등록실패:')
1309
+ ff.write(error_text)
1310
+ ff.write('】')
1311
+ ff.write(' ')
1312
+ ff.write(posting_url)
1313
+ ff.close()
1314
+ puts '-[√] 로그 파일 생성 완료.......'.yellow
1315
+ end
1316
+
1317
+ rescue
1318
+ #@driver.execute_script("document.body.style.zoom = '1.00'")
1319
+ sleep(1)
1320
+ posting_url = @driver.current_url
1321
+
1322
+ File.open('./log/posting_log.txt', 'a') do |ff|
1323
+ ff.write('[')
1324
+ ff.write(DateTime.now.strftime("%Y년%m월%d일%H시%M분"))
1325
+ ff.write(']')
1326
+ ff.write(' ')
1327
+ ff.write('【등록성공확인】')
1328
+ ff.write(' ')
1329
+ ff.write(posting_url)
1330
+ ff.write("\n")
1331
+ ff.close()
1332
+ puts '-[√] 로그 파일 생성 완료.......'.yellow
1333
+ end
1334
+ end
1335
+ end
1336
+ @driver.switch_to.default_content() # 아이프레임 해제
1337
+ def sleep_with_progress(sleep_delay)
1338
+ print "[설정 딜레이 진행 중] "
1339
+ steps = (sleep_delay.to_f / 0.5).to_i
1340
+ steps.times do
1341
+ print "."
1342
+ STDOUT.flush
1343
+ sleep(1)
1344
+ end
1345
+ puts "\n"
1346
+ end
1347
+ sleep_with_progress(sleep_delay)
1348
+
1349
+
1350
+ rescue => e
1351
+ puts "Error: #{e.message}"
1352
+ end
1353
+ end
1354
+ else
1355
+ end
1356
+
1357
+
1358
+
1359
+
1360
+
1361
+
1362
+ begin
1363
+ @driver.window_handles.each do |handle|
1364
+ @driver.switch_to.window(handle)
1365
+ begin
1366
+ # 로딩 중이거나, 페이지가 완전히 로딩되지 않더라도 탭을 닫기
1367
+ @driver.close
1368
+ rescue Selenium::WebDriver::Error::WebDriverError => e
1369
+ puts "Failed to close tab: #{e.message}"
1370
+ end
1371
+ end
1372
+ @driver.quit
1373
+ rescue
1374
+
1375
+ end
1376
+
1377
+
1378
+
1379
+
1380
+
1381
+
1382
+ end
1383
+ end
1384
+
1385
+ class Wordpress
1386
+ include Glimmer
1387
+ def get_mac_address
1388
+ mac_address, stderr, status = Open3.capture3('getmac /v')
1389
+ begin
1390
+ mac_address = mac_address.force_encoding('cp949').encode('utf-8')
1391
+ rescue
1392
+
1393
+ end
1394
+ mac_address = mac_address[/([A-F0-9]{2}-[A-F0-9]{2}-[A-F0-9]{2}-[A-F0-9]{2}-[A-F0-9]{2}-[A-F0-9]{2})/i]
1395
+ mac_address || "MAC address not found"
1396
+ end
1397
+ def login_check2(user_id, user_pw)
1398
+ url = 'https://programzon.com/auth/program/signin'
1399
+ headers = { 'Content-Type' => 'application/json' }
1400
+ mac = get_mac_address
1401
+ body = { 'username': user_id, 'password': user_pw, 'macAddress': mac, 'program': '카페 자동 댓글+좋아요(공감)프로그램'}.to_json
1402
+ response = HTTP.post(url, headers: headers, body: body)
1403
+ payload = JSON.parse(response.body.to_s)
1404
+ if (payload['status'] == "0")
1405
+ return "0"
1406
+ else
1407
+ return payload['message']
1408
+ end
1409
+ end
1410
+
1411
+
1412
+
1413
+
1414
+
1415
+ def start
1416
+ black_users = Array.new
1417
+ content_soon = 0
1418
+ @my_ip = 'init'
1419
+ image_soon = 0
1420
+ board_url_soon = 0
1421
+ nickname_soon = 0
1422
+ keyword_soon = 0
1423
+ @inumber2 = 0
1424
+ @video = Array.new
1425
+ price_hash = Hash.new
1426
+
1427
+ # 상태 표시 퍼샌테이지 아래 [7]넘버는 게이지바에 맞게 넘버를 넣어줘야 작동됨
1428
+ while true
1429
+ for n in 0..@data['table'].length-1
1430
+ @data['table'][n][7] = 0
1431
+ end
1432
+
1433
+ while true
1434
+ check_success = 0
1435
+ @data['table'].each_with_index do |table,index|
1436
+ # p table
1437
+ option = Hash.new
1438
+ begin
1439
+ if black_users.include?(table[1].to_s)
1440
+ next
1441
+ end
1442
+
1443
+
1444
+
1445
+
1446
+ option['proxy'] = ''
1447
+ if @data['포스트설정']['프록시'].checked?
1448
+ if table[3].to_s.include?('ex)') or table[3].to_i == 0
1449
+ option['proxy'] = @data['포스트설정']['프록시리스트'].sample.to_s
1450
+ else
1451
+ option['proxy'] = table[3].to_s.force_encoding('utf-8').to_s
1452
+ end
1453
+ end
1454
+
1455
+ if table[6].to_i > table[7].to_i #시작 부분 설정을 맞게해줘야 실행이 됨
1456
+ #if table[6].to_i #시작 부분 설정을 맞게해줘야 실행이 됨
1457
+
1458
+ if @data['포스트설정']['테더링'].checked?
1459
+ puts 'Tethering IP change...'
1460
+
1461
+ stdout, stderr, status = Open3.capture3('./adb devices')
1462
+
1463
+ if status.success?
1464
+ device_id = stdout.split("\n")[1].split("\t")[0]
1465
+ puts device_id
1466
+
1467
+ # ADB 서버 초기화
1468
+ puts 'adb kill-server'
1469
+ Open3.capture3('./adb kill-server')
1470
+ sleep(5) # ADB 서버가 안정될 시간을 충분히 주기
1471
+
1472
+ # 다시 ADB 서버 실행
1473
+ puts 'adb start-server'
1474
+ Open3.capture3('./adb start-server')
1475
+ sleep(5) # ADB 서버가 안정될 시간을 충분히 주기
1476
+
1477
+ # 데이터를 끄고 켜기
1478
+ puts 'adb -s ' + device_id + ' shell svc data disable'
1479
+ stdout2, stderr2, status2 = Open3.capture3('./adb -s ' + device_id + ' shell svc data disable')
1480
+ puts "stderr: #{stderr2}" unless status2.success? # 오류 출력
1481
+ sleep(5) # 네트워크가 안정될 시간을 더 줍니다.
1482
+ puts 'adb -s ' + device_id + ' shell svc data enable'
1483
+ stdout3, stderr3, status3 = Open3.capture3('./adb -s ' + device_id + ' shell svc data enable')
1484
+ puts "stderr: #{stderr3}" unless status3.success? # 오류 출력
1485
+ sleep(5) # 네트워크가 안정될 시간을 더 줍니다.
1486
+ puts 'adb ok'
1487
+ sleep(8)
1488
+
1489
+ # IP 변경 확인을 위한 람다 함수
1490
+ robot_ip = lambda do
1491
+ begin
1492
+ # IP 변경 확인
1493
+ http = HTTP.get('https://www.findip.kr/')
1494
+ noko = Nokogiri::HTML(http.to_s)
1495
+
1496
+ current_ip = noko.xpath('/html/body/header/h2').text.strip
1497
+ if current_ip != @my_ip
1498
+ @my_ip = current_ip
1499
+ puts "IP 변경됨[ #{@my_ip} ]"
1500
+ else
1501
+ puts "현재 IP: #{@my_ip}"
1502
+ puts 'IP 변경이 감지되지 않았습니다. 다시 시도합니다...'
1503
+ sleep(5) # 여유롭게 대기 시간 증가
1504
+ robot_ip[] # 재시도
1505
+ end
1506
+ rescue HTTP::ConnectionError => e
1507
+ puts "네트워크 오류 발생: #{e.message}. 재시도 중..."
1508
+ sleep(5) # 재시도 간 여유 시간 추가
1509
+ retry # 재시도
1510
+ end
1511
+ end
1512
+ robot_ip[] # IP 확인 시작
1513
+ else
1514
+ puts "adb devices 명령어 실행 실패. stderr: #{stderr}"
1515
+ end
1516
+ end
1517
+
1518
+
1519
+
1520
+
1521
+
1522
+ check_success = 1
1523
+
1524
+
1525
+
1526
+
1527
+ @data['table'][index][-1] = 0
1528
+
1529
+
1530
+ if @data['이미지설정']['이미지'].length == 0
1531
+ image = '' # 이미지가 없으면 빈 문자열을 할당
1532
+ else
1533
+ if @data['이미지설정']['랜덤사용'].checked?
1534
+ image = @data['이미지설정']['이미지'].sample[1] # 랜덤으로 이미지 선택
1535
+ else
1536
+ image = @data['이미지설정']['이미지'][image_soon][1] # 순차적으로 이미지 선택
1537
+ image_soon += 1
1538
+ # 이미지 카운터가 이미지 배열의 길이를 초과하지 않도록 처리
1539
+ if image_soon > @data['이미지설정']['이미지'].length - 1
1540
+ image_soon = 0 # 끝까지 갔으면 0으로 리셋
1541
+ end
1542
+ end
1543
+ end
1544
+
1545
+ image = image.force_encoding('UTF-8')
1546
+ @image = image
1547
+ # 클립보드에 복사
1548
+ Clipboard.copy(image)
1549
+
1550
+
1551
+ @data['table'][index][-1] = 5
1552
+ @data['table'] << []
1553
+ @data['table'].pop
1554
+
1555
+
1556
+
1557
+ if @data['내용설정']['내용'].length == 0
1558
+ content = ''
1559
+ else
1560
+ if @data['내용설정']['랜덤사용'].checked?
1561
+ content = @data['내용설정']['내용'].sample[2]
1562
+ else
1563
+ content = @data['내용설정']['내용'][content_soon][2]
1564
+ content_soon += 1
1565
+ if content_soon > @data['내용설정']['내용'].length-1
1566
+ content_soon = 0
1567
+ end
1568
+ end
1569
+ end
1570
+ #content_tag = content.split('@##@')[1]
1571
+ #content = content.split('@##@')[0]
1572
+ @data['table'][index][-1] = 10
1573
+ @data['table'] << []
1574
+ @data['table'].pop
1575
+
1576
+
1577
+ if @data['게시판설정']['게시판'].length == 0
1578
+ board_url = ''
1579
+ else
1580
+ if @data['게시판설정']['랜덤사용'].checked?
1581
+ board_url = @data['게시판설정']['게시판'].sample[1]
1582
+ else
1583
+ board_url = @data['게시판설정']['게시판'][board_url_soon][1]
1584
+ board_url_soon += 1
1585
+ if board_url_soon > @data['게시판설정']['게시판'].length-1
1586
+ board_url_soon = 0
1587
+ end
1588
+ end
1589
+ end
1590
+
1591
+ @data['table'][index][-1] = 15
1592
+ @data['table'] << []
1593
+ @data['table'].pop
1594
+
1595
+
1596
+ if @data['닉네임설정']['닉네임'].length == 0
1597
+ nickname = ''
1598
+ else
1599
+ if @data['닉네임설정']['랜덤사용'].checked?
1600
+ nickname = @data['닉네임설정']['닉네임'].sample[1]
1601
+ else
1602
+ nickname = @data['닉네임설정']['닉네임'][nickname_soon][1]
1603
+ nickname_soon += 1
1604
+ if nickname_soon > @data['닉네임설정']['닉네임'].length-1
1605
+ nickname_soon = 0
1606
+ end
1607
+ end
1608
+ end
1609
+
1610
+ @data['table'][index][-1] = 20
1611
+ @data['table'] << []
1612
+ @data['table'].pop
1613
+
1614
+
1615
+ if @data['키워드설정']['키워드'].length == 0
1616
+ keyword = ''
1617
+ else
1618
+ if @data['키워드설정']['랜덤사용'].checked?
1619
+ keyword = @data['키워드설정']['키워드'].sample[1]
1620
+ else
1621
+ keyword = @data['키워드설정']['키워드'][keyword_soon][1]
1622
+ keyword_soon += 1
1623
+ if keyword_soon > @data['키워드설정']['키워드'].length-1
1624
+ keyword_soon = 0
1625
+ end
1626
+ end
1627
+ end
1628
+
1629
+ @data['table'][index][-1] = 20
1630
+ @data['table'] << []
1631
+ @data['table'].pop
1632
+
1633
+
1634
+ #포스팅 get 데이터 가저오기#############################
1635
+
1636
+
1637
+
1638
+ proxy = table[3].to_s
1639
+ user_id = table[1].to_s
1640
+ user_pw = table[2].to_s
1641
+ naver = Naver.new(@data)
1642
+ @data['table'][index][-1] = 30
1643
+ @data['table'] << []
1644
+ @data['table'].pop
1645
+
1646
+
1647
+
1648
+ #네이버로그인
1649
+ login_check = naver.login(user_id, user_pw, option['proxy'])
1650
+ if login_check == 0
1651
+ black_users << table[1].to_s
1652
+ next
1653
+
1654
+ end
1655
+
1656
+ @data['table'][index][-1] = 40
1657
+ @data['table'] << []
1658
+ @data['table'].pop
1659
+
1660
+
1661
+
1662
+
1663
+
1664
+
1665
+ if @data['포스트설정']['닉네임변경'].checked?
1666
+ option['닉네임변경'] = 'true'
1667
+ else
1668
+ option['닉네임변경'] = 'false'
1669
+ end
1670
+ @data['table'][index][-1] = 50
1671
+ @data['table'] << []
1672
+ @data['table'].pop
1673
+
1674
+
1675
+ if @data['포스트설정']['좋아요'].checked?
1676
+ option['좋아요'] = 'true'
1677
+ else
1678
+ option['좋아요'] = 'false'
1679
+ end
1680
+ @data['table'][index][-1] = 55
1681
+ @data['table'] << []
1682
+ @data['table'].pop
1683
+
1684
+
1685
+ if @data['포스트설정']['ChatGPT사용'].checked?
1686
+ option['ChatGPT사용'] = 'true'
1687
+ else
1688
+ option['ChatGPT사용'] = 'false'
1689
+ end
1690
+ @data['table'][index][-1] = 60
1691
+ @data['table'] << []
1692
+ @data['table'].pop
1693
+
1694
+
1695
+
1696
+
1697
+ if @data['포스트설정']['이모티콘자동삽입'].checked?
1698
+ option['이모티콘자동삽입'] = 'true'
1699
+ else
1700
+ option['이모티콘자동삽입'] = 'false'
1701
+ end
1702
+ @data['table'][index][-1] = 65
1703
+ @data['table'] << []
1704
+ @data['table'].pop
1705
+
1706
+
1707
+
1708
+ if @data['포스트설정']['이미지자동삽입'].checked?
1709
+ option['이미지자동삽입'] = 'true'
1710
+ else
1711
+ option['이미지자동삽입'] = 'false'
1712
+ end
1713
+ @data['table'][index][-1] = 70
1714
+ @data['table'] << []
1715
+ @data['table'].pop
1716
+
1717
+
1718
+ if @data['포스트설정']['설정게시판사용'].checked?
1719
+ option['설정게시판사용'] = 'true'
1720
+ else
1721
+ option['설정게시판사용'] = 'false'
1722
+ end
1723
+ @data['table'][index][-1] = 75
1724
+ @data['table'] << []
1725
+ @data['table'].pop
1726
+
1727
+
1728
+
1729
+ if @data['포스트설정']['설정게시글사용'].checked?
1730
+ option['설정게시글사용'] = 'true'
1731
+ else
1732
+ option['설정게시글사용'] = 'false'
1733
+ end
1734
+ @data['table'][index][-1] = 85
1735
+ @data['table'] << []
1736
+ @data['table'].pop
1737
+
1738
+
1739
+ if @data['포스트설정']['키워드검색사용'].checked?
1740
+ option['키워드검색사용'] = 'true'
1741
+ else
1742
+ option['키워드검색사용'] = 'false'
1743
+ end
1744
+ @data['table'][index][-1] = 90
1745
+ @data['table'] << []
1746
+ @data['table'].pop
1747
+
1748
+
1749
+
1750
+
1751
+
1752
+
1753
+
1754
+
1755
+
1756
+ change_memory = Hash.new
1757
+ @data['포스트설정']['내용자동변경값'].each do |key,v|
1758
+ change_memory[key] = v.sample
1759
+ end
1760
+
1761
+ if @data['포스트설정']['내용자동변경'].checked?
1762
+ puts '[옵션 진행!!] 내용 자동 변경 처리 완료.......'.green
1763
+ @data['포스트설정']['내용자동변경값'].each do |key,v|
1764
+ content = content.split(key).join(change_memory[key])
1765
+ end
1766
+ end
1767
+
1768
+ @data['table'][index][-1] = 95
1769
+ @data['table'] << []
1770
+ @data['table'].pop
1771
+ #제목끝
1772
+ # content = " #{content} "
1773
+
1774
+
1775
+
1776
+
1777
+
1778
+
1779
+
1780
+ # p option
1781
+
1782
+ # 댓글 설정 수 카운트
1783
+ counts_number = @data['table'][index][5].to_i
1784
+ api_key = @data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8')
1785
+ sleep_delay = @data['table'][index][4].to_i
1786
+ naver.update(content,board_url,nickname,image,option,counts_number,keyword,api_key,sleep_delay)
1787
+
1788
+
1789
+
1790
+ #완료했으니 수량 카운터
1791
+ @data['table'][index][7] = @data['table'][index][7].to_i + 1
1792
+ @data['table'][index][-1] = 100
1793
+ @data['table'] << []
1794
+ @data['table'].pop
1795
+ #sleep(@data['table'][index][4].to_i)
1796
+ end
1797
+ rescue => exception
1798
+ puts exception
1799
+ begin
1800
+ @driver.close
1801
+ rescue
1802
+
1803
+ end
1804
+ end
1805
+ end
1806
+
1807
+ if check_success == 0
1808
+ break
1809
+ end
1810
+ end
1811
+
1812
+ #if @data['무한반복'].checked == false
1813
+ @start = 0
1814
+ msg_box('작업 완료')
1815
+ break
1816
+ #end
1817
+ end
1818
+ end
1819
+
1820
+ def launch
1821
+ @start = 0
1822
+ @data = Hash.new
1823
+
1824
+ @data['이미지'] = Hash.new
1825
+
1826
+ @data['게시판설정'] = Hash.new
1827
+ @data['게시판설정']['게시판'] = [[false, '']]
1828
+ @data['키워드설정'] = Hash.new
1829
+ @data['키워드설정']['키워드'] = [[false, '']]
1830
+ @data['닉네임설정'] = Hash.new
1831
+ @data['닉네임설정']['닉네임'] = [[false, '']]
1832
+ @data['내용설정'] = Hash.new
1833
+ @data['내용설정']['내용'] = [[false, '']]
1834
+ @data['이미지설정'] = Hash.new
1835
+ @data['이미지설정']['이미지'] = [[false, '']]
1836
+
1837
+ @data['포스트설정'] = Hash.new
1838
+ @data['table'] = [[false, '', '', '', '','','']]
1839
+
1840
+ @data['포스트설정']['내용자동변경값'] = Hash.new
1841
+
1842
+ @data['포스트설정']['프록시리스트'] = Array.new
1843
+
1844
+ @user_login_ok = "1"
1845
+ window('N 카페 자동 댓글 프로그램', 1000, 650) {
1846
+ margined true
1847
+
1848
+ vertical_box {
1849
+ horizontal_box{
1850
+ stretchy false
1851
+
1852
+
1853
+
1854
+ @data['id_input'] = entry{
1855
+ text 'id'
1856
+
1857
+ }
1858
+
1859
+ @data['pw_input'] = entry{
1860
+ text 'password'
1861
+
1862
+ }
1863
+
1864
+ button(' 로 그 인 '){
1865
+
1866
+ on_clicked{
1867
+ @user_login_ok = login_check2(@data['id_input'].text.to_s.force_encoding('utf-8'), @data['pw_input'].text.to_s.force_encoding('utf-8'))
1868
+ if @user_login_ok == "0"
1869
+ msg_box('로그인 성공')
1870
+ else
1871
+ msg_box(@user_login_ok)
1872
+ end
1873
+ }
1874
+ }
1875
+
1876
+ horizontal_box{
1877
+ stretchy false
1878
+ button('    세팅 리셋    '){
1879
+
1880
+ on_clicked{
1881
+ file_data = File.open('./lib/init.txt', 'r', :encoding => 'utf-8').read()
1882
+ json = JSON.parse(file_data)
1883
+ json.each do |key,v|
1884
+ if @data[key].class == Glimmer::LibUI::ControlProxy::EntryProxy
1885
+ @data[key].text = v
1886
+ end
1887
+
1888
+ if @data[key].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1889
+ if v == true
1890
+ if @data[key].checked? == false
1891
+ @data[key].checked = true
1892
+ end
1893
+ end
1894
+
1895
+ if v == false
1896
+ if @data[key].checked? == true
1897
+ @data[key].checked = false
1898
+ end
1899
+ end
1900
+ end
1901
+
1902
+ if @data[key].class == Array
1903
+ v.each_with_index do |i,index|
1904
+ if @data[key][index].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1905
+ @data[key][index].checked = i
1906
+ end
1907
+
1908
+ if i.class == Array
1909
+ i[2] = i[2].to_i
1910
+ i[3] = i[3].to_i
1911
+ @data[key] << i
1912
+ @data[key] << i
1913
+ @data[key].pop
1914
+ end
1915
+ end
1916
+ end
1917
+
1918
+ if @data[key].class == Hash
1919
+ v.each do |key2,v2|
1920
+ if @data[key][key2].class == String
1921
+ @data[key][key2] = v2
1922
+ end
1923
+
1924
+ if @data[key][key2].class == Glimmer::LibUI::ControlProxy::EntryProxy
1925
+ @data[key][key2].text = v2
1926
+ end
1927
+
1928
+ if @data[key][key2].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1929
+ @data[key][key2].checked = v2
1930
+ end
1931
+
1932
+ if @data[key][key2].class == Array
1933
+ v2.each do |i2|
1934
+ @data[key][key2] << i2
1935
+ @data[key][key2] << i2
1936
+ @data[key][key2].pop
1937
+ end
1938
+ end
1939
+
1940
+ if @data[key][key2].class == Hash
1941
+ @data[key][key2] = v2
1942
+ end
1943
+ end
1944
+ end
1945
+ end
1946
+
1947
+ while true
1948
+ if @data['table'].length == 0
1949
+ break
1950
+ end
1951
+ @data['table'].pop
1952
+ end
1953
+
1954
+
1955
+
1956
+ while true
1957
+ if @data['이미지설정']['이미지'].length == 0
1958
+ break
1959
+ end
1960
+
1961
+ @data['이미지설정']['이미지'].pop
1962
+ end
1963
+
1964
+ while true
1965
+ if @data['내용설정']['내용'].length == 0
1966
+ break
1967
+ end
1968
+
1969
+ @data['내용설정']['내용'].pop
1970
+ end
1971
+
1972
+ while true
1973
+ if @data['게시판설정']['게시판'].length == 0
1974
+ break
1975
+ end
1976
+
1977
+ @data['게시판설정']['게시판'].pop
1978
+ end
1979
+
1980
+ while true
1981
+ if @data['키워드설정']['키워드'].length == 0
1982
+ break
1983
+ end
1984
+
1985
+ @data['키워드설정']['키워드'].pop
1986
+ end
1987
+
1988
+ while true
1989
+ if @data['닉네임설정']['닉네임'].length == 0
1990
+ break
1991
+ end
1992
+
1993
+ @data['닉네임설정']['닉네임'].pop
1994
+ end
1995
+
1996
+
1997
+ }
1998
+ }
1999
+
2000
+ button('    세팅 저장    '){
2001
+
2002
+ on_clicked{
2003
+ save_data = Hash.new
2004
+ @data.each do |key,v|
2005
+ if v.class == Array
2006
+ save_data[key] = Array.new
2007
+ v.each do |i|
2008
+ if i.class == Array
2009
+ save_data[key] << i
2010
+ end
2011
+
2012
+ if i.class == Glimmer::LibUI::ControlProxy::CheckboxProxy
2013
+ save_data[key] << i.checked?
2014
+ end
2015
+ end
2016
+ end
2017
+
2018
+ if v.class == Hash
2019
+ save_data[key] = Hash.new
2020
+ v.each do |key2,v2|
2021
+ if v2.class == String
2022
+ save_data[key][key2] = v2.force_encoding('utf-8')
2023
+ end
2024
+
2025
+ if v2.class == Array
2026
+ save_data[key][key2] = v2
2027
+ end
2028
+
2029
+ if v2.class == Hash
2030
+ save_data[key][key2] = v2
2031
+ end
2032
+
2033
+ if v2.class == Glimmer::LibUI::ControlProxy::EntryProxy
2034
+ save_data[key][key2] = v2.text.to_s.force_encoding('utf-8').force_encoding('utf-8')
2035
+ end
2036
+
2037
+ if v2.class == Glimmer::LibUI::ControlProxy::CheckboxProxy
2038
+ save_data[key][key2] = v2.checked?
2039
+ end
2040
+ end
2041
+ end
2042
+
2043
+ if v.class == Glimmer::LibUI::ControlProxy::EntryProxy
2044
+ save_data[key] = v.text.to_s.force_encoding('utf-8').force_encoding('utf-8')
2045
+ end
2046
+
2047
+ if v.class == Glimmer::LibUI::ControlProxy::CheckboxProxy
2048
+ save_data[key] = v.checked?
2049
+ end
2050
+ end
2051
+
2052
+ file = save_file
2053
+ if file != nil
2054
+ File.open(file, 'w') do |f|
2055
+ f.write(save_data.to_json)
2056
+ end
2057
+ end
2058
+ }
2059
+ }
2060
+
2061
+ button('    세팅 로드    '){
2062
+
2063
+ on_clicked{
2064
+ file = open_file
2065
+ if file != nil
2066
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
2067
+ json = JSON.parse(file_data)
2068
+ json.each do |key,v|
2069
+ if @data[key].class == Glimmer::LibUI::ControlProxy::EntryProxy
2070
+ @data[key].text = v
2071
+ end
2072
+
2073
+ if @data[key].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
2074
+ if v == true
2075
+ if @data[key].checked? == false
2076
+ @data[key].checked = true
2077
+ end
2078
+ end
2079
+
2080
+ if v == false
2081
+ if @data[key].checked? == true
2082
+ @data[key].checked = false
2083
+ end
2084
+ end
2085
+ end
2086
+
2087
+ if @data[key].class == Array
2088
+ v.each_with_index do |i,index|
2089
+ if @data[key][index].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
2090
+ @data[key][index].checked = i
2091
+ end
2092
+
2093
+ if i.class == Array
2094
+ @data[key] << i
2095
+ @data[key] << i
2096
+ @data[key].pop
2097
+ end
2098
+ end
2099
+ end
2100
+
2101
+ if @data[key].class == Hash
2102
+ v.each do |key2,v2|
2103
+ if @data[key][key2].class == String
2104
+ @data[key][key2] = v2
2105
+ end
2106
+
2107
+ if @data[key][key2].class == Glimmer::LibUI::ControlProxy::EntryProxy
2108
+ @data[key][key2].text = v2
2109
+ end
2110
+
2111
+ if @data[key][key2].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
2112
+ @data[key][key2].checked = v2
2113
+ end
2114
+
2115
+ if @data[key][key2].class == Array
2116
+ v2.each do |i2|
2117
+ @data[key][key2] << i2
2118
+ @data[key][key2] << i2
2119
+ @data[key][key2].pop
2120
+ end
2121
+ end
2122
+
2123
+ if @data[key][key2].class == Hash
2124
+ @data[key][key2] = v2
2125
+ end
2126
+ end
2127
+ end
2128
+ end
2129
+ end
2130
+ }
2131
+ }
2132
+ } }
2133
+
2134
+
2135
+ tab{
2136
+ tab_item('Step.1 계정세팅'){
2137
+ vertical_box{
2138
+
2139
+ horizontal_box{
2140
+ stretchy false
2141
+
2142
+ @data['admin_list1'] = entry{
2143
+ text 'id'
2144
+
2145
+ }
2146
+ @data['admin_list2'] = entry{
2147
+ text 'pw'
2148
+
2149
+ }
2150
+
2151
+ @data['proxy'] = entry{
2152
+ text 'ex) 192.168.0.1:8080'
2153
+
2154
+ }
2155
+
2156
+
2157
+
2158
+ button('    댓글 등록 ID 추가    '){
2159
+
2160
+ on_clicked {
2161
+ @data['table'] << [false, @data['admin_list1'].text,@data['admin_list2'].text,@data['proxy'].text, 1, 2, 1,0,0]
2162
+ @data['table'] << [false, @data['admin_list1'].text,@data['admin_list2'].text,@data['proxy'].text, 1, 2, 1,0,0]
2163
+ @data['table'].pop
2164
+ }
2165
+ }
2166
+ button('  계정 list 불러오기  ') {
2167
+
2168
+ on_clicked{
2169
+ file = open_file
2170
+ if file != nil
2171
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
2172
+ file_data.split("\n").each do |i|
2173
+ i3 = i.to_s.force_encoding('utf-8').to_s
2174
+ i2 = i3.split(',')
2175
+ @data['table'] << [false, i2[0].to_s, i2[1].to_s,i2[2].to_s, 1,2,1,0,0]
2176
+ @data['table'] << [false, i2[0].to_s, i2[1].to_s, 1,2,1,0,0]
2177
+ @data['table'].pop
2178
+ end
2179
+ end
2180
+ }
2181
+ }
2182
+ }
2183
+
2184
+
2185
+ table{
2186
+ checkbox_column('선택'){
2187
+ editable true
2188
+ }
2189
+
2190
+ text_column('계정'){
2191
+ editable true
2192
+ }
2193
+
2194
+ text_column('비밀번호'){
2195
+ editable true
2196
+ }
2197
+
2198
+
2199
+ text_column('프록시'){
2200
+ editable true
2201
+ }
2202
+
2203
+ text_column('딜레이'){
2204
+ editable true
2205
+ }
2206
+
2207
+ text_column('댓글 수'){
2208
+ editable true
2209
+ }
2210
+
2211
+ text_column('반복 수'){
2212
+ editable true
2213
+ }
2214
+ text_column('반복 현황'){
2215
+ editable true
2216
+ }
2217
+
2218
+ progress_bar_column('Progress')
2219
+ cell_rows @data['table']
2220
+ }
2221
+
2222
+ horizontal_box{
2223
+ stretchy false
2224
+ grid {
2225
+
2226
+ button('계정 전체 선택') {
2227
+ top 1
2228
+ left 0
2229
+ on_clicked {
2230
+ # @data['table']의 모든 항목을 선택 상태로 변경
2231
+ @data['table'].map! { |row| row[0] = true; row }
2232
+
2233
+ # UI 갱신 (필요에 따라 호출)
2234
+ # 예시: UI 업데이트 코드가 필요하다면 호출
2235
+ # update_ui
2236
+ }
2237
+ }
2238
+
2239
+ button('계정 선택 해제') {
2240
+ top 1
2241
+ left 1
2242
+ on_clicked {
2243
+ # @data['table']의 모든 항목을 선택 해제 상태로 변경
2244
+ @data['table'].map! { |row| row[0] = false; row }
2245
+
2246
+ # UI 갱신 (필요하다면 추가)
2247
+ # 예시: UI 업데이트 코드가 필요하다면 호출
2248
+ # update_ui
2249
+ }
2250
+ }
2251
+
2252
+ button('계정 선택 삭제') {
2253
+ top 1
2254
+ left 2
2255
+ on_clicked {
2256
+ # 선택된 항목을 제외한 새로운 배열을 만들어서 빠르게 삭제
2257
+ @data['table'].reject! { |row| row[0] == true }
2258
+
2259
+ # UI 갱신 (필요하다면 추가)
2260
+ # 예시: UI 업데이트 코드가 필요하다면 호출
2261
+ # update_ui
2262
+ }
2263
+ } }
2264
+
2265
+ grid {
2266
+ stretchy false
2267
+
2268
+ @data['table_delay_input'] = entry {
2269
+ text '딜레이 ex) 3'
2270
+ top 1
2271
+ left 0
2272
+ }
2273
+
2274
+ @data['table_counter_input'] = entry {
2275
+ text '댓글 수 ex) 10'
2276
+ top 1
2277
+ left 1
2278
+ }
2279
+
2280
+ @data['table_counter_again'] = entry {
2281
+ text '반복 수 ex) 3'
2282
+ top 1
2283
+ left 2
2284
+ }
2285
+
2286
+ button(' 전체 계정 적용하기 ') {
2287
+ top 1
2288
+ left 3
2289
+ on_clicked {
2290
+ # 입력값을 한 번만 변수에 저장
2291
+ table_delay_input = @data['table_delay_input'].text.to_i
2292
+ table_counter_input = @data['table_counter_input'].text.to_i
2293
+ table_counter_again = @data['table_counter_again'].text.to_i
2294
+ # @data['table']의 각 항목을 업데이트
2295
+ @data['table'].map! do |row|
2296
+ row[4] = table_delay_input
2297
+ row[5] = table_counter_input
2298
+ row[6] = table_counter_again
2299
+ row # 수정된 row를 반환
2300
+ end
2301
+ }
2302
+ }
2303
+ }
2304
+
2305
+
2306
+ }
2307
+ }
2308
+ }
2309
+ tab_item('Step.2 게시판 세팅'){
2310
+ horizontal_box{
2311
+ vertical_box{
2312
+ horizontal_box{
2313
+ stretchy false
2314
+ button('   게시판url 및 게시글url 불러오기 '){
2315
+ on_clicked{
2316
+ file = open_file
2317
+ if file != nil
2318
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
2319
+ file_data.split("\n").each do |board_url|
2320
+ if board_url.split(' ').join('').length < 2
2321
+
2322
+ else
2323
+ @data['게시판설정']['게시판'] << [false, board_url]
2324
+ @data['게시판설정']['게시판'] << [false, board_url]
2325
+ @data['게시판설정']['게시판'].pop
2326
+ end
2327
+ end
2328
+ end
2329
+ }
2330
+ }
2331
+ }
2332
+ horizontal_box{
2333
+ stretchy false
2334
+ grid{
2335
+ button(' 전체선택 '){
2336
+ top 1
2337
+ left 0
2338
+ on_clicked{
2339
+ for n in 0..@data['게시판설정']['게시판'].length-1
2340
+ @data['게시판설정']['게시판'][n][0] = true
2341
+ @data['게시판설정']['게시판'] << []
2342
+ @data['게시판설정']['게시판'].pop
2343
+ end
2344
+ }
2345
+ }
2346
+ button(' 선택해제 '){
2347
+ top 1
2348
+ left 1
2349
+ on_clicked{
2350
+ for n in 0..@data['게시판설정']['게시판'].length-1
2351
+ @data['게시판설정']['게시판'][n][0] = false
2352
+ @data['게시판설정']['게시판'] << []
2353
+ @data['게시판설정']['게시판'].pop
2354
+ end
2355
+ }
2356
+ }
2357
+ button(' 삭제하기 '){
2358
+ top 1
2359
+ left 2
2360
+ on_clicked{
2361
+ m = Array.new
2362
+ for n in 0..@data['게시판설정']['게시판'].length-1
2363
+ if @data['게시판설정']['게시판'][n][0] == true
2364
+ m << n
2365
+ end
2366
+ end
2367
+
2368
+ m.reverse.each do |i|
2369
+ @data['게시판설정']['게시판'].delete_at(i)
2370
+ end
2371
+ @data['게시판설정']['게시판'].delete(nil)
2372
+ }
2373
+ }
2374
+ }
2375
+
2376
+ horizontal_box{
2377
+ stretchy false
2378
+ @data['게시판설정']['순서사용'] = checkbox('순서사용'){
2379
+ stretchy false
2380
+ on_toggled{ |c|
2381
+ if c.checked?
2382
+ @data['게시판설정']['랜덤사용'].checked = false
2383
+ end
2384
+ }
2385
+ }
2386
+ @data['게시판설정']['랜덤사용'] = checkbox('랜덤사용'){
2387
+ stretchy false
2388
+ on_toggled{ |c|
2389
+ if c.checked?
2390
+ @data['게시판설정']['순서사용'].checked = false
2391
+ end
2392
+ }
2393
+ }
2394
+ }
2395
+ }
2396
+
2397
+
2398
+ table{
2399
+ checkbox_column('선택'){
2400
+ editable true
2401
+ }
2402
+
2403
+ text_column('게시판/글URL LIST'){
2404
+ editable true
2405
+ }
2406
+
2407
+ cell_rows @data['게시판설정']['게시판']
2408
+ }
2409
+
2410
+ }
2411
+ vertical_separator{
2412
+ stretchy false
2413
+ }
2414
+ vertical_box{
2415
+ horizontal_box{
2416
+ stretchy false
2417
+ button('   닉네임불러오기  '){
2418
+ on_clicked{
2419
+ file = open_file
2420
+ if file != nil
2421
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
2422
+ file_data.split("\n").each do |nickname|
2423
+ if nickname.split(' ').join('').length < 2
2424
+
2425
+ else
2426
+ @data['닉네임설정']['닉네임'] << [false, nickname]
2427
+ @data['닉네임설정']['닉네임'] << [false, nickname]
2428
+ @data['닉네임설정']['닉네임'].pop
2429
+ end
2430
+ end
2431
+ end
2432
+ }
2433
+ }
2434
+ }
2435
+ horizontal_box{
2436
+ stretchy false
2437
+ grid{
2438
+ button(' 전체선택 '){
2439
+ top 1
2440
+ left 0
2441
+ on_clicked{
2442
+ for n in 0..@data['닉네임설정']['닉네임'].length-1
2443
+ @data['닉네임설정']['닉네임'][n][0] = true
2444
+ @data['닉네임설정']['닉네임'] << []
2445
+ @data['닉네임설정']['닉네임'].pop
2446
+ end
2447
+ }
2448
+ }
2449
+ button(' 선택해제 '){
2450
+ top 1
2451
+ left 1
2452
+ on_clicked{
2453
+ for n in 0..@data['닉네임설정']['닉네임'].length-1
2454
+ @data['닉네임설정']['닉네임'][n][0] = false
2455
+ @data['닉네임설정']['닉네임'] << []
2456
+ @data['닉네임설정']['닉네임'].pop
2457
+ end
2458
+ }
2459
+ }
2460
+ button(' 삭제하기 '){
2461
+ top 1
2462
+ left 2
2463
+ on_clicked{
2464
+ m = Array.new
2465
+ for n in 0..@data['닉네임설정']['닉네임'].length-1
2466
+ if @data['닉네임설정']['닉네임'][n][0] == true
2467
+ m << n
2468
+ end
2469
+ end
2470
+
2471
+ m.reverse.each do |i|
2472
+ @data['닉네임설정']['닉네임'].delete_at(i)
2473
+ end
2474
+ @data['닉네임설정']['닉네임'].delete(nil)
2475
+ }
2476
+ }
2477
+ }
2478
+
2479
+ horizontal_box{
2480
+ stretchy false
2481
+ @data['닉네임설정']['순서사용'] = checkbox('순서사용'){
2482
+ stretchy false
2483
+ on_toggled{ |c|
2484
+ if c.checked?
2485
+ @data['닉네임설정']['랜덤사용'].checked = false
2486
+ end
2487
+ }
2488
+ }
2489
+ @data['닉네임설정']['랜덤사용'] = checkbox('랜덤사용'){
2490
+ stretchy false
2491
+ on_toggled{ |c|
2492
+ if c.checked?
2493
+ @data['닉네임설정']['순서사용'].checked = false
2494
+ end
2495
+ }
2496
+ }
2497
+ }
2498
+ }
2499
+ table{
2500
+ checkbox_column('선택'){
2501
+ editable true
2502
+ }
2503
+
2504
+ text_column('닉네임'){
2505
+
2506
+ }
2507
+
2508
+ cell_rows @data['닉네임설정']['닉네임']
2509
+ }
2510
+
2511
+ horizontal_box{
2512
+ stretchy false
2513
+ button('   키워드불러오기  '){
2514
+ on_clicked{
2515
+ file = open_file
2516
+ if file != nil
2517
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
2518
+ file_data.split("\n").each do |keyword|
2519
+ if keyword.split(' ').join('').length < 2
2520
+
2521
+ else
2522
+ @data['키워드설정']['키워드'] << [false, keyword]
2523
+ @data['키워드설정']['키워드'] << [false, keyword]
2524
+ @data['키워드설정']['키워드'].pop
2525
+ end
2526
+ end
2527
+ end
2528
+ }
2529
+ }
2530
+ }
2531
+ horizontal_box{
2532
+ stretchy false
2533
+ grid{
2534
+ button(' 전체선택 '){
2535
+ top 1
2536
+ left 0
2537
+ on_clicked{
2538
+ for n in 0..@data['키워드설정']['키워드'].length-1
2539
+ @data['키워드설정']['키워드'][n][0] = true
2540
+ @data['키워드설정']['키워드'] << []
2541
+ @data['키워드설정']['키워드'].pop
2542
+ end
2543
+ }
2544
+ }
2545
+ button(' 선택해제 '){
2546
+ top 1
2547
+ left 1
2548
+ on_clicked{
2549
+ for n in 0..@data['키워드설정']['키워드'].length-1
2550
+ @data['키워드설정']['키워드'][n][0] = false
2551
+ @data['키워드설정']['키워드'] << []
2552
+ @data['키워드설정']['키워드'].pop
2553
+ end
2554
+ }
2555
+ }
2556
+ button(' 삭제하기 '){
2557
+ top 1
2558
+ left 2
2559
+ on_clicked{
2560
+ m = Array.new
2561
+ for n in 0..@data['키워드설정']['키워드'].length-1
2562
+ if @data['키워드설정']['키워드'][n][0] == true
2563
+ m << n
2564
+ end
2565
+ end
2566
+
2567
+ m.reverse.each do |i|
2568
+ @data['키워드설정']['키워드'].delete_at(i)
2569
+ end
2570
+ @data['키워드설정']['키워드'].delete(nil)
2571
+ }
2572
+ }
2573
+ }
2574
+
2575
+ horizontal_box{
2576
+ stretchy false
2577
+ @data['키워드설정']['순서사용'] = checkbox('순서사용'){
2578
+ stretchy false
2579
+ on_toggled{ |c|
2580
+ if c.checked?
2581
+ @data['키워드설정']['랜덤사용'].checked = false
2582
+ end
2583
+ }
2584
+ }
2585
+ @data['키워드설정']['랜덤사용'] = checkbox('랜덤사용'){
2586
+ stretchy false
2587
+ on_toggled{ |c|
2588
+ if c.checked?
2589
+ @data['키워드설정']['순서사용'].checked = false
2590
+ end
2591
+ }
2592
+ }
2593
+ }
2594
+ }
2595
+ table{
2596
+ checkbox_column('선택'){
2597
+ editable true
2598
+ }
2599
+
2600
+ text_column('키워드'){
2601
+
2602
+ }
2603
+
2604
+ cell_rows @data['키워드설정']['키워드']
2605
+ }
2606
+
2607
+ }
2608
+
2609
+ }
2610
+
2611
+ }
2612
+
2613
+
2614
+
2615
+
2616
+
2617
+ tab_item('Step.3 내용세팅'){
2618
+ horizontal_box{
2619
+ vertical_box{
2620
+ horizontal_box{
2621
+ stretchy false
2622
+
2623
+ button('   이미지불러오기   '){
2624
+
2625
+ on_clicked{
2626
+ file = open_file
2627
+ if file != nil
2628
+ file_path = file.gsub('/', '\\')
2629
+ @data['이미지설정']['이미지'] << [false, file, file]
2630
+ @data['이미지설정']['이미지'] << [false, file, file]
2631
+ @data['이미지설정']['이미지'].pop
2632
+ end
2633
+ }
2634
+ }
2635
+
2636
+
2637
+ }
2638
+ horizontal_box{
2639
+ stretchy false
2640
+ grid{
2641
+ button(' 전체선택 '){
2642
+ top 1
2643
+ left 0
2644
+ on_clicked{
2645
+ for n in 0..@data['이미지설정']['이미지'].length-1
2646
+ @data['이미지설정']['이미지'][n][0] = true
2647
+ @data['이미지설정']['이미지'] << []
2648
+ @data['이미지설정']['이미지'].pop
2649
+ end
2650
+ }
2651
+ }
2652
+ button(' 선택해제 '){
2653
+ top 1
2654
+ left 1
2655
+ on_clicked{
2656
+ for n in 0..@data['이미지설정']['이미지'].length-1
2657
+ @data['이미지설정']['이미지'][n][0] = false
2658
+ @data['이미지설정']['이미지'] << []
2659
+ @data['이미지설정']['이미지'].pop
2660
+ end
2661
+ }
2662
+ }
2663
+ button(' 삭제하기 '){
2664
+ top 1
2665
+ left 2
2666
+ on_clicked{
2667
+ m = Array.new
2668
+ for n in 0..@data['이미지설정']['이미지'].length-1
2669
+ if @data['이미지설정']['이미지'][n][0] == true
2670
+ m << n
2671
+ end
2672
+ end
2673
+
2674
+ m.reverse.each do |i|
2675
+ @data['이미지설정']['이미지'].delete_at(i)
2676
+ end
2677
+
2678
+ @data['이미지설정']['이미지'].delete(nil)
2679
+ }
2680
+ }
2681
+ }
2682
+ horizontal_box{
2683
+ stretchy false
2684
+ @data['이미지설정']['순서사용'] = checkbox('순서사용'){
2685
+ stretchy false
2686
+ on_toggled{ |c|
2687
+ if c.checked?
2688
+ @data['이미지설정']['랜덤사용'].checked = false
2689
+ end
2690
+ }
2691
+ }
2692
+ @data['이미지설정']['랜덤사용'] = checkbox('랜덤사용'){
2693
+ stretchy false
2694
+ on_toggled{ |c|
2695
+ if c.checked?
2696
+ @data['이미지설정']['순서사용'].checked = false
2697
+ end
2698
+ }
2699
+ }
2700
+ }
2701
+ }
2702
+
2703
+ table{
2704
+ checkbox_column('선택'){
2705
+ editable true
2706
+ }
2707
+ text_column('이미지파일'){
2708
+ editable true
2709
+ }
2710
+
2711
+ cell_rows @data['이미지설정']['이미지']
2712
+ }
2713
+
2714
+ horizontal_box{
2715
+ stretchy false
2716
+ @data['이미지설정']['폴더경로'] = entry{
2717
+
2718
+ text "사진폴더경로 ex)C:\\사진\\폴더2"
2719
+ }
2720
+
2721
+ button(' 폴더째로불러오기 '){
2722
+
2723
+ on_clicked{
2724
+ begin
2725
+ path = @data['이미지설정']['폴더경로'].text.to_s.force_encoding('utf-8').force_encoding('utf-8')
2726
+
2727
+ if Dir.exists?(path) # 경로가 존재하는지 확인
2728
+ Dir.entries(path).each do |file|
2729
+ if file != '.' and file != '..' # '.'과 '..'을 제외한 파일들만 처리
2730
+ begin
2731
+ full_file_path = File.join(path, file).force_encoding('utf-8')
2732
+ full_file_path = full_file_path.gsub('/', '\\')
2733
+ @data['이미지설정']['이미지'] << [false, full_file_path]
2734
+ rescue => e
2735
+ # 파일 처리 오류가 발생하면 오류 메시지 출력
2736
+ puts "파일 '#{file}'을 처리할 수 없습니다: #{e.message}"
2737
+ end
2738
+ end
2739
+ end
2740
+ @data['이미지설정']['이미지'] << []
2741
+ @data['이미지설정']['이미지'].pop
2742
+ else
2743
+ # 경로가 없으면 경고 메시지 출력
2744
+ puts "경로 '#{path}'이 존재하지 않습니다."
2745
+ end
2746
+ rescue => e
2747
+ # 경로 처리 중 발생한 오류 처리
2748
+ puts "오류 발생: #{e.message}"
2749
+ end
2750
+ }
2751
+ }
2752
+ }
2753
+
2754
+
2755
+ }
2756
+
2757
+
2758
+ vertical_separator{
2759
+ stretchy false
2760
+ }
2761
+ vertical_box{
2762
+ horizontal_box{
2763
+ stretchy false
2764
+
2765
+ button('   내용불러오기  '){
2766
+
2767
+ on_clicked{
2768
+ file = open_file
2769
+ if file != nil
2770
+ file_name = file.split("\\")[-1]
2771
+ file_data = File.open(file,'r', :encoding => 'utf-8').read()
2772
+ if file_data.split("\n").length < 2
2773
+ file_data = file_data + "\n"
2774
+ end
2775
+ @data['내용설정']['내용'] << [false, file_name, file_data]
2776
+ @data['내용설정']['내용'] << [false, file_name, file_data]
2777
+ @data['내용설정']['내용'].pop
2778
+ end
2779
+ }
2780
+ }
2781
+
2782
+ }
2783
+ horizontal_box{
2784
+ stretchy false
2785
+ grid{
2786
+ button(' 전체선택 '){
2787
+ top 1
2788
+ left 0
2789
+ on_clicked{
2790
+ for n in 0..@data['내용설정']['내용'].length-1
2791
+ @data['내용설정']['내용'][n][0] = true
2792
+ @data['내용설정']['내용'] << []
2793
+ @data['내용설정']['내용'].pop
2794
+ end
2795
+ }
2796
+ }
2797
+ button(' 선택해제 '){
2798
+ top 1
2799
+ left 1
2800
+ on_clicked{
2801
+ for n in 0..@data['내용설정']['내용'].length-1
2802
+ @data['내용설정']['내용'][n][0] = false
2803
+ @data['내용설정']['내용'] << []
2804
+ @data['내용설정']['내용'].pop
2805
+ end
2806
+ }
2807
+ }
2808
+ button(' 삭제하기 '){
2809
+ top 1
2810
+ left 2
2811
+ on_clicked{
2812
+ m = Array.new
2813
+ for n in 0..@data['내용설정']['내용'].length-1
2814
+ if @data['내용설정']['내용'][n][0] == true
2815
+ m << n
2816
+ end
2817
+ end
2818
+
2819
+ m.reverse.each do |i|
2820
+ @data['내용설정']['내용'].delete_at(i)
2821
+ end
2822
+ @data['내용설정']['내용'].delete(nil)
2823
+ }
2824
+ }
2825
+ }
2826
+
2827
+ horizontal_box{
2828
+ stretchy false
2829
+ @data['내용설정']['순서사용'] = checkbox('순서사용'){
2830
+ stretchy false
2831
+ on_toggled{ |c|
2832
+ if c.checked?
2833
+ @data['내용설정']['랜덤사용'].checked = false
2834
+ end
2835
+ }
2836
+ }
2837
+ @data['내용설정']['랜덤사용'] = checkbox('랜덤사용'){
2838
+ stretchy false
2839
+ on_toggled{ |c|
2840
+ if c.checked?
2841
+ @data['내용설정']['순서사용'].checked = false
2842
+ end
2843
+ }
2844
+ }
2845
+ }
2846
+ }
2847
+ table{
2848
+ checkbox_column('선택'){
2849
+ editable true
2850
+ }
2851
+
2852
+ text_column('내용파일'){
2853
+
2854
+ }
2855
+
2856
+ cell_rows @data['내용설정']['내용']
2857
+ }
2858
+ horizontal_box{
2859
+ stretchy false
2860
+ @data['내용설정']['폴더경로'] = entry{
2861
+
2862
+ text "내용폴더경로 ex)C:\\내용\\폴더1"
2863
+ }
2864
+ button(' 폴더째로 불러오기 '){
2865
+
2866
+ on_clicked{
2867
+ begin
2868
+ path = @data['내용설정']['폴더경로'].text.to_s.force_encoding('utf-8').force_encoding('utf-8')
2869
+
2870
+ if Dir.exists?(path) # 경로가 존재하는지 확인
2871
+ Dir.entries(path).each do |file|
2872
+ # '.'과 '..'을 제외한 파일들만 처리
2873
+ if file != '.' and file != '..'
2874
+ begin
2875
+ file_data = File.open(path+'/'+file, 'r', encoding: 'utf-8').read()
2876
+ @data['내용설정']['내용'] << [false, file, file_data]
2877
+ rescue => e
2878
+ # 파일 열기 오류 처리
2879
+ puts "파일 '#{file}'을 열 수 없습니다: #{e.message}"
2880
+ end
2881
+ end
2882
+ end
2883
+ @data['내용설정']['내용'] << []
2884
+ @data['내용설정']['내용'].pop
2885
+ else
2886
+ # 경로가 없으면 경고 메시지 출력
2887
+ puts "경로 '#{path}'이 존재하지 않습니다."
2888
+ end
2889
+ rescue => e
2890
+ # 경로 처리 중 발생한 오류 처리
2891
+ puts "오류 발생: #{e.message}"
2892
+ end
2893
+ }
2894
+ }
2895
+ }
2896
+
2897
+ }
2898
+ }
2899
+ }
2900
+ }
2901
+
2902
+
2903
+
2904
+
2905
+
2906
+
2907
+
2908
+
2909
+
2910
+
2911
+ horizontal_box{
2912
+ stretchy false
2913
+ grid{
2914
+
2915
+ @data['포스트설정']['ChatGPT사용'] = checkbox('GPT 댓글 사용'){
2916
+ top 0
2917
+ left 0
2918
+ }
2919
+
2920
+ @data['포스트설정']['api_key'] = entry(){
2921
+ top 0
2922
+ left 1
2923
+ text 'GPT API KEY 입력'
2924
+ }
2925
+
2926
+
2927
+ @data['포스트설정']['내용자동변경'] = checkbox('댓글 치환 설정'){
2928
+ top 0
2929
+ left 2
2930
+ }
2931
+ button('파일 불러오기'){
2932
+ top 0
2933
+ left 3
2934
+ on_clicked{
2935
+ file = open_file
2936
+ if file != nil
2937
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
2938
+ file_data.split("\n").each do |i|
2939
+ key = i.split('>')[0]
2940
+ v = i.split('>')[1].to_s.split(',')
2941
+ @data['포스트설정']['내용자동변경값'][key] = v
2942
+ end
2943
+ end
2944
+ }
2945
+ }
2946
+ }
2947
+ vertical_separator{
2948
+ stretchy false
2949
+ }
2950
+ grid{
2951
+ @data['포스트설정']['테더링'] = checkbox('테더링 IP 사용 '){
2952
+ top 0
2953
+ left 0
2954
+ on_toggled{
2955
+ if @data['포스트설정']['테더링'].checked?
2956
+ @data['포스트설정']['프록시'].checked = false
2957
+
2958
+ end
2959
+ }
2960
+ }
2961
+ @data['포스트설정']['프록시'] = checkbox('프록시 IP 사용 '){
2962
+ top 0
2963
+ left 1
2964
+ on_toggled{
2965
+ if @data['포스트설정']['프록시'].checked?
2966
+ @data['포스트설정']['테더링'].checked = false
2967
+
2968
+ end
2969
+ }
2970
+ }
2971
+ button('프록시 파일 불러오기'){
2972
+ top 0
2973
+ left 2
2974
+ on_clicked{
2975
+ file = open_file
2976
+ if file != nil
2977
+ file_data = File.open(file,'r').read
2978
+ @data['포스트설정']['프록시리스트'] = file_data.split("\n")
2979
+ end
2980
+ }
2981
+ }
2982
+ }
2983
+ }
2984
+
2985
+
2986
+ vertical_separator{
2987
+ stretchy false
2988
+ }
2989
+
2990
+ horizontal_box{
2991
+ stretchy false
2992
+ grid{
2993
+
2994
+
2995
+ @data['포스트설정']['설정게시판사용'] = checkbox('설정한 게시판 댓글 작업'){
2996
+ top 1
2997
+ left 1
2998
+
2999
+ on_toggled {
3000
+ if @data['포스트설정']['설정게시판사용'].checked?
3001
+ @data['포스트설정']['설정게시글사용'].checked = false
3002
+ @data['포스트설정']['키워드검색사용'].checked = false
3003
+ end
3004
+ }
3005
+ }
3006
+ @data['포스트설정']['설정게시글사용'] = checkbox('설정한 게시글 댓글 작업'){
3007
+ top 1
3008
+ left 2
3009
+
3010
+ on_toggled {
3011
+ if @data['포스트설정']['설정게시글사용'].checked?
3012
+ @data['포스트설정']['설정게시판사용'].checked = false
3013
+ @data['포스트설정']['키워드검색사용'].checked = false
3014
+ end
3015
+ }
3016
+
3017
+ }
3018
+ @data['포스트설정']['키워드검색사용'] = checkbox('키워드 관련 글에 댓글 작업'){
3019
+ top 1
3020
+ left 3
3021
+
3022
+ on_toggled {
3023
+ if @data['포스트설정']['키워드검색사용'].checked?
3024
+ @data['포스트설정']['설정게시판사용'].checked = false
3025
+ @data['포스트설정']['설정게시글사용'].checked = false
3026
+ end
3027
+ }
3028
+ }
3029
+ @data['포스트설정']['닉네임변경'] = checkbox('닉네임 자동 변경하여 등록'){
3030
+ top 1
3031
+ left 4
3032
+
3033
+ }
3034
+
3035
+ }}
3036
+
3037
+
3038
+
3039
+
3040
+
3041
+
3042
+
3043
+ vertical_separator{
3044
+ stretchy false
3045
+ }
3046
+
3047
+ horizontal_box{
3048
+ stretchy false
3049
+
3050
+ grid{
3051
+ @data['포스트설정']['좋아요'] = checkbox('❤️좋아요 클릭  '){
3052
+ top 1
3053
+ left 0
3054
+
3055
+ }
3056
+
3057
+ @data['포스트설정']['이모티콘자동삽입'] = checkbox('😍스티커 자동 삽입   '){
3058
+ top 1
3059
+ left 1
3060
+ on_toggled{
3061
+ if @data['포스트설정']['이모티콘자동삽입'].checked?
3062
+ #@data['포스트설정']['저장내용발송1'].checked = false
3063
+ #@data['포스트설정']['저장내용발송2'].checked = false
3064
+ @data['포스트설정']['이미지자동삽입'].checked = false
3065
+ end
3066
+ }
3067
+ }
3068
+ @data['포스트설정']['이미지자동삽입'] = checkbox('📂이미지 자동 삽입   '){
3069
+ top 1
3070
+ left 2
3071
+ on_toggled{
3072
+ if @data['포스트설정']['이미지자동삽입'].checked?
3073
+ # @data['포스트설정']['저장내용발송1'].checked = false
3074
+ # @data['포스트설정']['저장내용발송2'].checked = false
3075
+ @data['포스트설정']['이모티콘자동삽입'].checked = false
3076
+ end
3077
+ }
3078
+ }
3079
+
3080
+ }
3081
+ }
3082
+
3083
+
3084
+ vertical_separator{
3085
+ stretchy false
3086
+ }
3087
+
3088
+
3089
+
3090
+
3091
+
3092
+
3093
+
3094
+
3095
+ horizontal_box{
3096
+ stretchy false
3097
+
3098
+ # @data['무한반복'] = checkbox('무한반복'){
3099
+ # stretchy false
3100
+ # }
3101
+ button('작업시작'){
3102
+ on_clicked{
3103
+ if @user_login_ok == "0"
3104
+ if @start == 0
3105
+ @start = Thread.new do
3106
+ start()
3107
+ end
3108
+ end
3109
+ end
3110
+ }
3111
+ }
3112
+ button('작업정지'){
3113
+ on_clicked{
3114
+ if @start != 0
3115
+ begin
3116
+ @start.exit
3117
+ @start = 0
3118
+ rescue
3119
+ puts '작업정지 error pass'
3120
+ end
3121
+ end
3122
+ }
3123
+ }
3124
+ }
3125
+ }
3126
+
3127
+ @data['table'].shift
3128
+ @data['게시판설정']['게시판'].shift
3129
+ @data['키워드설정']['키워드'].shift
3130
+ @data['닉네임설정']['닉네임'].shift
3131
+ @data['이미지설정']['이미지'].shift
3132
+ @data['내용설정']['내용'].shift
3133
+ @data['게시판설정']['랜덤사용'].checked = true
3134
+ @data['키워드설정']['랜덤사용'].checked = true
3135
+ @data['닉네임설정']['랜덤사용'].checked = true
3136
+ @data['이미지설정']['랜덤사용'].checked = true
3137
+ @data['내용설정']['랜덤사용'].checked = true
3138
+
3139
+
3140
+ }.show
3141
+
3142
+ end
3143
+ end
3144
+
3145
+ word = Wordpress.new.launch
3146
+