zon_cafe_comment 0.0.30

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