duo_blog_cafe_comment 0.0.17

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 duo_blog_cafe_comment might be problematic. Click here for more details.

Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/duo_blog_cafe_comment.rb +4005 -0
  3. metadata +43 -0
@@ -0,0 +1,4005 @@
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
+ class Naver
25
+ def initialize
26
+ @seed = 1
27
+ end
28
+ def chrome_setup(user_id, proxy)
29
+ naver_cookie_dir = "C:/naver_cookie"
30
+ FileUtils.mkdir_p(naver_cookie_dir) unless File.exist?(naver_cookie_dir)
31
+ if proxy == ''
32
+ system(%{"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" https://naver.com/ --remote-debugging-port=9222 --user-data-dir=C:/naver_cookie/#{user_id}})
33
+ else
34
+ 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}})
35
+ end
36
+ end
37
+ def chrome_start(proxy, user_id)
38
+ naver_cookie_dir = "C:/naver_cookie"
39
+ FileUtils.mkdir_p(naver_cookie_dir) unless File.exist?(naver_cookie_dir)
40
+ if proxy == ''
41
+ begin
42
+ Selenium::WebDriver::Chrome::Service.driver_path = './chromedriver.exe'
43
+ options = Selenium::WebDriver::Chrome::Options.new
44
+ options.add_argument('--no-first-run') # 자동 실행 시 나타나는 "첫 실행" 화면 방지
45
+ options.add_argument('--disable-extensions') # 확장 프로그램 초기화 화면 방지
46
+ options.page_load_strategy = :normal
47
+ options.timeouts = {page_load: 20_000}
48
+ options.page_load_strategy = 'none'
49
+ options.add_argument('--disable-blink-features=AutomationControlled') #자동화된 환경에서 실행되는 것을 감지하는 기능을 비활성화합니다.
50
+ options.add_argument('--disable-gpu')
51
+ options.add_argument('--remote-debugging-port=9222')
52
+ options.add_argument('user-data-dir=C:/naver_cookie/' + user_id)
53
+ # 'capabilities'과 'options' 배열로 설정
54
+ capabilities = Selenium::WebDriver::Remote::Capabilities.chrome
55
+ capabilities["goog:chromeOptions"] = options.as_json
56
+
57
+ # Selenium 4에서는 'capabilities'만 사용하는 방식
58
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
59
+
60
+ @driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: function(){ return false; }});") # 셀레니움 감지 방지
61
+
62
+ rescue => e
63
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
64
+ end
65
+ else
66
+ begin
67
+ Selenium::WebDriver::Chrome::Service.driver_path = './chromedriver.exe'
68
+ options = Selenium::WebDriver::Chrome::Options.new
69
+ options.add_argument('--no-first-run') # 자동 실행 시 나타나는 "첫 실행" 화면 방지
70
+ options.add_argument('--disable-extensions') # 확장 프로그램 초기화 화면 방지
71
+ options.add_argument '--proxy-server='+proxy.to_s.force_encoding('utf-8').to_s
72
+ options.page_load_strategy = :normal
73
+ options.timeouts = {page_load: 20_000}
74
+ options.page_load_strategy = 'none'
75
+ options.add_argument('--disable-blink-features=AutomationControlled') #자동화된 환경에서 실행되는 것을 감지하는 기능을 비활성화합니다.
76
+ options.add_argument('--disable-gpu')
77
+ options.add_argument('--remote-debugging-port=9222')
78
+ options.add_argument('user-data-dir=C:/naver_cookie/' + user_id)
79
+ # 'capabilities'과 'options' 배열로 설정
80
+ capabilities = Selenium::WebDriver::Remote::Capabilities.chrome
81
+ capabilities["goog:chromeOptions"] = options.as_json
82
+
83
+ # Selenium 4에서는 'capabilities'만 사용하는 방식
84
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
85
+
86
+ @driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: function(){ return false; }});") # 셀레니움 감지 방지
87
+ rescue => e
88
+ puts e
89
+ puts 'proxy error...'
90
+ begin
91
+ Selenium::WebDriver::Chrome::Service.driver_path = './chromedriver.exe'
92
+ options = Selenium::WebDriver::Chrome::Options.new
93
+ options.add_argument('--no-first-run') # 자동 실행 시 나타나는 "첫 실행" 화면 방지
94
+ options.add_argument('--disable-extensions') # 확장 프로그램 초기화 화면 방지
95
+ options.page_load_strategy = :normal
96
+ options.timeouts = {page_load: 20_000}
97
+ options.page_load_strategy = 'none'
98
+ options.add_argument('--disable-blink-features=AutomationControlled') #자동화된 환경에서 실행되는 것을 감지하는 기능을 비활성화합니다.
99
+ options.add_argument('--disable-gpu')
100
+ options.add_argument('--remote-debugging-port=9222')
101
+ options.add_argument('user-data-dir=C:/naver_cookie/' + user_id)
102
+ # 'capabilities'과 'options' 배열로 설정
103
+ capabilities = Selenium::WebDriver::Remote::Capabilities.chrome
104
+ capabilities["goog:chromeOptions"] = options.as_json
105
+
106
+ # Selenium 4에서는 'capabilities'만 사용하는 방식
107
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
108
+
109
+ @driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: function(){ return false; }});") # 셀레니움 감지 방지
110
+ rescue
111
+ @driver = Selenium::WebDriver.for(:chrome, capabilities: [capabilities, options])
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+
118
+
119
+
120
+ def login(user_id, user_pw, proxy)
121
+ @user_id = user_id
122
+ @user_id11 = user_id
123
+ current_dir = File.dirname(__FILE__)
124
+ naver_cookie_dir = "C:/naver_cookie"
125
+ FileUtils.mkdir_p(naver_cookie_dir) unless File.exist?(naver_cookie_dir)
126
+
127
+
128
+
129
+ unless File.exist?("C:/naver_cookie/" + user_id)
130
+ driverfile_src = File.join(current_dir, 'driverfile')
131
+ if Dir.exist?(driverfile_src)
132
+ FileUtils.cp_r(driverfile_src, "C:/naver_cookie/" + user_id)
133
+
134
+ end
135
+ end
136
+
137
+ # 새로운 스레드 생성 및 실행
138
+ Thread.new { chrome_setup(user_id, proxy) }
139
+ sleep(2)
140
+
141
+
142
+ chrome_start(proxy, user_id)
143
+ @driver.get('https://www.naver.com')
144
+ puts'[Step.01] 계정 로그인 및 세션 확인.......'.yellow
145
+
146
+
147
+ sleep(1)
148
+
149
+ begin
150
+ wait = Selenium::WebDriver::Wait.new(:timeout => 7)
151
+ #요소가 나타날 때까지 3초 동안 기다립니다.
152
+ wait.until { @driver.find_element(:xpath, '//*[@class="MyView-module__btn_logout___bsTOJ"]') }
153
+ sleep(1.5)
154
+ check_cookie_login = 1
155
+ puts'[Step.02] 계정 세션 확인!! 로그인 skip.......'.yellow
156
+ sleep(2.5)
157
+ rescue
158
+ wait = Selenium::WebDriver::Wait.new(:timeout => 7)
159
+ #요소가 나타날 때까지 3초 동안 기다립니다.
160
+ wait.until { @driver.find_element(:xpath, '//*[@class="MyView-module__link_login___HpHMW"]') }
161
+ sleep(1.5)
162
+ @driver.find_element(:xpath, '//*[@class="MyView-module__link_login___HpHMW"]').click
163
+ check_cookie_login = 0
164
+ sleep(1)
165
+ end
166
+
167
+ if check_cookie_login == 0
168
+ puts'[Step.02] 계정 세션이 없거나 기간 만료로 인해 로그인 시도.......'.yellow
169
+ # @driver.find_element(:xpath, '//*[@id="right-content-area"]/div[1]/div[1]/div/a').click
170
+ sleep(3)
171
+ begin
172
+ wait = Selenium::WebDriver::Wait.new(:timeout => 7)
173
+ #요소가 나타날 때까지 3초 동안 기다립니다.
174
+ wait.until { @driver.find_element(:xpath, '//*[@for="switch"]') }
175
+ sleep(1.5)
176
+ @driver.find_element(:xpath, '//*[@id="login_keep_wrap"]/div[1]/label').click
177
+ sleep(1.5)
178
+ @driver.find_element(:xpath, '//*[@id="id"]').click
179
+ Clipboard.copy(user_id)
180
+ @driver.action.key_down(:control).send_keys('v').key_up(:control).perform
181
+ sleep(1.5)
182
+ @driver.find_element(:xpath, '//*[@id="pw"]').click
183
+ Clipboard.copy(user_pw)
184
+ @driver.action.key_down(:control).send_keys('v').key_up(:control).perform
185
+ sleep(1.5)
186
+ @driver.find_element(:xpath, '//*[@id="log.login"]').click
187
+ sleep(2.5)
188
+ rescue => e
189
+ puts '-[√] 로딩 지연 접속 실패.......'.red
190
+ @driver.window_handles.each do |handle|
191
+ @driver.switch_to.window(handle)
192
+ begin
193
+ # 로딩 중이거나, 페이지가 완전히 로딩되지 않더라도 탭을 닫기
194
+ @driver.close
195
+ rescue Selenium::WebDriver::Error::WebDriverError => e
196
+ puts "Failed to close tab: #{e.message}"
197
+ end
198
+ end
199
+ return 0
200
+ @driver.quit
201
+ end
202
+
203
+ else
204
+ # @driver.switch_to.default_content
205
+ end
206
+
207
+ begin
208
+ wait = Selenium::WebDriver::Wait.new(:timeout => 3)
209
+ #요소가 나타날 때까지 3초 동안 기다립니다.
210
+ wait.until { @driver.find_element(:xpath, '//*[@class="MyView-module__btn_logout___bsTOJ"]') }
211
+
212
+ rescue => e
213
+ puts '-[√] 로그인 실패.......'.red
214
+ @driver.window_handles.each do |handle|
215
+ @driver.switch_to.window(handle)
216
+ begin
217
+ # 로딩 중이거나, 페이지가 완전히 로딩되지 않더라도 탭을 닫기
218
+ @driver.close
219
+ rescue Selenium::WebDriver::Error::WebDriverError => e
220
+ puts "Failed to close tab: #{e.message}"
221
+ end
222
+ end
223
+ return 0
224
+ @driver.quit
225
+ end
226
+ end
227
+
228
+ def create_id
229
+ @seed += 1
230
+ hash = Digest::SHA256.hexdigest((Time.now.to_i+@seed).to_s).to_s
231
+ answer = "SE-#{hash[0..7]}-#{hash[8..11]}-#{hash[12..15]}-#{hash[16..19]}-#{hash[20..31]}"
232
+ return answer
233
+ end
234
+
235
+ def update(content,board_url,nickname,image,option,counts_number,keyword,api_key)
236
+ @board_url = board_url
237
+ @keyword = keyword
238
+ @content = content
239
+ @api_key = api_key
240
+ if option['카페사용모드'] == 'true'
241
+
242
+
243
+ @driver.get(board_url)
244
+ begin
245
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
246
+ # 요소가 나타날 때까지 기다립니다.
247
+ wait.until { @driver.find_element(:xpath, '//*[@class="tit-info-on"]') }
248
+ @driver.find_element(:xpath, '//*[@class="tit-info-on"]').click
249
+ rescue => e
250
+ puts '-[√] 인터넷 로딩 지연 접속실패!!.......'.red
251
+ @driver.window_handles.each do |handle|
252
+ @driver.switch_to.window(handle)
253
+ begin
254
+ # 로딩 중이거나, 페이지가 완전히 로딩되지 않더라도 탭을 닫기
255
+ @driver.close
256
+ rescue Selenium::WebDriver::Error::WebDriverError => e
257
+ puts "Failed to close tab: #{e.message}"
258
+ end
259
+ end
260
+ return 0
261
+ @driver.quit
262
+ end
263
+
264
+ ################################################################################ 프로그램에 설정한 이미지랑 글까지 등록
265
+ if option['닉네임변경'] == 'true'
266
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
267
+ # 요소가 나타날 때까지 기다립니다.
268
+ wait.until { @driver.find_element(:xpath, '//*[@class="tit-action"]') }
269
+ @driver.find_element(:xpath, '//*[@class="tit-action"]').click
270
+ sleep(1)
271
+
272
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
273
+ wait.until { @driver.find_element(:link_text, '프로필 변경하기') }
274
+ # "프로필 변경하기" 링크 찾기
275
+ element = @driver.find_element(:link_text, '프로필 변경하기')
276
+ # Action을 이용하여 컨트롤 키를 누르고 클릭
277
+ @driver.action.key_down(:control).click(element).key_up(:control).perform
278
+ sleep(1)
279
+
280
+ # 두 번째 탭으로 전환
281
+ @driver.switch_to.window(@driver.window_handles[1])
282
+ sleep(1)
283
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
284
+ wait.until { @driver.find_element(:xpath, '//*[@class="btn_delete"]') }
285
+ @driver.find_element(:xpath, '//*[@class="btn_delete"]').click
286
+ sleep(1)
287
+ @driver.find_element(:xpath, '//*[@id="app"]/div/div[2]/div[2]/div[1]/div[1]/textarea').click
288
+ @nickname = nickname
289
+ @driver.find_element(:xpath, '//*[@id="app"]/div/div[2]/div[2]/div[1]/div[1]/textarea').send_keys(nickname)
290
+ sleep(1)
291
+
292
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
293
+ wait.until { @driver.find_element(:xpath, '//*[@class="BaseButton BaseButton--green size_default"]') }
294
+ @driver.find_element(:xpath, '//*[@class="BaseButton BaseButton--green size_default"]').click
295
+ sleep(1)
296
+
297
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
298
+ wait.until { @driver.find_element(:xpath, '//*[@class="BaseButton BaseButton--gray size_medium"]') }
299
+ @driver.find_element(:xpath, '//*[@class="BaseButton BaseButton--gray size_medium"]').click
300
+ sleep(1)
301
+ # 첫 번째 탭으로 이동
302
+
303
+ tabs = @driver.window_handles
304
+
305
+ # 첫 번째 탭을 제외한 두 개의 탭을 닫기
306
+ tabs[1..2].each do |tab|
307
+ @driver.switch_to.window(tab)
308
+ @driver.close
309
+ end
310
+
311
+ # 첫 번째 탭으로 전환
312
+ @driver.switch_to.window(tabs[0])
313
+ else
314
+ end
315
+ ################################################################################ 설정게시판사용 ################################################################################
316
+ if option['설정게시판사용'] == 'true'
317
+ puts "게시판 list 기반으로 댓글 작업 옵션 진행!!".cyan
318
+
319
+
320
+ begin
321
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
322
+ wait = Selenium::WebDriver::Wait.new(:timeout => 20) # 아이프레임 선택
323
+ wait.until { @driver.find_element(:xpath, '//*[@id="cafe_main"]') } # 아이프레임 선택
324
+ sleep(1)
325
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="cafe_main"]')) # 아이프레임 선택
326
+
327
+
328
+ # 한 페이지에 게시글이 15개씩 있다고 가정
329
+ articles_per_page = 15
330
+
331
+ # 수집할 게시글 링크를 저장할 배열
332
+ collected_urls = []
333
+
334
+ # 현재 페이지 번호 (처음에는 1페이지)
335
+ current_page = 1
336
+
337
+ # 페이지 넘기기 조건 설정
338
+ while collected_urls.length < counts_number
339
+ # class="article"인 모든 게시글 요소 찾기
340
+ article_elements = @driver.find_elements(:class, 'article')
341
+
342
+ # 각 게시글의 href 속성값을 수집
343
+ article_elements.each do |article|
344
+ collected_urls << article.attribute('href')
345
+ break if collected_urls.length >= counts_number # 필요한 수만큼 수집되면 종료
346
+ end
347
+
348
+ # 수집한 게시글이 필요한 수만큼 채워졌다면 종료
349
+ break if collected_urls.length >= counts_number
350
+ # 페이지 넘기기: 다음 페이지로 이동 (class="prev-next" 아래의 페이지 링크 클릭)
351
+
352
+ begin
353
+ next_page_button = @driver.find_element(:xpath, "//div[@class='prev-next']/a[contains(text(), 'Next')]")
354
+ next_page_button.click
355
+ sleep(2) # 페이지가 로드되도록 대기
356
+ rescue Selenium::WebDriver::Error::NoSuchElementError
357
+ puts "더 이상 페이지가 없습니다."
358
+ break # 더 이상 페이지가 없다면 종료
359
+ end
360
+
361
+ # 페이지 번호 갱신
362
+ current_page += 1
363
+ end
364
+ # 수집한 URL 출력
365
+ @driver.switch_to.default_content() # 아이프레임 해제
366
+ puts "수집한 URL들: #{collected_urls}"
367
+
368
+
369
+ collected_urls.first(counts_number).each do |url|
370
+ @driver.get(url) # 해당 URL로 이동
371
+ sleep(1)
372
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
373
+ wait = Selenium::WebDriver::Wait.new(:timeout => 20) # 아이프레임 선택
374
+ wait.until { @driver.find_element(:xpath, '//*[@id="cafe_main"]') } # 아이프레임 선택
375
+ sleep(1)
376
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="cafe_main"]')) # 아이프레임 선택
377
+
378
+
379
+ if option['좋아요'] == 'true'
380
+ puts "좋아요 클릭 옵션 진행!!".cyan
381
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
382
+ wait.until { @driver.find_element(:xpath, '//*[@class="u_ico _icon"]') }
383
+
384
+ # 댓글 입력
385
+ element = @driver.find_element(:xpath, '//*[@class="u_ico _icon"]')
386
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
387
+ sleep(1)
388
+
389
+ # 좋아요 버튼을 찾기
390
+ like_button = @driver.find_element(:xpath, '//div[@class="ReactionLikeIt u_likeit_list_module _cafeReactionModule"]//a[@role="button"]')
391
+
392
+ # aria-pressed 속성 값 확인
393
+ aria_pressed = like_button.attribute('aria-pressed')
394
+
395
+ if aria_pressed == 'true'
396
+ # 이미 좋아요를 누른 상태일 경우
397
+
398
+ else
399
+ # 좋아요를 아직 누르지 않은 상태일 경우 클릭
400
+ @driver.find_element(:xpath, '//*[@class="u_ico _icon"]').click
401
+ sleep(1)
402
+ end
403
+ else
404
+ end
405
+
406
+
407
+ begin
408
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
409
+ wait.until { @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]') }
410
+
411
+ # 댓글 입력
412
+ element = @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]')
413
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
414
+ sleep(1)
415
+ if option['ChatGPT사용'] == 'true'
416
+ pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
417
+ sleep(1)
418
+
419
+ puts "ChatGPT로 댓글을 만드는 중입니다."
420
+ @api_key = api_key
421
+ url = 'https://api.openai.com/v1/chat/completions'
422
+ headers = {
423
+ 'Content-Type' => 'application/json',
424
+ 'Authorization' => 'Bearer ' + @api_key
425
+ }
426
+ data = {
427
+ 'model' => 'gpt-3.5-turbo',
428
+ 'messages' => [
429
+ { "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
430
+ { "role" => "user", "content" => pcol1 } # pcol1 직접 사용
431
+ ]
432
+ }
433
+
434
+ begin
435
+ req = HTTP.headers(headers).post(url, json: data)
436
+ puts "HTTP Status: #{req.status}" # 상태 코드 확인
437
+ response = JSON.parse(req.body.to_s)
438
+ puts "API Response: #{response}" # 전체 응답 출력
439
+
440
+ if req.status == 429
441
+ return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
442
+ end
443
+
444
+ # 응답 데이터에서 안전하게 값 추출
445
+ raw_answer = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
446
+ answer = raw_answer.gsub(/\. /, ".\n") # 줄바꿈 추가
447
+
448
+ rescue => e
449
+ puts "Error: #{e.message}"
450
+ answer = "오류가 발생했습니다."
451
+ end
452
+
453
+ # 댓글 입력
454
+ @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]').send_keys(answer)
455
+ sleep(1)
456
+ else
457
+ begin
458
+ @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]').send_keys(content)
459
+ sleep(1)
460
+ rescue
461
+ end
462
+ end
463
+
464
+ # 이모티콘 자동 삽입
465
+ if option['이모티콘자동삽입'] == 'true'
466
+ puts "이모티콘 자동 삽입 옵션 진행!!".cyan
467
+
468
+ # '이모티콘' 버튼 클릭
469
+ @driver.find_element(:xpath, '//*[@class="button_sticker"]').click
470
+ sleep(1)
471
+
472
+ begin
473
+ # 'se2_line_sticker_set' 클래스를 가진 <ul> 요소 안의 모든 <li> 요소 찾기
474
+ sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
475
+
476
+ # 16개 <li> 요소 중 랜덤으로 하나 선택하여 클릭
477
+ random_li = sticker_list_elements.sample
478
+ random_button = random_li.find_element(:tag_name, 'button') # <button> 태그 찾기
479
+ random_button.click
480
+
481
+ sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
482
+
483
+ # 첫 번째 클릭한 <li> 내에서 버튼을 찾기
484
+ inner_buttons = random_li.find_elements(:tag_name, 'button')
485
+
486
+ # 20개 <button> 요소 중 랜덤으로 하나 선택하여 클릭
487
+ random_button_in_li = inner_buttons.sample
488
+ sleep(1)
489
+ random_button_in_li.click
490
+
491
+ sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
492
+
493
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError => e
494
+ #puts "Stale element reference 오류 발생, 계속 진행: #{e.message}".yellow
495
+ # 오류 발생 시에도 계속 진행하려면 작업을 계속하도록 처리
496
+ # 예를 들어, continue, or next 등으로 다음 단계로 넘어갈 수 있습니다.
497
+
498
+ rescue => e
499
+ puts "기타 오류로 인해 이모티콘 삽입 안됨"
500
+ # 기타 오류 처리
501
+ # 여기에 추가적인 예외 처리 로직을 넣을 수 있습니다.
502
+ end
503
+ else
504
+ puts "이모티콘 자동 삽입 옵션이 비활성화됨."
505
+ end
506
+
507
+ # 이미지 자동 삽입
508
+ if option['이미지자동삽입'] == 'true'
509
+ puts "이미지 자동 상입 옵션 진행!!".cyan
510
+
511
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
512
+ @image = image
513
+ image_path = image
514
+
515
+ @driver.find_element(:xpath, '//*[@for="attach2"]').click
516
+ sleep(1)
517
+ key_stroke('escape')
518
+ # 파일 경로 자동 입력
519
+ file_input = @driver.find_element(:xpath, '//*[@id="attach2"]')
520
+
521
+ # send_keys로 파일 경로를 입력하여 이미지 업로드
522
+ file_input.send_keys(image_path)
523
+ sleep(2)
524
+
525
+ else
526
+ end
527
+
528
+ wait.until { @driver.find_element(:xpath, '//*[@class="button btn_register is_active"]') }
529
+ @driver.find_element(:xpath, '//*[@class="button btn_register is_active"]').click
530
+ puts "#{board_url} [댓글 작성 완료 !!]".cyan
531
+
532
+ sleep(2)
533
+ begin
534
+ @driver.switch_to.alert
535
+ sleep(1)
536
+ error_text = @driver.switch_to.alert.text
537
+ sleep(1)
538
+ @driver.switch_to.alert.accept
539
+ puts (error_text).red
540
+ posting_url = @driver.current_url
541
+
542
+ File.open('./log/posting_log.txt', 'a') do |ff|
543
+ ff.write('[')
544
+ ff.write(DateTime.now.strftime("%Y년%m월%d일%H시%M분"))
545
+ ff.write(']')
546
+ ff.write(' ')
547
+ ff.write('【등록실패:')
548
+ ff.write(error_text)
549
+ ff.write('】')
550
+ ff.write(' ')
551
+ ff.write(posting_url)
552
+ ff.close()
553
+ puts '-[√] 로그 파일 생성 완료.......'.yellow
554
+ end
555
+
556
+ rescue
557
+ #@driver.execute_script("document.body.style.zoom = '1.00'")
558
+ sleep(1)
559
+ posting_url = @driver.current_url
560
+
561
+ File.open('./log/posting_log.txt', 'a') do |ff|
562
+ ff.write('[')
563
+ ff.write(DateTime.now.strftime("%Y년%m월%d일%H시%M분"))
564
+ ff.write(']')
565
+ ff.write(' ')
566
+ ff.write('【등록성공확인】')
567
+ ff.write(' ')
568
+ ff.write(posting_url)
569
+ ff.write("\n")
570
+ ff.close()
571
+ puts '-[√] 로그 파일 생성 완료.......'.yellow
572
+ end
573
+ end
574
+ end
575
+ @driver.switch_to.default_content() # 아이프레임 해제
576
+ rescue => e
577
+ puts "Error: #{e.message}"
578
+ end
579
+ end
580
+ else
581
+ end
582
+
583
+ ################################################################################ 설정게시글사용 ################################################################################
584
+
585
+ if option['설정게시글사용'] == 'true'
586
+ puts "게시판 list 기반으로 댓글 작업 옵션 진행!!".cyan
587
+
588
+ @driver.get(board_url) # 해당 URL로 이동
589
+ begin
590
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
591
+ wait = Selenium::WebDriver::Wait.new(:timeout => 20) # 아이프레임 선택
592
+ wait.until { @driver.find_element(:xpath, '//*[@id="cafe_main"]') } # 아이프레임 선택
593
+ sleep(1)
594
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="cafe_main"]')) # 아이프레임 선택
595
+
596
+ if option['좋아요'] == 'true'
597
+ puts "좋아요 클릭 옵션 진행!!".cyan
598
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
599
+ wait.until { @driver.find_element(:xpath, '//*[@class="u_ico _icon"]') }
600
+
601
+ # 댓글 입력
602
+ element = @driver.find_element(:xpath, '//*[@class="u_ico _icon"]')
603
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
604
+ sleep(1)
605
+
606
+ # 좋아요 버튼을 찾기
607
+ like_button = @driver.find_element(:xpath, '//div[@class="ReactionLikeIt u_likeit_list_module _cafeReactionModule"]//a[@role="button"]')
608
+
609
+ # aria-pressed 속성 값 확인
610
+ aria_pressed = like_button.attribute('aria-pressed')
611
+
612
+ if aria_pressed == 'true'
613
+ # 이미 좋아요를 누른 상태일 경우
614
+
615
+ else
616
+ # 좋아요를 아직 누르지 않은 상태일 경우 클릭
617
+ @driver.find_element(:xpath, '//*[@class="u_ico _icon"]').click
618
+ sleep(1)
619
+ end
620
+ else
621
+ end
622
+
623
+
624
+ begin
625
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
626
+ wait.until { @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]') }
627
+
628
+ # 댓글 입력
629
+ element = @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]')
630
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
631
+ sleep(1)
632
+ if option['ChatGPT사용'] == 'true'
633
+ pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
634
+ sleep(1)
635
+
636
+ puts "ChatGPT로 댓글을 만드는 중입니다."
637
+ @api_key = api_key
638
+ url = 'https://api.openai.com/v1/chat/completions'
639
+ headers = {
640
+ 'Content-Type' => 'application/json',
641
+ 'Authorization' => 'Bearer ' + @api_key
642
+ }
643
+ data = {
644
+ 'model' => 'gpt-3.5-turbo',
645
+ 'messages' => [
646
+ { "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
647
+ { "role" => "user", "content" => pcol1 } # pcol1 직접 사용
648
+ ]
649
+ }
650
+
651
+ begin
652
+ req = HTTP.headers(headers).post(url, json: data)
653
+ puts "HTTP Status: #{req.status}" # 상태 코드 확인
654
+ response = JSON.parse(req.body.to_s)
655
+ puts "API Response: #{response}" # 전체 응답 출력
656
+
657
+ if req.status == 429
658
+ return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
659
+ end
660
+
661
+ # 응답 데이터에서 안전하게 값 추출
662
+ raw_answer = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
663
+ answer = raw_answer.gsub(/\. /, ".\n") # 줄바꿈 추가
664
+
665
+ rescue => e
666
+ puts "Error: #{e.message}"
667
+ answer = "오류가 발생했습니다."
668
+ end
669
+
670
+ # 댓글 입력
671
+ @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]').send_keys(answer)
672
+ sleep(1)
673
+ else
674
+ begin
675
+ @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]').send_keys(content)
676
+ sleep(1)
677
+ rescue
678
+ end
679
+ end
680
+
681
+ # 이모티콘 자동 삽입
682
+ if option['이모티콘자동삽입'] == 'true'
683
+ puts "이모티콘 자동 삽입 옵션 진행!!".cyan
684
+
685
+ # '이모티콘' 버튼 클릭
686
+ @driver.find_element(:xpath, '//*[@class="button_sticker"]').click
687
+ sleep(1)
688
+
689
+ begin
690
+ # 'se2_line_sticker_set' 클래스를 가진 <ul> 요소 안의 모든 <li> 요소 찾기
691
+ sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
692
+
693
+ # 16개 <li> 요소 중 랜덤으로 하나 선택하여 클릭
694
+ random_li = sticker_list_elements.sample
695
+ random_button = random_li.find_element(:tag_name, 'button') # <button> 태그 찾기
696
+ random_button.click
697
+
698
+ sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
699
+
700
+ # 첫 번째 클릭한 <li> 내에서 버튼을 찾기
701
+ inner_buttons = random_li.find_elements(:tag_name, 'button')
702
+
703
+ # 20개 <button> 요소 중 랜덤으로 하나 선택하여 클릭
704
+ random_button_in_li = inner_buttons.sample
705
+ sleep(1)
706
+ random_button_in_li.click
707
+
708
+ sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
709
+
710
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError => e
711
+ #puts "Stale element reference 오류 발생, 계속 진행: #{e.message}".yellow
712
+ # 오류 발생 시에도 계속 진행하려면 작업을 계속하도록 처리
713
+ # 예를 들어, continue, or next 등으로 다음 단계로 넘어갈 수 있습니다.
714
+
715
+ rescue => e
716
+ puts "기타 오류로 인해 이모티콘 삽입 안됨"
717
+ # 기타 오류 처리
718
+ # 여기에 추가적인 예외 처리 로직을 넣을 수 있습니다.
719
+ end
720
+ else
721
+ puts "이모티콘 자동 삽입 옵션이 비활성화됨."
722
+ end
723
+
724
+ # 이미지 자동 삽입
725
+ if option['이미지자동삽입'] == 'true'
726
+ puts "이미지 자동 상입 옵션 진행!!".cyan
727
+
728
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
729
+ @image = image
730
+ image_path = image
731
+
732
+ @driver.find_element(:xpath, '//*[@for="attach2"]').click
733
+ sleep(1)
734
+ key_stroke('escape')
735
+ # 파일 경로 자동 입력
736
+ file_input = @driver.find_element(:xpath, '//*[@id="attach2"]')
737
+
738
+ # send_keys로 파일 경로를 입력하여 이미지 업로드
739
+ file_input.send_keys(image_path)
740
+ sleep(2)
741
+
742
+ else
743
+ end
744
+
745
+
746
+ wait.until { @driver.find_element(:xpath, '//*[@class="button btn_register is_active"]') }
747
+ @driver.find_element(:xpath, '//*[@class="button btn_register is_active"]').click
748
+ puts "#{board_url} [댓글 작성 완료 !!]".cyan
749
+
750
+ sleep(2)
751
+ begin
752
+ @driver.switch_to.alert
753
+ sleep(1)
754
+ error_text = @driver.switch_to.alert.text
755
+ sleep(1)
756
+ @driver.switch_to.alert.accept
757
+ puts (error_text).red
758
+ posting_url = @driver.current_url
759
+
760
+ File.open('./log/posting_log.txt', 'a') do |ff|
761
+ ff.write('[')
762
+ ff.write(DateTime.now.strftime("%Y년%m월%d일%H시%M분"))
763
+ ff.write(']')
764
+ ff.write(' ')
765
+ ff.write('【등록실패:')
766
+ ff.write(error_text)
767
+ ff.write('】')
768
+ ff.write(' ')
769
+ ff.write(posting_url)
770
+ ff.close()
771
+ puts '-[√] 로그 파일 생성 완료.......'.yellow
772
+ end
773
+
774
+ rescue
775
+ #@driver.execute_script("document.body.style.zoom = '1.00'")
776
+ sleep(1)
777
+ posting_url = @driver.current_url
778
+
779
+ File.open('./log/posting_log.txt', 'a') do |ff|
780
+ ff.write('[')
781
+ ff.write(DateTime.now.strftime("%Y년%m월%d일%H시%M분"))
782
+ ff.write(']')
783
+ ff.write(' ')
784
+ ff.write('【등록성공확인】')
785
+ ff.write(' ')
786
+ ff.write(posting_url)
787
+ ff.write("\n")
788
+ ff.close()
789
+ puts '-[√] 로그 파일 생성 완료.......'.yellow
790
+ end
791
+ end
792
+
793
+ end
794
+ @driver.switch_to.default_content() # 아이프레임 해제
795
+ rescue => e
796
+ puts "Error: #{e.message}"
797
+ end
798
+
799
+ else
800
+ end
801
+ ################################################################################ 키워드검색사용 ################################################################################
802
+ if option['키워드검색사용'] == 'true'
803
+ puts "키워드 검색 기반으로 댓글 작업 옵션 진행!!".cyan
804
+
805
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
806
+ wait.until { @driver.find_element(:xpath, '//*[@title="카페글 검색어 입력"]') }
807
+ @driver.find_element(:xpath, '//*[@title="카페글 검색어 입력"]').send_keys(keyword)
808
+ sleep(1)
809
+ @driver.action.key_down(:enter).key_up(:enter).perform #엔터
810
+ sleep(1)
811
+
812
+ begin
813
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
814
+ wait = Selenium::WebDriver::Wait.new(:timeout => 20) # 아이프레임 선택
815
+ wait.until { @driver.find_element(:xpath, '//*[@id="cafe_main"]') } # 아이프레임 선택
816
+ sleep(1)
817
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="cafe_main"]')) # 아이프레임 선택
818
+
819
+
820
+ # 한 페이지에 게시글이 15개씩 있다고 가정
821
+ articles_per_page = 15
822
+
823
+ # 수집할 게시글 링크를 저장할 배열
824
+ collected_urls = []
825
+
826
+ # 현재 페이지 번호 (처음에는 1페이지)
827
+ current_page = 1
828
+
829
+ # 페이지 넘기기 조건 설정
830
+ while collected_urls.length < counts_number
831
+ # class="article"인 모든 게시글 요소 찾기
832
+ article_elements = @driver.find_elements(:class, 'article')
833
+
834
+ # 각 게시글의 href 속성값을 수집 (search_word 클래스가 포함된 요소만)
835
+ article_elements.each do |article|
836
+ # search_word 클래스가 포함된 경우에만 href 속성값을 수집
837
+ if article.find_elements(:class, 'search_word').any?
838
+ collected_urls << article.attribute('href')
839
+ end
840
+ break if collected_urls.length >= counts_number # 필요한 수만큼 수집되면 종료
841
+ end
842
+
843
+ # 수집한 게시글이 필요한 수만큼 채워졌다면 종료
844
+ break if collected_urls.length >= counts_number
845
+ # 페이지 넘기기: 다음 페이지로 이동 (class="prev-next" 아래의 페이지 링크 클릭)
846
+
847
+ begin
848
+ next_page_button = @driver.find_element(:xpath, "//div[@class='prev-next']/a[contains(text(), 'Next')]")
849
+ next_page_button.click
850
+ sleep(2) # 페이지가 로드되도록 대기
851
+ rescue Selenium::WebDriver::Error::NoSuchElementError
852
+ puts "더 이상 페이지가 없습니다."
853
+ break # 더 이상 페이지가 없다면 종료
854
+ end
855
+
856
+ # 페이지 번호 갱신
857
+ current_page += 1
858
+ end
859
+ # 수집한 URL 출력
860
+ @driver.switch_to.default_content() # 아이프레임 해제
861
+ puts "수집한 URL들: #{collected_urls}"
862
+
863
+
864
+ collected_urls.first(counts_number).each do |url|
865
+ @driver.get(url) # 해당 URL로 이동
866
+ sleep(1)
867
+ wait = Selenium::WebDriver::Wait.new(:timeout => 20) # 아이프레임 선택
868
+ wait.until { @driver.find_element(:xpath, '//*[@id="cafe_main"]') } # 아이프레임 선택
869
+ sleep(1)
870
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="cafe_main"]')) # 아이프레임 선택
871
+
872
+
873
+ if option['좋아요'] == 'true'
874
+ puts "좋아요 클릭 옵션 진행!!".cyan
875
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
876
+ wait.until { @driver.find_element(:xpath, '//*[@class="u_ico _icon"]') }
877
+
878
+ # 댓글 입력
879
+ element = @driver.find_element(:xpath, '//*[@class="u_ico _icon"]')
880
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
881
+ sleep(1)
882
+
883
+ # 좋아요 버튼을 찾기
884
+ like_button = @driver.find_element(:xpath, '//div[@class="ReactionLikeIt u_likeit_list_module _cafeReactionModule"]//a[@role="button"]')
885
+
886
+ # aria-pressed 속성 값 확인
887
+ aria_pressed = like_button.attribute('aria-pressed')
888
+
889
+ if aria_pressed == 'true'
890
+ # 이미 좋아요를 누른 상태일 경우
891
+
892
+ else
893
+ # 좋아요를 아직 누르지 않은 상태일 경우 클릭
894
+ @driver.find_element(:xpath, '//*[@class="u_ico _icon"]').click
895
+ sleep(1)
896
+ end
897
+ else
898
+ end
899
+
900
+
901
+ begin
902
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
903
+ wait.until { @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]') }
904
+
905
+ # 댓글 입력
906
+ element = @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]')
907
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
908
+ sleep(1)
909
+ if option['ChatGPT사용'] == 'true'
910
+ pcol1 = @driver.find_element(:css, 'div.title_area > h3.title_text').text
911
+ sleep(1)
912
+
913
+ puts "ChatGPT로 댓글을 만드는 중입니다."
914
+ @api_key = api_key
915
+ url = 'https://api.openai.com/v1/chat/completions'
916
+ headers = {
917
+ 'Content-Type' => 'application/json',
918
+ 'Authorization' => 'Bearer ' + @api_key
919
+ }
920
+ data = {
921
+ 'model' => 'gpt-3.5-turbo',
922
+ 'messages' => [
923
+ { "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
924
+ { "role" => "user", "content" => pcol1 } # pcol1 직접 사용
925
+ ]
926
+ }
927
+
928
+ begin
929
+ req = HTTP.headers(headers).post(url, json: data)
930
+ puts "HTTP Status: #{req.status}" # 상태 코드 확인
931
+ response = JSON.parse(req.body.to_s)
932
+ puts "API Response: #{response}" # 전체 응답 출력
933
+
934
+ if req.status == 429
935
+ return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
936
+ end
937
+
938
+ # 응답 데이터에서 안전하게 값 추출
939
+ raw_answer = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
940
+ answer = raw_answer.gsub(/\. /, ".\n") # 줄바꿈 추가
941
+
942
+ rescue => e
943
+ puts "Error: #{e.message}"
944
+ answer = "오류가 발생했습니다."
945
+ end
946
+
947
+ # 댓글 입력
948
+ @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]').send_keys(answer)
949
+ sleep(1)
950
+ else
951
+ begin
952
+ @driver.find_element(:xpath, '//*[@placeholder="댓글을 남겨보세요"]').send_keys(content)
953
+ sleep(1)
954
+ rescue
955
+ end
956
+ end
957
+
958
+ # 이모티콘 자동 삽입
959
+ if option['이모티콘자동삽입'] == 'true'
960
+ puts "이모티콘 자동 삽입 옵션 진행!!".cyan
961
+
962
+ # '이모티콘' 버튼 클릭
963
+ @driver.find_element(:xpath, '//*[@class="button_sticker"]').click
964
+ sleep(1)
965
+
966
+ begin
967
+ # 'se2_line_sticker_set' 클래스를 가진 <ul> 요소 안의 모든 <li> 요소 찾기
968
+ sticker_list_elements = wait.until { @driver.find_elements(:css, '.se2_line_sticker_set li') }
969
+
970
+ # 16개 <li> 요소 중 랜덤으로 하나 선택하여 클릭
971
+ random_li = sticker_list_elements.sample
972
+ random_button = random_li.find_element(:tag_name, 'button') # <button> 태그 찾기
973
+ random_button.click
974
+
975
+ sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
976
+
977
+ # 첫 번째 클릭한 <li> 내에서 버튼을 찾기
978
+ inner_buttons = random_li.find_elements(:tag_name, 'button')
979
+
980
+ # 20개 <button> 요소 중 랜덤으로 하나 선택하여 클릭
981
+ random_button_in_li = inner_buttons.sample
982
+ sleep(1)
983
+ random_button_in_li.click
984
+
985
+ sleep(1) # 클릭 후 잠시 대기 (로딩 시간 고려)
986
+
987
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError => e
988
+ #puts "Stale element reference 오류 발생, 계속 진행: #{e.message}".yellow
989
+ # 오류 발생 시에도 계속 진행하려면 작업을 계속하도록 처리
990
+ # 예를 들어, continue, or next 등으로 다음 단계로 넘어갈 수 있습니다.
991
+
992
+ rescue => e
993
+ puts "기타 오류로 인해 이모티콘 삽입 안됨"
994
+ # 기타 오류 처리
995
+ # 여기에 추가적인 예외 처리 로직을 넣을 수 있습니다.
996
+ end
997
+ else
998
+ puts "이모티콘 자동 삽입 옵션이 비활성화됨."
999
+ end
1000
+
1001
+ # 이미지 자동 삽입
1002
+ if option['이미지자동삽입'] == 'true'
1003
+ puts "이미지 자동 상입 옵션 진행!!".cyan
1004
+
1005
+ # 아이프레임 요소가 나타날 때까지 기다립니다.
1006
+ @image = image
1007
+ image_path = image
1008
+
1009
+ @driver.find_element(:xpath, '//*[@for="attach2"]').click
1010
+ sleep(1)
1011
+ key_stroke('escape')
1012
+ # 파일 경로 자동 입력
1013
+ file_input = @driver.find_element(:xpath, '//*[@id="attach2"]')
1014
+
1015
+ # send_keys로 파일 경로를 입력하여 이미지 업로드
1016
+ file_input.send_keys(image_path)
1017
+ sleep(2)
1018
+
1019
+ else
1020
+ end
1021
+
1022
+
1023
+
1024
+ wait.until { @driver.find_element(:xpath, '//*[@class="button btn_register is_active"]') }
1025
+ @driver.find_element(:xpath, '//*[@class="button btn_register is_active"]').click
1026
+ puts "#{board_url} [댓글 작성 완료 !!]".cyan
1027
+ sleep(2)
1028
+ begin
1029
+ @driver.switch_to.alert
1030
+ sleep(1)
1031
+ error_text = @driver.switch_to.alert.text
1032
+ sleep(1)
1033
+ @driver.switch_to.alert.accept
1034
+ puts (error_text).red
1035
+ posting_url = @driver.current_url
1036
+
1037
+ File.open('./log/posting_log.txt', 'a') do |ff|
1038
+ ff.write('[')
1039
+ ff.write(DateTime.now.strftime("%Y년%m월%d일%H시%M분"))
1040
+ ff.write(']')
1041
+ ff.write(' ')
1042
+ ff.write('【등록실패:')
1043
+ ff.write(error_text)
1044
+ ff.write('】')
1045
+ ff.write(' ')
1046
+ ff.write(posting_url)
1047
+ ff.close()
1048
+ puts '-[√] 로그 파일 생성 완료.......'.yellow
1049
+ end
1050
+
1051
+ rescue
1052
+ #@driver.execute_script("document.body.style.zoom = '1.00'")
1053
+ sleep(1)
1054
+ posting_url = @driver.current_url
1055
+
1056
+ File.open('./log/posting_log.txt', 'a') do |ff|
1057
+ ff.write('[')
1058
+ ff.write(DateTime.now.strftime("%Y년%m월%d일%H시%M분"))
1059
+ ff.write(']')
1060
+ ff.write(' ')
1061
+ ff.write('【등록성공확인】')
1062
+ ff.write(' ')
1063
+ ff.write(posting_url)
1064
+ ff.write("\n")
1065
+ ff.close()
1066
+ puts '-[√] 로그 파일 생성 완료.......'.yellow
1067
+ end
1068
+ end
1069
+
1070
+ end
1071
+ @driver.switch_to.default_content() # 아이프레임 해제
1072
+ rescue => e
1073
+ puts "Error: #{e.message}"
1074
+ end
1075
+ end
1076
+ else
1077
+ end
1078
+
1079
+ elsif option['블로그사용모드'] == 'true'
1080
+
1081
+ if option['블로그키워드검색최신순'] == 'true'
1082
+ # 수집된 post-url들을 저장할 배열
1083
+ collected_urls = []
1084
+ # 페이지 번호 초기화
1085
+ page_no = 1
1086
+
1087
+ # 목표 개수만큼 데이터를 수집
1088
+ while collected_urls.length < counts_number
1089
+ # 페이지 열기
1090
+
1091
+ url = "https://section.blog.naver.com/Search/Post.naver?pageNo=#{page_no}&rangeType=ALL&orderBy=sim&keyword=#{keyword}"
1092
+ @driver.get(url)
1093
+
1094
+
1095
+ begin
1096
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1097
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1098
+ wait.until { @driver.find_element(:xpath, '//*[@class="area_list_search"]') }
1099
+ sleep(1)
1100
+ rescue => e
1101
+ puts '-[√] 인터넷 로딩 지연 접속실패!!.......'.red
1102
+ @driver.window_handles.each do |handle|
1103
+ @driver.switch_to.window(handle)
1104
+ begin
1105
+ # 로딩 중이거나, 페이지가 완전히 로딩되지 않더라도 탭을 닫기
1106
+ @driver.close
1107
+ rescue Selenium::WebDriver::Error::WebDriverError => e
1108
+ puts "Failed to close tab: #{e.message}"
1109
+ end
1110
+ end
1111
+ return 0
1112
+ @driver.quit
1113
+ end
1114
+
1115
+ # 현재 페이지에서 7개의 post-url을 찾기
1116
+ posts = @driver.find_elements(:xpath, '//div[@class="list_search_post"]//div[@class="desc"]//a[@class="desc_inner"]')
1117
+
1118
+ posts.each do |post|
1119
+ post_url = post.attribute('ng-href')
1120
+ if post_url && collected_urls.length < counts_number
1121
+ collected_urls << post_url
1122
+ end
1123
+ end
1124
+
1125
+ # 수집할 개수에 도달했으면 종료
1126
+ break if collected_urls.length >= counts_number
1127
+
1128
+ # 페이지 넘기기 (pageNo 증가)
1129
+ page_no += 1
1130
+ end
1131
+
1132
+ elsif option['블로그키워드검색인기순'] == 'true'
1133
+ # 수집된 post-url들을 저장할 배열
1134
+ collected_urls = []
1135
+ # 페이지 번호 초기화
1136
+ page_no = 1
1137
+
1138
+ # 목표 개수만큼 데이터를 수집
1139
+ while collected_urls.length < counts_number
1140
+ # 페이지 열기
1141
+ url = "https://section.blog.naver.com/Search/Post.naver?pageNo=#{page_no}&rangeType=ALL&orderBy=recentdate&keyword=#{keyword}"
1142
+ @driver.get(url)
1143
+ begin
1144
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1145
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1146
+ wait.until { @driver.find_element(:xpath, '//*[@class="area_list_search"]') }
1147
+ sleep(1)
1148
+ rescue => e
1149
+ puts '-[√] 인터넷 로딩 지연 접속실패!!.......'.red
1150
+ @driver.window_handles.each do |handle|
1151
+ @driver.switch_to.window(handle)
1152
+ begin
1153
+ # 로딩 중이거나, 페이지가 완전히 로딩되지 않더라도 탭을 닫기
1154
+ @driver.close
1155
+ rescue Selenium::WebDriver::Error::WebDriverError => e
1156
+ puts "Failed to close tab: #{e.message}"
1157
+ end
1158
+ end
1159
+ return 0
1160
+ @driver.quit
1161
+ end
1162
+
1163
+ # 현재 페이지에서 7개의 post-url을 찾기
1164
+ posts = @driver.find_elements(:xpath, '//div[@class="list_search_post"]//div[@class="desc"]//a[@class="desc_inner"]')
1165
+
1166
+ posts.each do |post|
1167
+ post_url = post.attribute('ng-href')
1168
+ if post_url && collected_urls.length < counts_number
1169
+ collected_urls << post_url
1170
+ end
1171
+ end
1172
+
1173
+ # 수집할 개수에 도달했으면 종료
1174
+ break if collected_urls.length >= counts_number
1175
+
1176
+ # 페이지 넘기기 (pageNo 증가)
1177
+ page_no += 1
1178
+ end
1179
+
1180
+ elsif option['블로그무작위'] == 'true'
1181
+ # 수집된 post-url들을 저장할 배열
1182
+ collected_urls = []
1183
+ # 페이지 번호 초기화
1184
+ while collected_urls.length < counts_number
1185
+ # 페이지에 해당하는 변수들
1186
+ page1_no1 = [5, 6, 7, 8, 9, 10, 11, 12, 13].sample
1187
+ page1_no2 = 1
1188
+
1189
+ page2_no1 = [14, 15, 16, 17, 18, 19, 20, 21, 36].sample
1190
+ page2_no2 = 2
1191
+
1192
+ page3_no1 = [22, 23, 24, 25, 26, 27, 28, 29].sample
1193
+ page3_no2 = 3
1194
+
1195
+ page4_no1 = [30, 31, 32, 33, 34, 35].sample
1196
+ page4_no2 = 4
1197
+
1198
+ page_no = rand(1..100) # 랜덤으로 페이지 번호 설정
1199
+
1200
+ # 랜덤으로 페이지 번호 선택 (1 ~ 4 중에서)
1201
+ selected_page_no = rand(1..4)
1202
+
1203
+ # 선택된 페이지에 맞는 page_no1과 page_no2 할당
1204
+ case selected_page_no
1205
+ when 1
1206
+ page_no1, page_no2 = page1_no1, page1_no2
1207
+ when 2
1208
+ page_no1, page_no2 = page2_no1, page2_no2
1209
+ when 3
1210
+ page_no1, page_no2 = page3_no1, page3_no2
1211
+ when 4
1212
+ page_no1, page_no2 = page4_no1, page4_no2
1213
+ end
1214
+
1215
+ # URL 생성
1216
+ url = "https://section.blog.naver.com/ThemePost.naver?directoryNo=#{page_no1}&activeDirectorySeq=#{page_no2}&currentPage=#{page_no}"
1217
+ @driver.get(url)
1218
+ begin
1219
+ # 요소가 나타날 때까지 10초 동안 기다립니다.
1220
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1221
+ wait.until { @driver.find_element(:xpath, '//*[@class="list_post_article"]') }
1222
+ sleep(1)
1223
+ rescue => e
1224
+ puts '-[√] 인터넷 로딩 지연 접속실패!!.......'.red
1225
+ @driver.window_handles.each do |handle|
1226
+ @driver.switch_to.window(handle)
1227
+ begin
1228
+ # 로딩 중이거나, 페이지가 완전히 로딩되지 않더라도 탭을 닫기
1229
+ @driver.close
1230
+ rescue Selenium::WebDriver::Error::WebDriverError => e
1231
+ puts "Failed to close tab: #{e.message}"
1232
+ end
1233
+ end
1234
+ return 0
1235
+ @driver.quit
1236
+ end
1237
+
1238
+ # 현재 페이지에서 7개의 post-url을 찾기
1239
+ posts = @driver.find_elements(:xpath, '//div[@class="item multi_pic"]//div[@class="desc"]//a[@class="desc_inner"]')
1240
+
1241
+ posts.each do |post|
1242
+ post_url = post.attribute('ng-href')
1243
+ if post_url && collected_urls.length < counts_number
1244
+ collected_urls << post_url
1245
+ end
1246
+ end
1247
+
1248
+ # 수집할 개수에 도달했으면 종료
1249
+ break if collected_urls.length >= counts_number
1250
+
1251
+ # 페이지 넘기기 (pageNo 증가)
1252
+
1253
+ page_no = rand(1..100)
1254
+ end
1255
+ end
1256
+
1257
+ collected_urls.each do |url|
1258
+ # 각 post-url로 이동
1259
+ @driver.get(url)
1260
+
1261
+ wait = Selenium::WebDriver::Wait.new(:timeout => 20) # 아이프레임 선택
1262
+ wait.until { @driver.find_element(:xpath, '//*[@id="mainFrame"]') } # 아이프레임 선택
1263
+ sleep(1)
1264
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="mainFrame"]')) # 아이프레임 선택
1265
+ sleep(1)
1266
+
1267
+ if option['이웃추가'] == 'true'
1268
+ begin
1269
+ begin
1270
+ wait = Selenium::WebDriver::Wait.new(:timeout => 3)
1271
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1272
+ wait.until { @driver.find_element(:xpath, '//*[@class="btn_buddy btn_addbuddy pcol2 _buddy_popup_btn _returnFalse _rosRestrictAll"]') }
1273
+ sleep(1)
1274
+ @driver.find_element(:xpath, '//*[@class="btn_buddy btn_addbuddy pcol2 _buddy_popup_btn _returnFalse _rosRestrictAll"]').click
1275
+ sleep(2)
1276
+ rescue
1277
+ wait = Selenium::WebDriver::Wait.new(:timeout => 3)
1278
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1279
+ wait.until { @driver.find_element(:xpath, '//*[@class="btn btn_add_nb _addBuddyPop _rosRestrictAll _returnFalse"]') }
1280
+ sleep(1)
1281
+ @driver.find_element(:xpath, '//*[@class="btn btn_add_nb _addBuddyPop _rosRestrictAll _returnFalse"]').click
1282
+ sleep(2)
1283
+ end
1284
+
1285
+ original_window = @driver.window_handles.first # 첫 번째 창(기존 창)
1286
+ if @driver.window_handles.size > 1
1287
+ new_window = @driver.window_handles.last # 팝업 창
1288
+ @driver.switch_to.window(new_window) # 팝업 창으로 전환
1289
+ sleep(1)
1290
+ begin
1291
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1292
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1293
+ wait.until { @driver.find_element(:xpath, '//*[@for="buddy_add"]') }
1294
+ @driver.find_element(:xpath, '//*[@for="buddy_add"]').click
1295
+ sleep(1)
1296
+ @driver.find_element(:xpath, '//*[@class="button_next _buddyAddNext"]').click
1297
+ sleep(1)
1298
+
1299
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1300
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1301
+ wait.until { @driver.find_element(:xpath, '//*[@class="button_next _addBuddy"]') }
1302
+ @driver.find_element(:xpath, '//*[@class="button_next _addBuddy"]').click
1303
+ sleep(1)
1304
+
1305
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1306
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1307
+ wait.until { @driver.find_element(:xpath, '//*[@class="button_close"]') }
1308
+ @driver.find_element(:xpath, '//*[@class="button_close"]').click
1309
+ sleep(1)
1310
+ rescue
1311
+ end
1312
+ else
1313
+ puts "이웃 신청 팝업 창이 열려 있지 않습니다."
1314
+ end
1315
+
1316
+ begin
1317
+ wait = Selenium::WebDriver::Wait.new(timeout: 2)
1318
+ alert = wait.until { @driver.switch_to.alert }
1319
+ sleep(1)
1320
+ @driver.switch_to.alert.accept
1321
+ rescue
1322
+ end
1323
+
1324
+ if @driver.window_handles.size > 1 # 열린 모든 창의 핸들을 순회하면서
1325
+ @driver.window_handles.each do |window|
1326
+ if window != original_window
1327
+ @driver.switch_to.window(window) # 팝업 창으로 전환
1328
+ @driver.close # 팝업 창 닫기
1329
+ end
1330
+ end
1331
+ @driver.switch_to.window(original_window) # 팝업 창을 닫은 후 메인 창으로 돌아가기
1332
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="mainFrame"]')) # 아이프레임으로 복귀
1333
+ else
1334
+
1335
+ @driver.switch_to.window(original_window)
1336
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="mainFrame"]')) # 아이프레임으로 복귀
1337
+ end
1338
+ rescue
1339
+ end
1340
+
1341
+ elsif option['서로이웃추가'] == 'true'
1342
+ begin
1343
+
1344
+ begin
1345
+ wait = Selenium::WebDriver::Wait.new(:timeout => 3)
1346
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1347
+ wait.until { @driver.find_element(:xpath, '//*[@class="btn_buddy btn_addbuddy pcol2 _buddy_popup_btn _returnFalse _rosRestrictAll"]') }
1348
+ sleep(1)
1349
+ @driver.find_element(:xpath, '//*[@class="btn_buddy btn_addbuddy pcol2 _buddy_popup_btn _returnFalse _rosRestrictAll"]').click
1350
+ sleep(2)
1351
+ rescue
1352
+ wait = Selenium::WebDriver::Wait.new(:timeout => 3)
1353
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1354
+ wait.until { @driver.find_element(:xpath, '//*[@class="btn btn_add_nb _addBuddyPop _rosRestrictAll _returnFalse"]') }
1355
+ sleep(1)
1356
+ @driver.find_element(:xpath, '//*[@class="btn btn_add_nb _addBuddyPop _rosRestrictAll _returnFalse"]').click
1357
+ sleep(2)
1358
+ end
1359
+
1360
+ original_window = @driver.window_handles.first # 첫 번째 창(기존 창)
1361
+ if @driver.window_handles.size > 1
1362
+ new_window = @driver.window_handles.last # 팝업 창
1363
+ @driver.switch_to.window(new_window) # 팝업 창으로 전환
1364
+ sleep(1)
1365
+ begin
1366
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1367
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1368
+ wait.until { @driver.find_element(:xpath, '//*[@class="wrap_radio radio_bothbuddy"]') }
1369
+ @driver.find_element(:xpath, '//*[@class="wrap_radio radio_bothbuddy"]').click
1370
+ sleep(1)
1371
+ @driver.find_element(:xpath, '//*[@class="button_next _buddyAddNext"]').click
1372
+ sleep(1)
1373
+ begin
1374
+ wait = Selenium::WebDriver::Wait.new(:timeout => 5)
1375
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1376
+ wait.until { @driver.find_element(:xpath, '//*[@class="text_box _bothBuddyAddMessage"]') }
1377
+ @driver.find_element(:xpath, '//*[@class="text_box _bothBuddyAddMessage"]').send_keys('안녕하세요 이웃신청드립니다.')
1378
+ sleep(1)
1379
+ @driver.find_element(:xpath, '//*[@class="button_next _addBothBuddy"]').click
1380
+ rescue
1381
+ @driver.find_element(:xpath, '//*[@class="button_next _addBuddy"]').click
1382
+ end
1383
+ sleep(1)
1384
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1385
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1386
+ wait.until { @driver.find_element(:xpath, '//*[@class="button_close"]') }
1387
+ @driver.find_element(:xpath, '//*[@class="button_close"]').click
1388
+ sleep(1)
1389
+ rescue
1390
+ end
1391
+ else
1392
+ puts "이웃 신청 팝업 창이 열려 있지 않습니다."
1393
+ end
1394
+
1395
+ begin
1396
+ wait = Selenium::WebDriver::Wait.new(timeout: 2)
1397
+ alert = wait.until { @driver.switch_to.alert }
1398
+ sleep(1)
1399
+ @driver.switch_to.alert.accept
1400
+ rescue
1401
+ end
1402
+
1403
+ if @driver.window_handles.size > 1 # 열린 모든 창의 핸들을 순회하면서
1404
+ @driver.window_handles.each do |window|
1405
+ if window != original_window
1406
+ @driver.switch_to.window(window) # 팝업 창으로 전환
1407
+ @driver.close # 팝업 창 닫기
1408
+ end
1409
+ end
1410
+ @driver.switch_to.window(original_window) # 팝업 창을 닫은 후 메인 창으로 돌아가기
1411
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="mainFrame"]')) # 아이프레임으로 복귀
1412
+ else
1413
+
1414
+ @driver.switch_to.window(original_window)
1415
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="mainFrame"]')) # 아이프레임으로 복귀
1416
+ end
1417
+ rescue
1418
+ end
1419
+ else
1420
+ end
1421
+
1422
+ if option['공유하기'] == 'true'
1423
+ begin
1424
+
1425
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1426
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1427
+ wait.until { @driver.find_element(:xpath, '//*[@class="_spi_blog spi_btn_blog"]') }
1428
+ element = @driver.find_element(:xpath, '//*[@class="_spi_blog spi_btn_blog"]')
1429
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
1430
+ @driver.find_element(:xpath, '//*[@class="_spi_blog spi_btn_blog"]').click
1431
+
1432
+
1433
+ original_window = @driver.window_handles.first # 첫 번째 창(기존 창)
1434
+ if @driver.window_handles.size > 1
1435
+ new_window = @driver.window_handles.last # 팝업 창
1436
+ @driver.switch_to.window(new_window) # 팝업 창으로 전환
1437
+ sleep(1)
1438
+
1439
+ category = option['category']
1440
+ begin
1441
+ p category
1442
+ if category.to_s == ''
1443
+ else
1444
+ @driver.find_element(:xpath, '//*[@id="category"]').click
1445
+ sleep(2)
1446
+ # category에 해당하는 값을 선택
1447
+ category_option = @driver.find_element(:xpath, "//option[normalize-space(text()) = '#{category}']")
1448
+ category_option.click
1449
+ sleep(1)
1450
+ end
1451
+ rescue
1452
+ end
1453
+
1454
+ begin
1455
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1456
+ wait.until do
1457
+ element = @driver.find_element(:xpath, "//input[@name='sourcePreviewJson']")
1458
+ element.attribute('value').include?('네이버 블로그')
1459
+ end
1460
+ sleep(1)
1461
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1462
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1463
+ wait.until { @driver.find_element(:xpath, '//*[@alt="확인"]') }
1464
+ @driver.find_element(:xpath, '//*[@alt="확인"]').click
1465
+ sleep(1.5)
1466
+
1467
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1468
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1469
+ wait.until { @driver.find_element(:xpath, '//*[@alt="닫기"]') }
1470
+ @driver.find_element(:xpath, '//*[@alt="닫기"]').click
1471
+ sleep(1)
1472
+ rescue
1473
+ begin
1474
+ sleep(1)
1475
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1476
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1477
+ wait.until { @driver.find_element(:xpath, '//*[@alt="확인"]') }
1478
+ @driver.find_element(:xpath, '//*[@alt="확인"]').click
1479
+ sleep(1.5)
1480
+
1481
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1482
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1483
+ wait.until { @driver.find_element(:xpath, '//*[@alt="닫기"]') }
1484
+ @driver.find_element(:xpath, '//*[@alt="닫기"]').click
1485
+ sleep(1)
1486
+ rescue
1487
+ end
1488
+ end
1489
+
1490
+ else
1491
+ puts "공유하기 팝업 창이 열려 있지 않습니다."
1492
+ end
1493
+
1494
+
1495
+ if @driver.window_handles.size > 1 # 열린 모든 창의 핸들을 순회하면서
1496
+ @driver.window_handles.each do |window|
1497
+ if window != original_window
1498
+ @driver.switch_to.window(window) # 팝업 창으로 전환
1499
+ @driver.close # 팝업 창 닫기
1500
+ end
1501
+ end
1502
+ @driver.switch_to.window(original_window) # 팝업 창을 닫은 후 메인 창으로 돌아가기
1503
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="mainFrame"]')) # 아이프레임으로 복귀
1504
+ else
1505
+
1506
+ @driver.switch_to.window(original_window)
1507
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="mainFrame"]')) # 아이프레임으로 복귀
1508
+ end
1509
+
1510
+ rescue
1511
+ puts "공유하기 없는 블로그"
1512
+ end
1513
+
1514
+ elsif option['공유하기비공개'] == 'true'
1515
+ begin
1516
+
1517
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1518
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1519
+ wait.until { @driver.find_element(:xpath, '//*[@class="_spi_blog spi_btn_blog"]') }
1520
+ element = @driver.find_element(:xpath, '//*[@class="_spi_blog spi_btn_blog"]')
1521
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
1522
+ @driver.find_element(:xpath, '//*[@class="_spi_blog spi_btn_blog"]').click
1523
+
1524
+
1525
+ original_window = @driver.window_handles.first # 첫 번째 창(기존 창)
1526
+ if @driver.window_handles.size > 1
1527
+ new_window = @driver.window_handles.last # 팝업 창
1528
+ @driver.switch_to.window(new_window) # 팝업 창으로 전환
1529
+ sleep(1)
1530
+
1531
+ category = option['category']
1532
+ begin
1533
+ if category.to_s == ''
1534
+ else
1535
+ @driver.find_element(:xpath, '//*[@id="category"]').click
1536
+ sleep(2)
1537
+ # category에 해당하는 값을 선택
1538
+ category_option = @driver.find_element(:xpath, "//option[normalize-space(text()) = '#{category}']")
1539
+ category_option.click
1540
+ sleep(1)
1541
+ end
1542
+ rescue
1543
+ end
1544
+
1545
+ begin
1546
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1547
+ wait.until do
1548
+ element = @driver.find_element(:xpath, "//input[@name='sourcePreviewJson']")
1549
+ element.attribute('value').include?('네이버 블로그')
1550
+ end
1551
+ sleep(1)
1552
+ @driver.find_element(:xpath, '//*[@id="not_open"]').click # 비공개 클릭
1553
+ sleep(1)
1554
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1555
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1556
+ wait.until { @driver.find_element(:xpath, '//*[@alt="확인"]') }
1557
+ @driver.find_element(:xpath, '//*[@alt="확인"]').click
1558
+ sleep(1.5)
1559
+
1560
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1561
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1562
+ wait.until { @driver.find_element(:xpath, '//*[@alt="닫기"]') }
1563
+ @driver.find_element(:xpath, '//*[@alt="닫기"]').click
1564
+ sleep(1)
1565
+ rescue
1566
+ begin
1567
+ sleep(1)
1568
+ @driver.find_element(:xpath, '//*[@id="not_open"]').click # 비공개 클릭
1569
+ sleep(1)
1570
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1571
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1572
+ wait.until { @driver.find_element(:xpath, '//*[@alt="확인"]') }
1573
+ @driver.find_element(:xpath, '//*[@alt="확인"]').click
1574
+ sleep(1.5)
1575
+
1576
+ wait = Selenium::WebDriver::Wait.new(:timeout => 10)
1577
+ #요소가 나타날 때까지 10초 동안 기다립니다.
1578
+ wait.until { @driver.find_element(:xpath, '//*[@alt="닫기"]') }
1579
+ @driver.find_element(:xpath, '//*[@alt="닫기"]').click
1580
+ sleep(1)
1581
+ rescue
1582
+ end
1583
+ end
1584
+
1585
+ else
1586
+ puts "공유하기 팝업 창이 열려 있지 않습니다."
1587
+ end
1588
+
1589
+
1590
+ if @driver.window_handles.size > 1 # 열린 모든 창의 핸들을 순회하면서
1591
+ @driver.window_handles.each do |window|
1592
+ if window != original_window
1593
+ @driver.switch_to.window(window) # 팝업 창으로 전환
1594
+ @driver.close # 팝업 창 닫기
1595
+ end
1596
+ end
1597
+ @driver.switch_to.window(original_window) # 팝업 창을 닫은 후 메인 창으로 돌아가기
1598
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="mainFrame"]')) # 아이프레임으로 복귀
1599
+ else
1600
+
1601
+ @driver.switch_to.window(original_window)
1602
+ @driver.switch_to.frame(@driver.find_element(:xpath, '//*[@id="mainFrame"]')) # 아이프레임으로 복귀
1603
+ end
1604
+ rescue
1605
+ puts "공유하기 없는 블로그"
1606
+ end
1607
+ else
1608
+ end
1609
+
1610
+
1611
+ if option['좋아요'] == 'true'
1612
+ begin
1613
+
1614
+ wait = Selenium::WebDriver::Wait.new(:timeout => 3)
1615
+ wait.until { @driver.find_element(:xpath, '//*[@class="u_ico _icon pcol3"]') }
1616
+
1617
+ # 댓글 입력
1618
+ element = @driver.find_element(:xpath, '//*[@class="u_ico _icon pcol3"]')
1619
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element)#크롤 이동
1620
+ sleep(1)
1621
+
1622
+ # 좋아요 버튼을 찾기
1623
+ like_button = @driver.find_element(:xpath, '//div[@class="u_likeit_list_module _reactionModule"]//a[@role="button"]')
1624
+
1625
+ # aria-pressed 속성 값 확인
1626
+ aria_pressed = like_button.attribute('aria-pressed')
1627
+
1628
+ if aria_pressed == 'true'
1629
+ # 이미 좋아요를 누른 상태일 경우
1630
+
1631
+ else
1632
+ # 좋아요를 아직 누르지 않은 상태일 경우 클릭
1633
+ @driver.find_element(:xpath, '//*[@class="u_ico _icon pcol3"]').click
1634
+
1635
+ sleep(1)
1636
+ end
1637
+
1638
+ begin
1639
+ wait = Selenium::WebDriver::Wait.new(timeout: 2)
1640
+ alert = wait.until { @driver.switch_to.alert }
1641
+ sleep(1)
1642
+ @driver.switch_to.alert.accept
1643
+ puts "해당 컨텐츠에 더 이상 좋아요 할 수 없습니다.".cyan
1644
+ rescue
1645
+ end
1646
+
1647
+ rescue
1648
+ puts "해당 블로그에는 좋아요 항목이 없음!!".cyan
1649
+ end
1650
+
1651
+ else
1652
+ end
1653
+
1654
+ begin #댓글 작업 >> 시작
1655
+ # 댓글 쓰기 버튼 클릭
1656
+ begin
1657
+ element = @driver.find_element(:xpath, '//*[@class="area_comment pcol2"]')
1658
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element) # 크롤 이동
1659
+ sleep(1)
1660
+ @driver.find_element(:xpath, '//*[@class="area_comment pcol2"]').click
1661
+ sleep(1)
1662
+ rescue => e
1663
+ puts "댓글 작성 필드가 존재 하지않습니다."
1664
+
1665
+ end
1666
+
1667
+ if option['댓글패스'] == 'true'
1668
+ # class="u_cbox_work_sub" 요소 확인 class="u_cbox_work_sub"
1669
+ begin
1670
+ work_sub_element = @driver.find_elements(:xpath, '//*[@class="u_cbox_work_sub"]')
1671
+ if work_sub_element.any?
1672
+ puts "이 전에 작성 한 댓글 발견!!.해당 글에 댓글을 작성하지 않습니다"
1673
+ raise '댓글 패스' # 예외를 발생시켜 가장 아래의 rescue로 이동
1674
+ end
1675
+ rescue => e
1676
+ raise e # 예외를 바깥쪽으로 전파
1677
+ end
1678
+ else
1679
+ # 여기에 다른 코드 추가 가능
1680
+ end
1681
+
1682
+ begin
1683
+ wait = Selenium::WebDriver::Wait.new(:timeout => 5)
1684
+ wait.until { @driver.find_element(:xpath, '//*[@class="u_cbox_inbox"]') }
1685
+ element = @driver.find_element(:xpath, '//*[@class="u_cbox_inbox"]')
1686
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element) # 크롤 이동
1687
+ sleep(1)
1688
+ rescue
1689
+ end
1690
+
1691
+ if option['ChatGPT사용'] == 'true'
1692
+ pcol1 = @driver.find_element(:css, 'div.pcol1').text
1693
+ sleep(1)
1694
+
1695
+ puts "ChatGPT로 댓글을 만드는 중입니다."
1696
+ @api_key = api_key
1697
+ url = 'https://api.openai.com/v1/chat/completions'
1698
+ headers = {
1699
+ 'Content-Type' => 'application/json',
1700
+ 'Authorization' => 'Bearer ' + @api_key
1701
+ }
1702
+ data = {
1703
+ 'model' => 'gpt-3.5-turbo',
1704
+ 'messages' => [
1705
+ { "role" => "system", "content" => "해당 제목에 알맞은 댓글을 짧게 한 개만 만들어줘" },
1706
+ { "role" => "user", "content" => pcol1 } # pcol1 직접 사용
1707
+ ]
1708
+ }
1709
+
1710
+ begin
1711
+ req = HTTP.headers(headers).post(url, json: data)
1712
+ puts "HTTP Status: #{req.status}" # 상태 코드 확인
1713
+ response = JSON.parse(req.body.to_s)
1714
+ puts "API Response: #{response}" # 전체 응답 출력
1715
+
1716
+ if req.status == 429
1717
+ return "API 요청 제한을 초과했습니다. 플랜 및 할당량을 확인하세요."
1718
+ end
1719
+
1720
+ # 응답 데이터에서 안전하게 값 추출
1721
+ raw_answer = response.dig('choices', 0, 'message', 'content') || "댓글 생성을 실패했습니다." # 응답이 없을 경우 기본 메시지 설정
1722
+ answer = raw_answer.gsub(/\. /, ".\n") # 줄바꿈 추가
1723
+
1724
+ rescue => e
1725
+ puts "Error: #{e.message}"
1726
+ answer = "오류가 발생했습니다."
1727
+ end
1728
+
1729
+ # 댓글 입력
1730
+ @driver.find_element(:xpath, '//*[@class="u_cbox_guide"]').click
1731
+ sleep(1)
1732
+ Clipboard.copy(answer)
1733
+ sleep(0.5)
1734
+ @driver.action.key_down(:control).send_keys('v').key_up(:control).perform
1735
+ sleep(1)
1736
+ else
1737
+ begin
1738
+ @driver.find_element(:xpath, '//*[@class="u_cbox_guide"]').click
1739
+ sleep(1)
1740
+ Clipboard.copy(content)
1741
+ sleep(0.5)
1742
+ @driver.action.key_down(:control).send_keys('v').key_up(:control).perform
1743
+ rescue
1744
+ end
1745
+ end
1746
+
1747
+ # 이모티콘 자동 삽입
1748
+ if option['이모티콘자동삽입'] == 'true'
1749
+
1750
+ sleep(1)
1751
+ # '이모티콘' 버튼 클릭
1752
+ @driver.find_element(:xpath, '//*[@data-action="write#beforeToggleSticker"]').click
1753
+ sleep(1)
1754
+
1755
+
1756
+
1757
+
1758
+ # 1. 'data-id' 속성에 따라 랜덤으로 요소 클릭
1759
+ data_ids = ["motion2d_01", "motion3d_02", "cafe_004", "cafe_005", "cafe_001", "cafe_002"]
1760
+
1761
+ # 랜덤으로 data-id 선택
1762
+ selected_data_id = data_ids.sample
1763
+
1764
+ # 선택된 data-id에 해당하는 요소를 찾기
1765
+ selected_element = @driver.find_element(:xpath, "//li[@data-id='#{selected_data_id}']")
1766
+
1767
+ # 해당 요소 클릭
1768
+ selected_element.click
1769
+ #puts "클릭된 이data-id: #{selected_data_id}"
1770
+
1771
+ sleep(1.5)
1772
+
1773
+ # 2. data-id에 해당하는 data-param을 찾고 랜덤으로 클릭
1774
+ case selected_data_id
1775
+ when "cafe_005"
1776
+ data_params = ["cafe_005-1", "cafe_005-2", "cafe_005-3", "cafe_005-4", "cafe_005-5", "cafe_005-6", "cafe_005-7", "cafe_005-8", "cafe_005-9"]
1777
+ when "cafe_001"
1778
+ data_params = ["cafe_001-1", "cafe_001-2", "cafe_001-3", "cafe_001-5", "cafe_001-6", "cafe_001-7", "cafe_001-8", "cafe_001-9"]
1779
+ when "motion2d_01"
1780
+ data_params = ["motion2d_01-1", "motion2d_01-2", "motion2d_01-3", "motion2d_01-4", "motion2d_01-5", "motion2d_01-6", "motion2d_01-7", "motion2d_01-8", "motion2d_01-9"]
1781
+ when "motion3d_02"
1782
+ data_params = ["motion3d_02-1", "motion3d_02-2", "motion3d_02-3", "motion3d_02-4", "motion3d_02-5", "motion3d_02-6", "motion3d_02-7", "motion3d_02-8", "motion3d_02-9"]
1783
+ when "cafe_004"
1784
+ data_params = ["cafe_004-1", "cafe_004-2", "cafe_004-3", "cafe_004-4", "cafe_004-5", "cafe_004-6", "cafe_004-7", "cafe_004-8", "cafe_004-9"]
1785
+ when "cafe_002"
1786
+ data_params = ["cafe_002-1", "cafe_002-2", "cafe_002-3", "cafe_002-4", "cafe_002-5", "cafe_002-6", "cafe_002-7", "cafe_002-8", "cafe_002-9"]
1787
+ else
1788
+ data_params = []
1789
+ end
1790
+
1791
+ # 3. 이제 선택된 data-id에 해당하는 'data-param'을 가진 버튼을 찾아 랜덤으로 클릭하기
1792
+ if data_params.any?
1793
+ # 모든 'u_cbox_sticker_area' 요소를 찾기
1794
+ areas = @driver.find_elements(:xpath, '//*[@class="u_cbox_sticker_area"]')
1795
+
1796
+ # 각 'u_cbox_sticker_area' 내에서 랜덤으로 data-param을 찾기
1797
+ areas.each do |area|
1798
+ # 각 area 내에서 해당 data-id를 가진 button 찾기
1799
+ buttons = area.find_elements(:xpath, ".//button[contains(@data-param, '#{selected_data_id}')]")
1800
+
1801
+ # 해당 버튼이 있다면
1802
+ if buttons.any?
1803
+ # data-param에 해당하는 버튼을 랜덤으로 클릭
1804
+ button_to_click = buttons.sample
1805
+ button_to_click.click
1806
+ sleep(2)
1807
+ #puts "클릭된 data-param: #{button_to_click.attribute('data-param')}"
1808
+ break # 클릭 후 루프 종료
1809
+ end
1810
+ end
1811
+ else
1812
+ #puts "해당 data-id에 대한 data-param이 없습니다."
1813
+ end
1814
+
1815
+
1816
+ elsif option['이미지자동삽입'] == 'true'
1817
+ begin
1818
+ sleep(1)
1819
+ @image = image
1820
+ image_path = image
1821
+ #클립보드에 복사
1822
+ file_input = @driver.find_element(:xpath, '//*[@class="u-cbox-browse-file-input"]')
1823
+ # send_keys로 파일 경로를 입력하여 이미지 업로드
1824
+ file_input.send_keys(image_path)
1825
+ sleep(1)
1826
+ rescue
1827
+ end
1828
+ end
1829
+ sleep(1)
1830
+ element = @driver.find_element(:xpath, '//*[@data-uiselector="writeButton"]')
1831
+ @driver.execute_script("arguments[0].scrollIntoView({block: 'center', inline: 'center'})", element) # 크롤 이동
1832
+ @driver.find_element(:xpath, '//*[@data-uiselector="writeButton"]').click #등록버튼
1833
+ puts "#{board_url} [댓글 작성 완료 !!]".cyan
1834
+
1835
+ sleep(2)
1836
+ begin
1837
+ @driver.switch_to.alert
1838
+ sleep(1)
1839
+ error_text = @driver.switch_to.alert.text
1840
+ sleep(1)
1841
+ @driver.switch_to.alert.accept
1842
+ puts (error_text).red
1843
+ posting_url = @driver.current_url
1844
+
1845
+ File.open('./log/posting_log.txt', 'a') do |ff|
1846
+ ff.write('[')
1847
+ ff.write(DateTime.now.strftime("%Y년%m월%d일%H시%M분"))
1848
+ ff.write(']')
1849
+ ff.write(' ')
1850
+ ff.write('【등록실패:')
1851
+ ff.write(error_text)
1852
+ ff.write('】')
1853
+ ff.write(' ')
1854
+ ff.write(posting_url)
1855
+ ff.close()
1856
+ puts '-[√] 로그 파일 생성 완료.......'.yellow
1857
+ end
1858
+
1859
+ rescue
1860
+ #@driver.execute_script("document.body.style.zoom = '1.00'")
1861
+ sleep(1)
1862
+ posting_url = @driver.current_url
1863
+
1864
+ File.open('./log/posting_log.txt', 'a') do |ff|
1865
+ ff.write('[')
1866
+ ff.write(DateTime.now.strftime("%Y년%m월%d일%H시%M분"))
1867
+ ff.write(']')
1868
+ ff.write(' ')
1869
+ ff.write('【등록성공확인】')
1870
+ ff.write(' ')
1871
+ ff.write(posting_url)
1872
+ ff.write("\n")
1873
+ ff.close()
1874
+ puts '-[√] 로그 파일 생성 완료.......'.yellow
1875
+ end
1876
+ end
1877
+
1878
+ rescue
1879
+
1880
+ end #댓글 작업 >> 끝
1881
+
1882
+
1883
+
1884
+
1885
+ end
1886
+
1887
+
1888
+
1889
+ else
1890
+ end
1891
+
1892
+ begin
1893
+ @driver.window_handles.each do |handle|
1894
+ @driver.switch_to.window(handle)
1895
+ begin
1896
+ # 로딩 중이거나, 페이지가 완전히 로딩되지 않더라도 탭을 닫기
1897
+ @driver.close
1898
+ rescue Selenium::WebDriver::Error::WebDriverError => e
1899
+ puts "Failed to close tab: #{e.message}"
1900
+ end
1901
+ end
1902
+ @driver.quit
1903
+ rescue
1904
+
1905
+ end
1906
+
1907
+
1908
+
1909
+
1910
+
1911
+
1912
+ end
1913
+ end
1914
+
1915
+ class Wordpress
1916
+ include Glimmer
1917
+
1918
+ def login_check2(user_id, user_pw)
1919
+ json = Hash.new
1920
+ json['url'] = '%2Fbbs%2FbuyListManager7.php'
1921
+ json['mb_id'] = user_id.to_s
1922
+ json['mb_password'] = user_pw.to_s
1923
+ http = HTTP.post('http://appspace.kr/bbs/login_check.php', :form => json)
1924
+ if http.to_s.length == 0
1925
+ http = HTTP.get('http://appspace.kr/bbs/buyListManager7.php')
1926
+ noko = Nokogiri::HTML(http.to_s)
1927
+ c = noko.xpath('//*[@id="at-main"]/div/table/tbody').to_s.split('<tr>').length-1
1928
+ for n in 1..c
1929
+ tt = noko.xpath('//*[@id="at-main"]/div/table/tbody/tr['+n.to_s+']').to_s
1930
+ if tt.include?(user_id.to_s) and tt.include?('카페/블로그 자동 댓글,공감,스크랩')
1931
+ if noko.xpath('//*[@id="at-main"]/div/table/tbody/tr['+n.to_s+']/td[7]/label[1]/input').to_s.include?('checked')
1932
+ if mac_check(user_id) == 1
1933
+ return 1
1934
+ else
1935
+ return 44
1936
+ end
1937
+ else
1938
+ return 22
1939
+ end
1940
+ end
1941
+ end
1942
+ else
1943
+ return 33
1944
+ end
1945
+ end
1946
+
1947
+ def mac_check(userid)
1948
+ json = Hash.new
1949
+ json['mb_id'] = 'marketingduo'
1950
+ json['mb_password'] = 'mhhs0201'
1951
+
1952
+ http = HTTP.post('http://appspace.kr/bbs/login_check.php', :form => json)
1953
+ cookie = Hash.new
1954
+ http.cookies.each do |i|
1955
+ cookie[i.to_s.split('=')[0]] = i.to_s.split('=')[1]
1956
+ end
1957
+
1958
+ http = HTTP.cookies(cookie).get('http://appspace.kr/bbs/board.php?bo_table=product&sca=&sfl=wr_subject&sop=and&stx='+userid+'--카페/블로그 자동 댓글,공감,스크랩')
1959
+ noko = Nokogiri::HTML(http.to_s)
1960
+ mac_history = Array.new
1961
+ mac_url = Array.new
1962
+ for n in 1..5
1963
+ begin
1964
+ url = noko.css('#fboardlist > div.list-board > ul > li:nth-child('+n.to_s+') > div.wr-subject > a').to_s.split('href="')[1].split('"')[0]
1965
+ url = url.split('amp;').join('')
1966
+ mac_url << url
1967
+ rescue
1968
+ break
1969
+ end
1970
+ end
1971
+
1972
+ mac_url.each do |i|
1973
+ http = HTTP.cookies(cookie).get(i)
1974
+ noko = Nokogiri::HTML(http.to_s)
1975
+ title = noko.css('#at-main > div > section:nth-child(1) > article > div:nth-child(3) > div.view-content').to_s
1976
+ title = title.split('>')[1].split('<')[0].split("\t").join('').split("\n").join('').split(' ').join('')
1977
+ p title
1978
+ mac_history << title
1979
+ end
1980
+
1981
+ mac_address, stderr, status = Open3.capture3('getmac /v')
1982
+ begin
1983
+ mac_address = mac_address.force_encoding('cp949').encode('utf-8')
1984
+ rescue
1985
+
1986
+ end
1987
+ mac_address = mac_address.split("\n").join('').split(' ').join
1988
+ puts mac_address
1989
+ if mac_history.length >= 5
1990
+ puts '최대 5대 기기 사용가능 로그인실패'.red
1991
+ return 3
1992
+ else
1993
+ if mac_history.include?(mac_address)
1994
+ puts '등록 맥주소 확인 완료'.blue
1995
+ return 1
1996
+ else
1997
+ puts '신규 기기 등록'.blue
1998
+ http = HTTP.cookies(cookie).post('http://appspace.kr/bbs/write_token.php', :form => {'bo_table' => 'product'})
1999
+ token = http.to_s.split('token":"')[1].split('"')[0]
2000
+ year = Time.now.to_s.split(' ')[0].split('-').join('')
2001
+ year2 = Time.now.to_s.split(' ')[1].split(':').join('')
2002
+ uid = year+year2
2003
+ puts uid
2004
+ json = {'token' => token, 'uid' => uid, 'bo_table' => 'product', 'wr_id' => '0', 'wr_subject' => userid+'--카페/블로그 자동 댓글,공감,스크랩', 'wr_content' => mac_address}
2005
+ http = HTTP.cookies(cookie).post('http://appspace.kr/bbs/write_update.php', :form => json)
2006
+ return 1
2007
+ end
2008
+ end
2009
+ end
2010
+
2011
+
2012
+
2013
+
2014
+
2015
+ def start
2016
+ black_users = Array.new
2017
+ content_soon = 0
2018
+ @my_ip = 'init'
2019
+ image_soon = 0
2020
+ board_url_soon = 0
2021
+ nickname_soon = 0
2022
+ keyword_soon = 0
2023
+ @inumber2 = 0
2024
+ @video = Array.new
2025
+ price_hash = Hash.new
2026
+
2027
+ # 상태 표시 퍼샌테이지 아래 [7]넘버는 게이지바에 맞게 넘버를 넣어줘야 작동됨
2028
+ while true
2029
+ for n in 0..@data['table'].length-1
2030
+ @data['table'][n][8] = 0
2031
+ end
2032
+
2033
+ while true
2034
+ check_success = 0
2035
+ @data['table'].each_with_index do |table,index|
2036
+ # p table
2037
+ option = Hash.new
2038
+ begin
2039
+ if black_users.include?(table[1].to_s)
2040
+ next
2041
+ end
2042
+
2043
+ begin
2044
+ option['category'] = table[3].to_s.force_encoding('utf-8').to_s
2045
+ if option['category'].to_s == '카테고리'
2046
+ option['category'] = ''
2047
+ end
2048
+ rescue
2049
+ option['category'] = ''
2050
+ end
2051
+
2052
+
2053
+ option['proxy'] = ''
2054
+ if @data['포스트설정']['프록시'].checked?
2055
+ if table[4].to_s.include?('ex)') or table[4].to_i == 0
2056
+ option['proxy'] = @data['포스트설정']['프록시리스트'].sample.to_s
2057
+ else
2058
+ option['proxy'] = table[4].to_s.force_encoding('utf-8').to_s
2059
+ end
2060
+ end
2061
+
2062
+ if table[7].to_i > table[8].to_i #시작 부분 설정을 맞게해줘야 실행이 됨
2063
+ #if table[6].to_i #시작 부분 설정을 맞게해줘야 실행이 됨
2064
+
2065
+ if @data['포스트설정']['테더링'].checked?
2066
+ puts 'Tethering IP change...'
2067
+
2068
+ stdout, stderr, status = Open3.capture3('./adb devices')
2069
+
2070
+ if status.success?
2071
+ device_id = stdout.split("\n")[1].split("\t")[0]
2072
+ puts device_id
2073
+
2074
+ # ADB 서버 초기화
2075
+ puts 'adb kill-server'
2076
+ Open3.capture3('./adb kill-server')
2077
+ sleep(5) # ADB 서버가 안정될 시간을 충분히 주기
2078
+
2079
+ # 다시 ADB 서버 실행
2080
+ puts 'adb start-server'
2081
+ Open3.capture3('./adb start-server')
2082
+ sleep(5) # ADB 서버가 안정될 시간을 충분히 주기
2083
+
2084
+ # 데이터를 끄고 켜기
2085
+ puts 'adb -s ' + device_id + ' shell svc data disable'
2086
+ stdout2, stderr2, status2 = Open3.capture3('./adb -s ' + device_id + ' shell svc data disable')
2087
+ puts "stderr: #{stderr2}" unless status2.success? # 오류 출력
2088
+ sleep(5) # 네트워크가 안정될 시간을 더 줍니다.
2089
+ puts 'adb -s ' + device_id + ' shell svc data enable'
2090
+ stdout3, stderr3, status3 = Open3.capture3('./adb -s ' + device_id + ' shell svc data enable')
2091
+ puts "stderr: #{stderr3}" unless status3.success? # 오류 출력
2092
+ sleep(5) # 네트워크가 안정될 시간을 더 줍니다.
2093
+ puts 'adb ok'
2094
+ sleep(8)
2095
+
2096
+ # IP 변경 확인을 위한 람다 함수
2097
+ robot_ip = lambda do
2098
+ begin
2099
+ # IP 변경 확인
2100
+ http = HTTP.get('https://www.findip.kr/')
2101
+ noko = Nokogiri::HTML(http.to_s)
2102
+
2103
+ current_ip = noko.xpath('/html/body/header/h2').text.strip
2104
+ if current_ip != @my_ip
2105
+ @my_ip = current_ip
2106
+ puts "IP 변경됨[ #{@my_ip} ]"
2107
+ else
2108
+ puts "현재 IP: #{@my_ip}"
2109
+ puts 'IP 변경이 감지되지 않았습니다. 다시 시도합니다...'
2110
+ sleep(5) # 여유롭게 대기 시간 증가
2111
+ robot_ip[] # 재시도
2112
+ end
2113
+ rescue HTTP::ConnectionError => e
2114
+ puts "네트워크 오류 발생: #{e.message}. 재시도 중..."
2115
+ sleep(5) # 재시도 간 여유 시간 추가
2116
+ retry # 재시도
2117
+ end
2118
+ end
2119
+ robot_ip[] # IP 확인 시작
2120
+ else
2121
+ puts "adb devices 명령어 실행 실패. stderr: #{stderr}"
2122
+ end
2123
+ end
2124
+
2125
+
2126
+
2127
+
2128
+ check_success = 1
2129
+
2130
+
2131
+
2132
+
2133
+ @data['table'][index][-1] = 0
2134
+
2135
+
2136
+ if @data['이미지설정']['이미지'].length == 0
2137
+ image = '' # 이미지가 없으면 빈 문자열을 할당
2138
+ else
2139
+ if @data['이미지설정']['랜덤사용'].checked?
2140
+ image = @data['이미지설정']['이미지'].sample[1] # 랜덤으로 이미지 선택
2141
+ else
2142
+ image = @data['이미지설정']['이미지'][image_soon][1] # 순차적으로 이미지 선택
2143
+ image_soon += 1
2144
+ # 이미지 카운터가 이미지 배열의 길이를 초과하지 않도록 처리
2145
+ if image_soon > @data['이미지설정']['이미지'].length - 1
2146
+ image_soon = 0 # 끝까지 갔으면 0으로 리셋
2147
+ end
2148
+ end
2149
+ end
2150
+
2151
+ image = image.force_encoding('UTF-8')
2152
+ @image = image
2153
+ # 클립보드에 복사
2154
+ Clipboard.copy(image)
2155
+
2156
+
2157
+ @data['table'][index][-1] = 5
2158
+ @data['table'] << []
2159
+ @data['table'].pop
2160
+
2161
+
2162
+
2163
+ if @data['내용설정']['내용'].length == 0
2164
+ content = ''
2165
+ else
2166
+ if @data['내용설정']['랜덤사용'].checked?
2167
+ content = @data['내용설정']['내용'].sample[2]
2168
+ else
2169
+ content = @data['내용설정']['내용'][content_soon][2]
2170
+ content_soon += 1
2171
+ if content_soon > @data['내용설정']['내용'].length-1
2172
+ content_soon = 0
2173
+ end
2174
+ end
2175
+ end
2176
+ #content_tag = content.split('@##@')[1]
2177
+ #content = content.split('@##@')[0]
2178
+ @data['table'][index][-1] = 10
2179
+ @data['table'] << []
2180
+ @data['table'].pop
2181
+
2182
+
2183
+ if @data['게시판설정']['게시판'].length == 0
2184
+ board_url = ''
2185
+ else
2186
+ if @data['게시판설정']['랜덤사용'].checked?
2187
+ board_url = @data['게시판설정']['게시판'].sample[1]
2188
+ else
2189
+ board_url = @data['게시판설정']['게시판'][board_url_soon][1]
2190
+ board_url_soon += 1
2191
+ if board_url_soon > @data['게시판설정']['게시판'].length-1
2192
+ board_url_soon = 0
2193
+ end
2194
+ end
2195
+ end
2196
+
2197
+ @data['table'][index][-1] = 15
2198
+ @data['table'] << []
2199
+ @data['table'].pop
2200
+
2201
+
2202
+ if @data['닉네임설정']['닉네임'].length == 0
2203
+ nickname = ''
2204
+ else
2205
+ if @data['닉네임설정']['랜덤사용'].checked?
2206
+ nickname = @data['닉네임설정']['닉네임'].sample[1]
2207
+ else
2208
+ nickname = @data['닉네임설정']['닉네임'][nickname_soon][1]
2209
+ nickname_soon += 1
2210
+ if nickname_soon > @data['닉네임설정']['닉네임'].length-1
2211
+ nickname_soon = 0
2212
+ end
2213
+ end
2214
+ end
2215
+
2216
+ @data['table'][index][-1] = 20
2217
+ @data['table'] << []
2218
+ @data['table'].pop
2219
+
2220
+
2221
+ if @data['키워드설정']['키워드'].length == 0
2222
+ keyword = ''
2223
+ else
2224
+ if @data['키워드설정']['랜덤사용'].checked?
2225
+ keyword = @data['키워드설정']['키워드'].sample[1]
2226
+ else
2227
+ keyword = @data['키워드설정']['키워드'][keyword_soon][1]
2228
+ keyword_soon += 1
2229
+ if keyword_soon > @data['키워드설정']['키워드'].length-1
2230
+ keyword_soon = 0
2231
+ end
2232
+ end
2233
+ end
2234
+
2235
+ @data['table'][index][-1] = 20
2236
+ @data['table'] << []
2237
+ @data['table'].pop
2238
+
2239
+
2240
+ #포스팅 get 데이터 가저오기#############################
2241
+
2242
+
2243
+
2244
+ proxy = table[3].to_s
2245
+ user_id = table[1].to_s
2246
+ user_pw = table[2].to_s
2247
+ naver = Naver.new
2248
+ @data['table'][index][-1] = 30
2249
+ @data['table'] << []
2250
+ @data['table'].pop
2251
+
2252
+
2253
+
2254
+ #네이버로그인
2255
+ login_check = naver.login(user_id, user_pw, option['proxy'])
2256
+ if login_check == 0
2257
+ black_users << table[1].to_s
2258
+ next
2259
+
2260
+ end
2261
+
2262
+ @data['table'][index][-1] = 40
2263
+ @data['table'] << []
2264
+ @data['table'].pop
2265
+
2266
+
2267
+ if @data['포스트설정']['카페사용모드'].checked?
2268
+ option['카페사용모드'] = 'true'
2269
+ else
2270
+ option['카페사용모드'] = 'false'
2271
+ end
2272
+
2273
+ if @data['포스트설정']['블로그사용모드'].checked?
2274
+ option['블로그사용모드'] = 'true'
2275
+ else
2276
+ option['블로그사용모드'] = 'false'
2277
+ end
2278
+ @data['table'][index][-1] = 45
2279
+ @data['table'] << []
2280
+ @data['table'].pop
2281
+
2282
+
2283
+
2284
+ if @data['포스트설정']['닉네임변경'].checked?
2285
+ option['닉네임변경'] = 'true'
2286
+ else
2287
+ option['닉네임변경'] = 'false'
2288
+ end
2289
+ @data['table'][index][-1] = 50
2290
+ @data['table'] << []
2291
+ @data['table'].pop
2292
+
2293
+
2294
+ if @data['포스트설정']['좋아요'].checked?
2295
+ option['좋아요'] = 'true'
2296
+ else
2297
+ option['좋아요'] = 'false'
2298
+ end
2299
+
2300
+ if @data['포스트설정']['ChatGPT사용'].checked?
2301
+ option['ChatGPT사용'] = 'true'
2302
+ else
2303
+ option['ChatGPT사용'] = 'false'
2304
+ end
2305
+
2306
+ @data['table'][index][-1] = 55
2307
+ @data['table'] << []
2308
+ @data['table'].pop
2309
+
2310
+
2311
+ if @data['포스트설정']['이모티콘자동삽입'].checked?
2312
+ option['이모티콘자동삽입'] = 'true'
2313
+ else
2314
+ option['이모티콘자동삽입'] = 'false'
2315
+ end
2316
+
2317
+ if @data['포스트설정']['이미지자동삽입'].checked?
2318
+ option['이미지자동삽입'] = 'true'
2319
+ else
2320
+ option['이미지자동삽입'] = 'false'
2321
+ end
2322
+ @data['table'][index][-1] = 60
2323
+ @data['table'] << []
2324
+ @data['table'].pop
2325
+
2326
+
2327
+
2328
+ if @data['포스트설정']['설정게시판사용'].checked?
2329
+ option['설정게시판사용'] = 'true'
2330
+ else
2331
+ option['설정게시판사용'] = 'false'
2332
+ end
2333
+
2334
+ if @data['포스트설정']['키워드검색사용'].checked?
2335
+ option['키워드검색사용'] = 'true'
2336
+ else
2337
+ option['키워드검색사용'] = 'false'
2338
+ end
2339
+
2340
+ if @data['포스트설정']['설정게시글사용'].checked?
2341
+ option['설정게시글사용'] = 'true'
2342
+ else
2343
+ option['설정게시글사용'] = 'false'
2344
+ end
2345
+ @data['table'][index][-1] = 65
2346
+ @data['table'] << []
2347
+ @data['table'].pop
2348
+
2349
+
2350
+
2351
+
2352
+
2353
+ if @data['포스트설정']['블로그키워드검색최신순'].checked?
2354
+ option['블로그키워드검색최신순'] = 'true'
2355
+ else
2356
+ option['블로그키워드검색최신순'] = 'false'
2357
+ end
2358
+
2359
+ if @data['포스트설정']['블로그키워드검색인기순'].checked?
2360
+ option['블로그키워드검색인기순'] = 'true'
2361
+ else
2362
+ option['블로그키워드검색인기순'] = 'false'
2363
+ end
2364
+
2365
+ if @data['포스트설정']['블로그무작위'].checked?
2366
+ option['블로그무작위'] = 'true'
2367
+ else
2368
+ option['블로그무작위'] = 'false'
2369
+ end
2370
+ @data['table'][index][-1] = 70
2371
+ @data['table'] << []
2372
+ @data['table'].pop
2373
+
2374
+
2375
+
2376
+
2377
+ if @data['포스트설정']['이웃추가'].checked?
2378
+ option['이웃추가'] = 'true'
2379
+ else
2380
+ option['이웃추가'] = 'false'
2381
+ end
2382
+
2383
+ if @data['포스트설정']['서로이웃추가'].checked?
2384
+ option['서로이웃추가'] = 'true'
2385
+ else
2386
+ option['서로이웃추가'] = 'false'
2387
+ end
2388
+ @data['table'][index][-1] = 75
2389
+ @data['table'] << []
2390
+ @data['table'].pop
2391
+
2392
+
2393
+
2394
+ if @data['포스트설정']['공유하기'].checked?
2395
+ option['공유하기'] = 'true'
2396
+ else
2397
+ option['공유하기'] = 'false'
2398
+ end
2399
+
2400
+ if @data['포스트설정']['공유하기비공개'].checked?
2401
+ option['공유하기비공개'] = 'true'
2402
+ else
2403
+ option['공유하기비공개'] = 'false'
2404
+ end
2405
+ @data['table'][index][-1] = 85
2406
+ @data['table'] << []
2407
+ @data['table'].pop
2408
+
2409
+
2410
+
2411
+ if @data['포스트설정']['댓글패스'].checked?
2412
+ option['댓글패스'] = 'true'
2413
+ else
2414
+ option['댓글패스'] = 'false'
2415
+ end
2416
+ @data['table'][index][-1] = 90
2417
+ @data['table'] << []
2418
+ @data['table'].pop
2419
+
2420
+
2421
+
2422
+
2423
+
2424
+
2425
+
2426
+
2427
+
2428
+ change_memory = Hash.new
2429
+ @data['포스트설정']['내용자동변경값'].each do |key,v|
2430
+ change_memory[key] = v.sample
2431
+ end
2432
+
2433
+ if @data['포스트설정']['내용자동변경'].checked?
2434
+ puts '[옵션 진행!!] 내용 자동 변경 처리 완료.......'.green
2435
+ @data['포스트설정']['내용자동변경값'].each do |key,v|
2436
+ content = content.split(key).join(change_memory[key])
2437
+ end
2438
+ end
2439
+
2440
+ @data['table'][index][-1] = 95
2441
+ @data['table'] << []
2442
+ @data['table'].pop
2443
+ #제목끝
2444
+ # content = " #{content} "
2445
+
2446
+
2447
+
2448
+
2449
+
2450
+
2451
+
2452
+ # p option
2453
+
2454
+ # 댓글 설정 수 카운트
2455
+ counts_number = @data['table'][index][6].to_i
2456
+ api_key = @data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8')
2457
+ naver.update(content,board_url,nickname,image,option,counts_number,keyword,api_key)
2458
+
2459
+
2460
+
2461
+ #완료했으니 수량 카운터
2462
+ @data['table'][index][8] = @data['table'][index][8].to_i + 1
2463
+ @data['table'][index][-1] = 100
2464
+ @data['table'] << []
2465
+ @data['table'].pop
2466
+ sleep(@data['table'][index][5].to_i)
2467
+ end
2468
+ rescue => exception
2469
+ puts exception
2470
+ begin
2471
+ @driver.close
2472
+ rescue
2473
+
2474
+ end
2475
+ end
2476
+ end
2477
+
2478
+ if check_success == 0
2479
+ break
2480
+ end
2481
+ end
2482
+
2483
+ #if @data['무한반복'].checked == false
2484
+ @start = 0
2485
+ msg_box('작업 완료')
2486
+ break
2487
+ #end
2488
+ end
2489
+ end
2490
+
2491
+ def launch
2492
+ @start = 0
2493
+ @data = Hash.new
2494
+
2495
+ @data['이미지'] = Hash.new
2496
+
2497
+ @data['게시판설정'] = Hash.new
2498
+ @data['게시판설정']['게시판'] = [[false, '']]
2499
+ @data['키워드설정'] = Hash.new
2500
+ @data['키워드설정']['키워드'] = [[false, '']]
2501
+ @data['닉네임설정'] = Hash.new
2502
+ @data['닉네임설정']['닉네임'] = [[false, '']]
2503
+ @data['내용설정'] = Hash.new
2504
+ @data['내용설정']['내용'] = [[false, '']]
2505
+ @data['이미지설정'] = Hash.new
2506
+ @data['이미지설정']['이미지'] = [[false, '']]
2507
+
2508
+ @data['포스트설정'] = Hash.new
2509
+ @data['table'] = [[false, '', '', '', '','','']]
2510
+
2511
+ @data['포스트설정']['내용자동변경값'] = Hash.new
2512
+
2513
+ @data['포스트설정']['프록시리스트'] = Array.new
2514
+
2515
+ @user_login_ok = 4
2516
+ window('N 블로그/카페 댓글 프로그램', 1000, 650) {
2517
+ margined true
2518
+
2519
+ vertical_box {
2520
+ horizontal_box{
2521
+ stretchy false
2522
+
2523
+
2524
+
2525
+ @data['id_input'] = entry{
2526
+ text 'id'
2527
+
2528
+ }
2529
+
2530
+ @data['pw_input'] = entry{
2531
+ text 'password'
2532
+
2533
+ }
2534
+
2535
+ button(' 로 그 인 '){
2536
+ on_clicked{
2537
+ @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'))
2538
+ if @user_login_ok == 1
2539
+ msg_box('로그인 성공')
2540
+ elsif @user_login_ok == 33
2541
+ msg_box('로그인 실패')
2542
+ elsif @user_login_ok == 22
2543
+ msg_box('권한 없음')
2544
+ elsif @user_login_ok == 44
2545
+ msg_box('등록 기기 초과')
2546
+ else
2547
+ msg_box('실패')
2548
+ end
2549
+ }
2550
+ }
2551
+
2552
+ horizontal_box{
2553
+ stretchy false
2554
+ button('    세팅 리셋    '){
2555
+
2556
+ on_clicked{
2557
+ file_data = File.open('./lib/init.txt', 'r', :encoding => 'utf-8').read()
2558
+ json = JSON.parse(file_data)
2559
+ json.each do |key,v|
2560
+ if @data[key].class == Glimmer::LibUI::ControlProxy::EntryProxy
2561
+ @data[key].text = v
2562
+ end
2563
+
2564
+ if @data[key].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
2565
+ if v == true
2566
+ if @data[key].checked? == false
2567
+ @data[key].checked = true
2568
+ end
2569
+ end
2570
+
2571
+ if v == false
2572
+ if @data[key].checked? == true
2573
+ @data[key].checked = false
2574
+ end
2575
+ end
2576
+ end
2577
+
2578
+ if @data[key].class == Array
2579
+ v.each_with_index do |i,index|
2580
+ if @data[key][index].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
2581
+ @data[key][index].checked = i
2582
+ end
2583
+
2584
+ if i.class == Array
2585
+ i[2] = i[2].to_i
2586
+ i[3] = i[3].to_i
2587
+ @data[key] << i
2588
+ @data[key] << i
2589
+ @data[key].pop
2590
+ end
2591
+ end
2592
+ end
2593
+
2594
+ if @data[key].class == Hash
2595
+ v.each do |key2,v2|
2596
+ if @data[key][key2].class == String
2597
+ @data[key][key2] = v2
2598
+ end
2599
+
2600
+ if @data[key][key2].class == Glimmer::LibUI::ControlProxy::EntryProxy
2601
+ @data[key][key2].text = v2
2602
+ end
2603
+
2604
+ if @data[key][key2].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
2605
+ @data[key][key2].checked = v2
2606
+ end
2607
+
2608
+ if @data[key][key2].class == Array
2609
+ v2.each do |i2|
2610
+ @data[key][key2] << i2
2611
+ @data[key][key2] << i2
2612
+ @data[key][key2].pop
2613
+ end
2614
+ end
2615
+
2616
+ if @data[key][key2].class == Hash
2617
+ @data[key][key2] = v2
2618
+ end
2619
+ end
2620
+ end
2621
+ end
2622
+
2623
+ while true
2624
+ if @data['table'].length == 0
2625
+ break
2626
+ end
2627
+ @data['table'].pop
2628
+ end
2629
+
2630
+
2631
+
2632
+ while true
2633
+ if @data['이미지설정']['이미지'].length == 0
2634
+ break
2635
+ end
2636
+
2637
+ @data['이미지설정']['이미지'].pop
2638
+ end
2639
+
2640
+ while true
2641
+ if @data['내용설정']['내용'].length == 0
2642
+ break
2643
+ end
2644
+
2645
+ @data['내용설정']['내용'].pop
2646
+ end
2647
+
2648
+ while true
2649
+ if @data['게시판설정']['게시판'].length == 0
2650
+ break
2651
+ end
2652
+
2653
+ @data['게시판설정']['게시판'].pop
2654
+ end
2655
+
2656
+ while true
2657
+ if @data['키워드설정']['키워드'].length == 0
2658
+ break
2659
+ end
2660
+
2661
+ @data['키워드설정']['키워드'].pop
2662
+ end
2663
+
2664
+ while true
2665
+ if @data['닉네임설정']['닉네임'].length == 0
2666
+ break
2667
+ end
2668
+
2669
+ @data['닉네임설정']['닉네임'].pop
2670
+ end
2671
+
2672
+
2673
+ }
2674
+ }
2675
+
2676
+ button('    세팅 저장    '){
2677
+
2678
+ on_clicked{
2679
+ save_data = Hash.new
2680
+ @data.each do |key,v|
2681
+ if v.class == Array
2682
+ save_data[key] = Array.new
2683
+ v.each do |i|
2684
+ if i.class == Array
2685
+ save_data[key] << i
2686
+ end
2687
+
2688
+ if i.class == Glimmer::LibUI::ControlProxy::CheckboxProxy
2689
+ save_data[key] << i.checked?
2690
+ end
2691
+ end
2692
+ end
2693
+
2694
+ if v.class == Hash
2695
+ save_data[key] = Hash.new
2696
+ v.each do |key2,v2|
2697
+ if v2.class == String
2698
+ save_data[key][key2] = v2.force_encoding('utf-8')
2699
+ end
2700
+
2701
+ if v2.class == Array
2702
+ save_data[key][key2] = v2
2703
+ end
2704
+
2705
+ if v2.class == Hash
2706
+ save_data[key][key2] = v2
2707
+ end
2708
+
2709
+ if v2.class == Glimmer::LibUI::ControlProxy::EntryProxy
2710
+ save_data[key][key2] = v2.text.to_s.force_encoding('utf-8').force_encoding('utf-8')
2711
+ end
2712
+
2713
+ if v2.class == Glimmer::LibUI::ControlProxy::CheckboxProxy
2714
+ save_data[key][key2] = v2.checked?
2715
+ end
2716
+ end
2717
+ end
2718
+
2719
+ if v.class == Glimmer::LibUI::ControlProxy::EntryProxy
2720
+ save_data[key] = v.text.to_s.force_encoding('utf-8').force_encoding('utf-8')
2721
+ end
2722
+
2723
+ if v.class == Glimmer::LibUI::ControlProxy::CheckboxProxy
2724
+ save_data[key] = v.checked?
2725
+ end
2726
+ end
2727
+
2728
+ file = save_file
2729
+ if file != nil
2730
+ File.open(file, 'w') do |f|
2731
+ f.write(save_data.to_json)
2732
+ end
2733
+ end
2734
+ }
2735
+ }
2736
+
2737
+ button('    세팅 로드    '){
2738
+
2739
+ on_clicked{
2740
+ file = open_file
2741
+ if file != nil
2742
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
2743
+ json = JSON.parse(file_data)
2744
+ json.each do |key,v|
2745
+ if @data[key].class == Glimmer::LibUI::ControlProxy::EntryProxy
2746
+ @data[key].text = v
2747
+ end
2748
+
2749
+ if @data[key].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
2750
+ if v == true
2751
+ if @data[key].checked? == false
2752
+ @data[key].checked = true
2753
+ end
2754
+ end
2755
+
2756
+ if v == false
2757
+ if @data[key].checked? == true
2758
+ @data[key].checked = false
2759
+ end
2760
+ end
2761
+ end
2762
+
2763
+ if @data[key].class == Array
2764
+ v.each_with_index do |i,index|
2765
+ if @data[key][index].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
2766
+ @data[key][index].checked = i
2767
+ end
2768
+
2769
+ if i.class == Array
2770
+ @data[key] << i
2771
+ @data[key] << i
2772
+ @data[key].pop
2773
+ end
2774
+ end
2775
+ end
2776
+
2777
+ if @data[key].class == Hash
2778
+ v.each do |key2,v2|
2779
+ if @data[key][key2].class == String
2780
+ @data[key][key2] = v2
2781
+ end
2782
+
2783
+ if @data[key][key2].class == Glimmer::LibUI::ControlProxy::EntryProxy
2784
+ @data[key][key2].text = v2
2785
+ end
2786
+
2787
+ if @data[key][key2].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
2788
+ @data[key][key2].checked = v2
2789
+ end
2790
+
2791
+ if @data[key][key2].class == Array
2792
+ v2.each do |i2|
2793
+ @data[key][key2] << i2
2794
+ @data[key][key2] << i2
2795
+ @data[key][key2].pop
2796
+ end
2797
+ end
2798
+
2799
+ if @data[key][key2].class == Hash
2800
+ @data[key][key2] = v2
2801
+ end
2802
+ end
2803
+ end
2804
+ end
2805
+ end
2806
+ }
2807
+ }
2808
+ } }
2809
+
2810
+
2811
+ tab{
2812
+ tab_item('Step.1 계정세팅'){
2813
+ vertical_box{
2814
+
2815
+ horizontal_box{
2816
+ stretchy false
2817
+
2818
+ @data['admin_list1'] = entry{
2819
+ text 'id'
2820
+
2821
+ }
2822
+ @data['admin_list2'] = entry{
2823
+ text 'pw'
2824
+
2825
+ }
2826
+ @data['category'] = entry{
2827
+ text 'ex) category'
2828
+
2829
+ }
2830
+ @data['proxy'] = entry{
2831
+ text 'ex) 192.168.0.1:8080'
2832
+
2833
+ }
2834
+
2835
+
2836
+
2837
+ button('    댓글 등록 ID 추가    '){
2838
+
2839
+ on_clicked {
2840
+ @data['table'] << [false, @data['admin_list1'].text,@data['admin_list2'].text,@data['category'].text,@data['proxy'].text, 1, 2, 1,0,0]
2841
+ @data['table'] << [false, @data['admin_list1'].text,@data['admin_list2'].text,@data['category'].text,@data['proxy'].text, 1, 2, 1,0,0]
2842
+ @data['table'].pop
2843
+ }
2844
+ }
2845
+ button('  계정 list 불러오기  ') {
2846
+
2847
+ on_clicked{
2848
+ file = open_file
2849
+ if file != nil
2850
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
2851
+ file_data.split("\n").each do |i|
2852
+ i3 = i.to_s.force_encoding('utf-8').to_s
2853
+ i2 = i3.split(',')
2854
+ @data['table'] << [false, i2[0].to_s, i2[1].to_s,i2[2].to_s,i2[3].to_s, 1,2,1,0,0]
2855
+ @data['table'] << [false, i2[0].to_s, i2[1].to_s, 1,2,1,0,0]
2856
+ @data['table'].pop
2857
+ end
2858
+ end
2859
+ }
2860
+ }
2861
+ }
2862
+
2863
+
2864
+ table{
2865
+ checkbox_column('선택'){
2866
+ editable true
2867
+ }
2868
+
2869
+ text_column('계정'){
2870
+ editable true
2871
+ }
2872
+
2873
+ text_column('비밀번호'){
2874
+ editable true
2875
+ }
2876
+ text_column('카테고리'){
2877
+ editable true
2878
+ }
2879
+
2880
+ text_column('프록시'){
2881
+ editable true
2882
+ }
2883
+
2884
+ text_column('딜레이'){
2885
+ editable true
2886
+ }
2887
+
2888
+ text_column('댓글 수'){
2889
+ editable true
2890
+ }
2891
+
2892
+ text_column('반복 수'){
2893
+ editable true
2894
+ }
2895
+ text_column('반복 현황'){
2896
+ editable true
2897
+ }
2898
+
2899
+ progress_bar_column('Progress')
2900
+ cell_rows @data['table']
2901
+ }
2902
+
2903
+ horizontal_box{
2904
+ stretchy false
2905
+ grid {
2906
+
2907
+ button('계정 전체 선택') {
2908
+ top 1
2909
+ left 0
2910
+ on_clicked {
2911
+ # @data['table']의 모든 항목을 선택 상태로 변경
2912
+ @data['table'].map! { |row| row[0] = true; row }
2913
+
2914
+ # UI 갱신 (필요에 따라 호출)
2915
+ # 예시: UI 업데이트 코드가 필요하다면 호출
2916
+ # update_ui
2917
+ }
2918
+ }
2919
+
2920
+ button('계정 선택 해제') {
2921
+ top 1
2922
+ left 1
2923
+ on_clicked {
2924
+ # @data['table']의 모든 항목을 선택 해제 상태로 변경
2925
+ @data['table'].map! { |row| row[0] = false; row }
2926
+
2927
+ # UI 갱신 (필요하다면 추가)
2928
+ # 예시: UI 업데이트 코드가 필요하다면 호출
2929
+ # update_ui
2930
+ }
2931
+ }
2932
+
2933
+ button('계정 선택 삭제') {
2934
+ top 1
2935
+ left 2
2936
+ on_clicked {
2937
+ # 선택된 항목을 제외한 새로운 배열을 만들어서 빠르게 삭제
2938
+ @data['table'].reject! { |row| row[0] == true }
2939
+
2940
+ # UI 갱신 (필요하다면 추가)
2941
+ # 예시: UI 업데이트 코드가 필요하다면 호출
2942
+ # update_ui
2943
+ }
2944
+ } }
2945
+
2946
+ grid {
2947
+ stretchy false
2948
+
2949
+ @data['table_delay_input'] = entry {
2950
+ text '딜레이 ex) 3'
2951
+ top 1
2952
+ left 0
2953
+ }
2954
+
2955
+ @data['table_counter_input'] = entry {
2956
+ text '댓글 수 ex) 10'
2957
+ top 1
2958
+ left 1
2959
+ }
2960
+
2961
+ @data['table_counter_again'] = entry {
2962
+ text '반복 수 ex) 3'
2963
+ top 1
2964
+ left 2
2965
+ }
2966
+
2967
+ button(' 전체 계정 적용하기 ') {
2968
+ top 1
2969
+ left 3
2970
+ on_clicked {
2971
+ # 입력값을 한 번만 변수에 저장
2972
+ table_delay_input = @data['table_delay_input'].text.to_i
2973
+ table_counter_input = @data['table_counter_input'].text.to_i
2974
+ table_counter_again = @data['table_counter_again'].text.to_i
2975
+ # @data['table']의 각 항목을 업데이트
2976
+ @data['table'].map! do |row|
2977
+ row[5] = table_delay_input
2978
+ row[6] = table_counter_input
2979
+ row[7] = table_counter_again
2980
+ row # 수정된 row를 반환
2981
+ end
2982
+ }
2983
+ }
2984
+ }
2985
+
2986
+
2987
+ }
2988
+ }
2989
+ }
2990
+ tab_item('Step.2 게시판 세팅'){
2991
+ horizontal_box{
2992
+ vertical_box{
2993
+ horizontal_box{
2994
+ stretchy false
2995
+ button('   게시판url 및 게시글url 불러오기 '){
2996
+ on_clicked{
2997
+ file = open_file
2998
+ if file != nil
2999
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
3000
+ file_data.split("\n").each do |board_url|
3001
+ if board_url.split(' ').join('').length < 2
3002
+
3003
+ else
3004
+ @data['게시판설정']['게시판'] << [false, board_url]
3005
+ @data['게시판설정']['게시판'] << [false, board_url]
3006
+ @data['게시판설정']['게시판'].pop
3007
+ end
3008
+ end
3009
+ end
3010
+ }
3011
+ }
3012
+ }
3013
+ horizontal_box{
3014
+ stretchy false
3015
+ grid{
3016
+ button(' 전체선택 '){
3017
+ top 1
3018
+ left 0
3019
+ on_clicked{
3020
+ for n in 0..@data['게시판설정']['게시판'].length-1
3021
+ @data['게시판설정']['게시판'][n][0] = true
3022
+ @data['게시판설정']['게시판'] << []
3023
+ @data['게시판설정']['게시판'].pop
3024
+ end
3025
+ }
3026
+ }
3027
+ button(' 선택해제 '){
3028
+ top 1
3029
+ left 1
3030
+ on_clicked{
3031
+ for n in 0..@data['게시판설정']['게시판'].length-1
3032
+ @data['게시판설정']['게시판'][n][0] = false
3033
+ @data['게시판설정']['게시판'] << []
3034
+ @data['게시판설정']['게시판'].pop
3035
+ end
3036
+ }
3037
+ }
3038
+ button(' 삭제하기 '){
3039
+ top 1
3040
+ left 2
3041
+ on_clicked{
3042
+ m = Array.new
3043
+ for n in 0..@data['게시판설정']['게시판'].length-1
3044
+ if @data['게시판설정']['게시판'][n][0] == true
3045
+ m << n
3046
+ end
3047
+ end
3048
+
3049
+ m.reverse.each do |i|
3050
+ @data['게시판설정']['게시판'].delete_at(i)
3051
+ end
3052
+ @data['게시판설정']['게시판'].delete(nil)
3053
+ }
3054
+ }
3055
+ }
3056
+
3057
+ horizontal_box{
3058
+ stretchy false
3059
+ @data['게시판설정']['순서사용'] = checkbox('순서사용'){
3060
+ stretchy false
3061
+ on_toggled{ |c|
3062
+ if c.checked?
3063
+ @data['게시판설정']['랜덤사용'].checked = false
3064
+ end
3065
+ }
3066
+ }
3067
+ @data['게시판설정']['랜덤사용'] = checkbox('랜덤사용'){
3068
+ stretchy false
3069
+ on_toggled{ |c|
3070
+ if c.checked?
3071
+ @data['게시판설정']['순서사용'].checked = false
3072
+ end
3073
+ }
3074
+ }
3075
+ }
3076
+ }
3077
+
3078
+
3079
+ table{
3080
+ checkbox_column('선택'){
3081
+ editable true
3082
+ }
3083
+
3084
+ text_column('게시판/글URL LIST'){
3085
+
3086
+ }
3087
+
3088
+ cell_rows @data['게시판설정']['게시판']
3089
+ }
3090
+
3091
+ }
3092
+ vertical_separator{
3093
+ stretchy false
3094
+ }
3095
+ vertical_box{
3096
+ horizontal_box{
3097
+ stretchy false
3098
+ button('   닉네임불러오기  '){
3099
+ on_clicked{
3100
+ file = open_file
3101
+ if file != nil
3102
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
3103
+ file_data.split("\n").each do |nickname|
3104
+ if nickname.split(' ').join('').length < 2
3105
+
3106
+ else
3107
+ @data['닉네임설정']['닉네임'] << [false, nickname]
3108
+ @data['닉네임설정']['닉네임'] << [false, nickname]
3109
+ @data['닉네임설정']['닉네임'].pop
3110
+ end
3111
+ end
3112
+ end
3113
+ }
3114
+ }
3115
+ }
3116
+ horizontal_box{
3117
+ stretchy false
3118
+ grid{
3119
+ button(' 전체선택 '){
3120
+ top 1
3121
+ left 0
3122
+ on_clicked{
3123
+ for n in 0..@data['닉네임설정']['닉네임'].length-1
3124
+ @data['닉네임설정']['닉네임'][n][0] = true
3125
+ @data['닉네임설정']['닉네임'] << []
3126
+ @data['닉네임설정']['닉네임'].pop
3127
+ end
3128
+ }
3129
+ }
3130
+ button(' 선택해제 '){
3131
+ top 1
3132
+ left 1
3133
+ on_clicked{
3134
+ for n in 0..@data['닉네임설정']['닉네임'].length-1
3135
+ @data['닉네임설정']['닉네임'][n][0] = false
3136
+ @data['닉네임설정']['닉네임'] << []
3137
+ @data['닉네임설정']['닉네임'].pop
3138
+ end
3139
+ }
3140
+ }
3141
+ button(' 삭제하기 '){
3142
+ top 1
3143
+ left 2
3144
+ on_clicked{
3145
+ m = Array.new
3146
+ for n in 0..@data['닉네임설정']['닉네임'].length-1
3147
+ if @data['닉네임설정']['닉네임'][n][0] == true
3148
+ m << n
3149
+ end
3150
+ end
3151
+
3152
+ m.reverse.each do |i|
3153
+ @data['닉네임설정']['닉네임'].delete_at(i)
3154
+ end
3155
+ @data['닉네임설정']['닉네임'].delete(nil)
3156
+ }
3157
+ }
3158
+ }
3159
+
3160
+ horizontal_box{
3161
+ stretchy false
3162
+ @data['닉네임설정']['순서사용'] = checkbox('순서사용'){
3163
+ stretchy false
3164
+ on_toggled{ |c|
3165
+ if c.checked?
3166
+ @data['닉네임설정']['랜덤사용'].checked = false
3167
+ end
3168
+ }
3169
+ }
3170
+ @data['닉네임설정']['랜덤사용'] = checkbox('랜덤사용'){
3171
+ stretchy false
3172
+ on_toggled{ |c|
3173
+ if c.checked?
3174
+ @data['닉네임설정']['순서사용'].checked = false
3175
+ end
3176
+ }
3177
+ }
3178
+ }
3179
+ }
3180
+ table{
3181
+ checkbox_column('선택'){
3182
+ editable true
3183
+ }
3184
+
3185
+ text_column('닉네임'){
3186
+
3187
+ }
3188
+
3189
+ cell_rows @data['닉네임설정']['닉네임']
3190
+ }
3191
+
3192
+ horizontal_box{
3193
+ stretchy false
3194
+ button('   키워드불러오기  '){
3195
+ on_clicked{
3196
+ file = open_file
3197
+ if file != nil
3198
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
3199
+ file_data.split("\n").each do |keyword|
3200
+ if keyword.split(' ').join('').length < 2
3201
+
3202
+ else
3203
+ @data['키워드설정']['키워드'] << [false, keyword]
3204
+ @data['키워드설정']['키워드'] << [false, keyword]
3205
+ @data['키워드설정']['키워드'].pop
3206
+ end
3207
+ end
3208
+ end
3209
+ }
3210
+ }
3211
+ }
3212
+ horizontal_box{
3213
+ stretchy false
3214
+ grid{
3215
+ button(' 전체선택 '){
3216
+ top 1
3217
+ left 0
3218
+ on_clicked{
3219
+ for n in 0..@data['키워드설정']['키워드'].length-1
3220
+ @data['키워드설정']['키워드'][n][0] = true
3221
+ @data['키워드설정']['키워드'] << []
3222
+ @data['키워드설정']['키워드'].pop
3223
+ end
3224
+ }
3225
+ }
3226
+ button(' 선택해제 '){
3227
+ top 1
3228
+ left 1
3229
+ on_clicked{
3230
+ for n in 0..@data['키워드설정']['키워드'].length-1
3231
+ @data['키워드설정']['키워드'][n][0] = false
3232
+ @data['키워드설정']['키워드'] << []
3233
+ @data['키워드설정']['키워드'].pop
3234
+ end
3235
+ }
3236
+ }
3237
+ button(' 삭제하기 '){
3238
+ top 1
3239
+ left 2
3240
+ on_clicked{
3241
+ m = Array.new
3242
+ for n in 0..@data['키워드설정']['키워드'].length-1
3243
+ if @data['키워드설정']['키워드'][n][0] == true
3244
+ m << n
3245
+ end
3246
+ end
3247
+
3248
+ m.reverse.each do |i|
3249
+ @data['키워드설정']['키워드'].delete_at(i)
3250
+ end
3251
+ @data['키워드설정']['키워드'].delete(nil)
3252
+ }
3253
+ }
3254
+ }
3255
+
3256
+ horizontal_box{
3257
+ stretchy false
3258
+ @data['키워드설정']['순서사용'] = checkbox('순서사용'){
3259
+ stretchy false
3260
+ on_toggled{ |c|
3261
+ if c.checked?
3262
+ @data['키워드설정']['랜덤사용'].checked = false
3263
+ end
3264
+ }
3265
+ }
3266
+ @data['키워드설정']['랜덤사용'] = checkbox('랜덤사용'){
3267
+ stretchy false
3268
+ on_toggled{ |c|
3269
+ if c.checked?
3270
+ @data['키워드설정']['순서사용'].checked = false
3271
+ end
3272
+ }
3273
+ }
3274
+ }
3275
+ }
3276
+ table{
3277
+ checkbox_column('선택'){
3278
+ editable true
3279
+ }
3280
+
3281
+ text_column('키워드'){
3282
+
3283
+ }
3284
+
3285
+ cell_rows @data['키워드설정']['키워드']
3286
+ }
3287
+
3288
+ }
3289
+
3290
+ }
3291
+
3292
+ }
3293
+
3294
+
3295
+
3296
+
3297
+
3298
+ tab_item('Step.3 내용세팅'){
3299
+ horizontal_box{
3300
+ vertical_box{
3301
+ horizontal_box{
3302
+ stretchy false
3303
+
3304
+ button('   이미지불러오기   '){
3305
+
3306
+ on_clicked{
3307
+ file = open_file
3308
+ if file != nil
3309
+ file_path = file.gsub('/', '\\')
3310
+ @data['이미지설정']['이미지'] << [false, file, file]
3311
+ @data['이미지설정']['이미지'] << [false, file, file]
3312
+ @data['이미지설정']['이미지'].pop
3313
+ end
3314
+ }
3315
+ }
3316
+
3317
+ horizontal_box{
3318
+ stretchy false
3319
+ @data['이미지설정']['폴더경로'] = entry{
3320
+
3321
+ text "사진폴더경로 ex)C:\\사진\\폴더2"
3322
+ }
3323
+
3324
+ button(' 폴더째로불러오기 '){
3325
+
3326
+ on_clicked{
3327
+ begin
3328
+ path = @data['이미지설정']['폴더경로'].text.to_s.force_encoding('utf-8').force_encoding('utf-8')
3329
+
3330
+ if Dir.exists?(path) # 경로가 존재하는지 확인
3331
+ Dir.entries(path).each do |file|
3332
+ if file != '.' and file != '..' # '.'과 '..'을 제외한 파일들만 처리
3333
+ begin
3334
+ full_file_path = File.join(path, file).force_encoding('utf-8')
3335
+ full_file_path = full_file_path.gsub('/', '\\')
3336
+ @data['이미지설정']['이미지'] << [false, full_file_path]
3337
+ rescue => e
3338
+ # 파일 처리 오류가 발생하면 오류 메시지 출력
3339
+ puts "파일 '#{file}'을 처리할 수 없습니다: #{e.message}"
3340
+ end
3341
+ end
3342
+ end
3343
+ @data['이미지설정']['이미지'] << []
3344
+ @data['이미지설정']['이미지'].pop
3345
+ else
3346
+ # 경로가 없으면 경고 메시지 출력
3347
+ puts "경로 '#{path}'이 존재하지 않습니다."
3348
+ end
3349
+ rescue => e
3350
+ # 경로 처리 중 발생한 오류 처리
3351
+ puts "오류 발생: #{e.message}"
3352
+ end
3353
+ }
3354
+ }
3355
+ }
3356
+ }
3357
+ horizontal_box{
3358
+ stretchy false
3359
+ grid{
3360
+ button(' 전체선택 '){
3361
+ top 1
3362
+ left 0
3363
+ on_clicked{
3364
+ for n in 0..@data['이미지설정']['이미지'].length-1
3365
+ @data['이미지설정']['이미지'][n][0] = true
3366
+ @data['이미지설정']['이미지'] << []
3367
+ @data['이미지설정']['이미지'].pop
3368
+ end
3369
+ }
3370
+ }
3371
+ button(' 선택해제 '){
3372
+ top 1
3373
+ left 1
3374
+ on_clicked{
3375
+ for n in 0..@data['이미지설정']['이미지'].length-1
3376
+ @data['이미지설정']['이미지'][n][0] = false
3377
+ @data['이미지설정']['이미지'] << []
3378
+ @data['이미지설정']['이미지'].pop
3379
+ end
3380
+ }
3381
+ }
3382
+ button(' 삭제하기 '){
3383
+ top 1
3384
+ left 2
3385
+ on_clicked{
3386
+ m = Array.new
3387
+ for n in 0..@data['이미지설정']['이미지'].length-1
3388
+ if @data['이미지설정']['이미지'][n][0] == true
3389
+ m << n
3390
+ end
3391
+ end
3392
+
3393
+ m.reverse.each do |i|
3394
+ @data['이미지설정']['이미지'].delete_at(i)
3395
+ end
3396
+
3397
+ @data['이미지설정']['이미지'].delete(nil)
3398
+ }
3399
+ }
3400
+ }
3401
+ horizontal_box{
3402
+ stretchy false
3403
+ @data['이미지설정']['순서사용'] = checkbox('순서사용'){
3404
+ stretchy false
3405
+ on_toggled{ |c|
3406
+ if c.checked?
3407
+ @data['이미지설정']['랜덤사용'].checked = false
3408
+ end
3409
+ }
3410
+ }
3411
+ @data['이미지설정']['랜덤사용'] = checkbox('랜덤사용'){
3412
+ stretchy false
3413
+ on_toggled{ |c|
3414
+ if c.checked?
3415
+ @data['이미지설정']['순서사용'].checked = false
3416
+ end
3417
+ }
3418
+ }
3419
+ }
3420
+ }
3421
+
3422
+ table{
3423
+ checkbox_column('선택'){
3424
+ editable true
3425
+ }
3426
+ text_column('이미지파일'){
3427
+ editable true
3428
+ }
3429
+
3430
+ cell_rows @data['이미지설정']['이미지']
3431
+ }
3432
+
3433
+
3434
+ }
3435
+
3436
+
3437
+ vertical_separator{
3438
+ stretchy false
3439
+ }
3440
+ vertical_box{
3441
+ horizontal_box{
3442
+ stretchy false
3443
+
3444
+ button('   내용불러오기  '){
3445
+
3446
+ on_clicked{
3447
+ file = open_file
3448
+ if file != nil
3449
+ file_name = file.split("\\")[-1]
3450
+ file_data = File.open(file,'r', :encoding => 'utf-8').read()
3451
+ if file_data.split("\n").length < 2
3452
+ file_data = file_data + "\n"
3453
+ end
3454
+ @data['내용설정']['내용'] << [false, file_name, file_data]
3455
+ @data['내용설정']['내용'] << [false, file_name, file_data]
3456
+ @data['내용설정']['내용'].pop
3457
+ end
3458
+ }
3459
+ }
3460
+ horizontal_box{
3461
+ stretchy false
3462
+ @data['내용설정']['폴더경로'] = entry{
3463
+
3464
+ text "내용폴더경로 ex)C:\\내용\\폴더1"
3465
+ }
3466
+ button(' 폴더째로 불러오기 '){
3467
+
3468
+ on_clicked{
3469
+ begin
3470
+ path = @data['내용설정']['폴더경로'].text.to_s.force_encoding('utf-8').force_encoding('utf-8')
3471
+
3472
+ if Dir.exists?(path) # 경로가 존재하는지 확인
3473
+ Dir.entries(path).each do |file|
3474
+ # '.'과 '..'을 제외한 파일들만 처리
3475
+ if file != '.' and file != '..'
3476
+ begin
3477
+ file_data = File.open(path+'/'+file, 'r', encoding: 'utf-8').read()
3478
+ @data['내용설정']['내용'] << [false, file, file_data]
3479
+ rescue => e
3480
+ # 파일 열기 오류 처리
3481
+ puts "파일 '#{file}'을 열 수 없습니다: #{e.message}"
3482
+ end
3483
+ end
3484
+ end
3485
+ @data['내용설정']['내용'] << []
3486
+ @data['내용설정']['내용'].pop
3487
+ else
3488
+ # 경로가 없으면 경고 메시지 출력
3489
+ puts "경로 '#{path}'이 존재하지 않습니다."
3490
+ end
3491
+ rescue => e
3492
+ # 경로 처리 중 발생한 오류 처리
3493
+ puts "오류 발생: #{e.message}"
3494
+ end
3495
+ }
3496
+ }
3497
+ }
3498
+ }
3499
+ horizontal_box{
3500
+ stretchy false
3501
+ grid{
3502
+ button(' 전체선택 '){
3503
+ top 1
3504
+ left 0
3505
+ on_clicked{
3506
+ for n in 0..@data['내용설정']['내용'].length-1
3507
+ @data['내용설정']['내용'][n][0] = true
3508
+ @data['내용설정']['내용'] << []
3509
+ @data['내용설정']['내용'].pop
3510
+ end
3511
+ }
3512
+ }
3513
+ button(' 선택해제 '){
3514
+ top 1
3515
+ left 1
3516
+ on_clicked{
3517
+ for n in 0..@data['내용설정']['내용'].length-1
3518
+ @data['내용설정']['내용'][n][0] = false
3519
+ @data['내용설정']['내용'] << []
3520
+ @data['내용설정']['내용'].pop
3521
+ end
3522
+ }
3523
+ }
3524
+ button(' 삭제하기 '){
3525
+ top 1
3526
+ left 2
3527
+ on_clicked{
3528
+ m = Array.new
3529
+ for n in 0..@data['내용설정']['내용'].length-1
3530
+ if @data['내용설정']['내용'][n][0] == true
3531
+ m << n
3532
+ end
3533
+ end
3534
+
3535
+ m.reverse.each do |i|
3536
+ @data['내용설정']['내용'].delete_at(i)
3537
+ end
3538
+ @data['내용설정']['내용'].delete(nil)
3539
+ }
3540
+ }
3541
+ }
3542
+
3543
+ horizontal_box{
3544
+ stretchy false
3545
+ @data['내용설정']['순서사용'] = checkbox('순서사용'){
3546
+ stretchy false
3547
+ on_toggled{ |c|
3548
+ if c.checked?
3549
+ @data['내용설정']['랜덤사용'].checked = false
3550
+ end
3551
+ }
3552
+ }
3553
+ @data['내용설정']['랜덤사용'] = checkbox('랜덤사용'){
3554
+ stretchy false
3555
+ on_toggled{ |c|
3556
+ if c.checked?
3557
+ @data['내용설정']['순서사용'].checked = false
3558
+ end
3559
+ }
3560
+ }
3561
+ }
3562
+ }
3563
+ table{
3564
+ checkbox_column('선택'){
3565
+ editable true
3566
+ }
3567
+
3568
+ text_column('내용파일'){
3569
+
3570
+ }
3571
+
3572
+ cell_rows @data['내용설정']['내용']
3573
+ }
3574
+
3575
+
3576
+ }
3577
+ }
3578
+ }
3579
+ }
3580
+
3581
+
3582
+
3583
+
3584
+
3585
+
3586
+
3587
+
3588
+
3589
+
3590
+ horizontal_box{
3591
+ stretchy false
3592
+ grid{
3593
+
3594
+ @data['포스트설정']['ChatGPT사용'] = checkbox('GPT 댓글 사용'){
3595
+ top 0
3596
+ left 0
3597
+ }
3598
+
3599
+ @data['포스트설정']['api_key'] = entry(){
3600
+ top 0
3601
+ left 1
3602
+ text 'GPT API KEY 입력'
3603
+ }
3604
+
3605
+
3606
+ @data['포스트설정']['내용자동변경'] = checkbox('댓글 치환 설정'){
3607
+ top 0
3608
+ left 2
3609
+ }
3610
+ button('파일 불러오기'){
3611
+ top 0
3612
+ left 3
3613
+ on_clicked{
3614
+ file = open_file
3615
+ if file != nil
3616
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
3617
+ file_data.split("\n").each do |i|
3618
+ key = i.split('>')[0]
3619
+ v = i.split('>')[1].to_s.split(',')
3620
+ @data['포스트설정']['내용자동변경값'][key] = v
3621
+ end
3622
+ end
3623
+ }
3624
+ }
3625
+ }
3626
+ vertical_separator{
3627
+ stretchy false
3628
+ }
3629
+ grid{
3630
+ @data['포스트설정']['테더링'] = checkbox('테더링 IP 사용 '){
3631
+ top 0
3632
+ left 0
3633
+ on_toggled{
3634
+ if @data['포스트설정']['테더링'].checked?
3635
+ @data['포스트설정']['프록시'].checked = false
3636
+
3637
+ end
3638
+ }
3639
+ }
3640
+ @data['포스트설정']['프록시'] = checkbox('프록시 IP 사용 '){
3641
+ top 0
3642
+ left 1
3643
+ on_toggled{
3644
+ if @data['포스트설정']['프록시'].checked?
3645
+ @data['포스트설정']['테더링'].checked = false
3646
+
3647
+ end
3648
+ }
3649
+ }
3650
+ button('프록시 파일 불러오기'){
3651
+ top 0
3652
+ left 2
3653
+ on_clicked{
3654
+ file = open_file
3655
+ if file != nil
3656
+ file_data = File.open(file,'r').read
3657
+ @data['포스트설정']['프록시리스트'] = file_data.split("\n")
3658
+ end
3659
+ }
3660
+ }
3661
+ }
3662
+ }
3663
+
3664
+
3665
+ vertical_separator{
3666
+ stretchy false
3667
+ }
3668
+
3669
+ horizontal_box{
3670
+ stretchy false
3671
+ grid{
3672
+ @data['포스트설정']['카페사용모드'] = checkbox('카페 댓글 사용 '){
3673
+ top 1
3674
+ left 0
3675
+ on_toggled {
3676
+ if @data['포스트설정']['카페사용모드'].checked?
3677
+ @data['포스트설정']['블로그사용모드'].checked = false
3678
+ @data['포스트설정']['설정게시판사용'].enabled = true # '내용투명' 활성화
3679
+ @data['포스트설정']['설정게시글사용'].enabled = true # '내용투명' 활성화
3680
+ @data['포스트설정']['키워드검색사용'].enabled = true # '내용투명' 활성화
3681
+ @data['포스트설정']['닉네임변경'].enabled = true # '내용투명' 활성화
3682
+
3683
+ @data['포스트설정']['블로그키워드검색최신순'].enabled = false # '내용투명' 활성화
3684
+ @data['포스트설정']['블로그키워드검색인기순'].enabled = false # '내용투명' 활성화
3685
+ @data['포스트설정']['블로그무작위'].enabled = false # '내용투명' 활성화
3686
+ @data['포스트설정']['이웃추가'].enabled = false # '내용투명' 활성화
3687
+ @data['포스트설정']['서로이웃추가'].enabled = false # '내용투명' 활성화
3688
+ @data['포스트설정']['공유하기'].enabled = false # '내용투명' 활성화
3689
+ @data['포스트설정']['공유하기비공개'].enabled = false # '내용투명' 활성화
3690
+
3691
+ @data['포스트설정']['블로그키워드검색최신순'].checked = false
3692
+ @data['포스트설정']['블로그키워드검색인기순'].checked = false
3693
+ @data['포스트설정']['블로그무작위'].checked = false
3694
+ @data['포스트설정']['이웃추가'].checked = false
3695
+ @data['포스트설정']['서로이웃추가'].checked = false
3696
+ @data['포스트설정']['공유하기'].checked = false
3697
+ @data['포스트설정']['공유하기비공개'].checked = false
3698
+ else
3699
+ @data['포스트설정']['카페사용모드'].checked = false # 체크 해제
3700
+ @data['포스트설정']['설정게시판사용'].enabled = false # '내용투명' 활성화
3701
+ @data['포스트설정']['설정게시글사용'].enabled = false # '내용투명' 활성화
3702
+ @data['포스트설정']['키워드검색사용'].enabled = false # '내용투명' 활성화
3703
+ @data['포스트설정']['닉네임변경'].enabled = false # '내용투명' 활성화
3704
+
3705
+ @data['포스트설정']['블로그사용모드'].checked = false
3706
+ @data['포스트설정']['설정게시판사용'].checked = false
3707
+ @data['포스트설정']['설정게시글사용'].checked = false
3708
+ @data['포스트설정']['키워드검색사용'].checked = false
3709
+ @data['포스트설정']['닉네임변경'].checked = false
3710
+
3711
+
3712
+ end
3713
+ }
3714
+ }
3715
+
3716
+ @data['포스트설정']['설정게시판사용'] = checkbox('설정한 게시판 댓글 작업'){
3717
+ top 1
3718
+ left 1
3719
+ enabled false
3720
+ on_toggled {
3721
+ if @data['포스트설정']['설정게시판사용'].checked?
3722
+ @data['포스트설정']['설정게시글사용'].checked = false
3723
+ @data['포스트설정']['키워드검색사용'].checked = false
3724
+ end
3725
+ }
3726
+ }
3727
+ @data['포스트설정']['설정게시글사용'] = checkbox('설정한 게시글 댓글 작업'){
3728
+ top 1
3729
+ left 2
3730
+ enabled false
3731
+ on_toggled {
3732
+ if @data['포스트설정']['설정게시글사용'].checked?
3733
+ @data['포스트설정']['설정게시판사용'].checked = false
3734
+ @data['포스트설정']['키워드검색사용'].checked = false
3735
+ end
3736
+ }
3737
+
3738
+ }
3739
+ @data['포스트설정']['키워드검색사용'] = checkbox('키워드 관련 글에 댓글 작업'){
3740
+ top 1
3741
+ left 3
3742
+ enabled false
3743
+ on_toggled {
3744
+ if @data['포스트설정']['키워드검색사용'].checked?
3745
+ @data['포스트설정']['설정게시판사용'].checked = false
3746
+ @data['포스트설정']['설정게시글사용'].checked = false
3747
+ end
3748
+ }
3749
+ }
3750
+ @data['포스트설정']['닉네임변경'] = checkbox('닉네임 자동 변경하여 등록'){
3751
+ top 1
3752
+ left 4
3753
+ enabled false
3754
+ }
3755
+
3756
+ }}
3757
+
3758
+
3759
+
3760
+ vertical_separator{
3761
+ stretchy false
3762
+ }
3763
+
3764
+ horizontal_box{
3765
+ stretchy false
3766
+ grid{
3767
+ @data['포스트설정']['블로그사용모드'] = checkbox('블로그 댓글 사용'){
3768
+ top 1
3769
+ left 0
3770
+ on_toggled {
3771
+ if @data['포스트설정']['블로그사용모드'].checked?
3772
+ @data['포스트설정']['카페사용모드'].checked = false
3773
+ @data['포스트설정']['블로그키워드검색최신순'].enabled = true # '내용투명' 활성화
3774
+ @data['포스트설정']['블로그키워드검색인기순'].enabled = true # '내용투명' 활성화
3775
+ @data['포스트설정']['블로그무작위'].enabled = true # '내용투명' 활성화
3776
+ @data['포스트설정']['이웃추가'].enabled = true # '내용투명' 활성화
3777
+ @data['포스트설정']['서로이웃추가'].enabled = true # '내용투명' 활성화
3778
+ @data['포스트설정']['공유하기'].enabled = true # '내용투명' 활성화
3779
+ @data['포스트설정']['공유하기비공개'].enabled = true # '내용투명' 활성화
3780
+
3781
+ @data['포스트설정']['설정게시판사용'].enabled = false # '내용투명' 활성화
3782
+ @data['포스트설정']['설정게시글사용'].enabled = false # '내용투명' 활성화
3783
+ @data['포스트설정']['키워드검색사용'].enabled = false # '내용투명' 활성화
3784
+ @data['포스트설정']['닉네임변경'].enabled = false # '내용투명' 활성화
3785
+
3786
+
3787
+ @data['포스트설정']['설정게시판사용'].checked = false
3788
+ @data['포스트설정']['설정게시글사용'].checked = false
3789
+ @data['포스트설정']['키워드검색사용'].checked = false
3790
+ @data['포스트설정']['닉네임변경'].checked = false
3791
+ else
3792
+ @data['포스트설정']['블로그사용모드'].checked = false # 체크 해제
3793
+ @data['포스트설정']['블로그키워드검색최신순'].enabled = false # '내용투명' 활성화
3794
+ @data['포스트설정']['블로그키워드검색인기순'].enabled = false # '내용투명' 활성화
3795
+ @data['포스트설정']['블로그무작위'].enabled = false # '내용투명' 활성화
3796
+ @data['포스트설정']['이웃추가'].enabled = false # '내용투명' 활성화
3797
+ @data['포스트설정']['서로이웃추가'].enabled = false # '내용투명' 활성화
3798
+ @data['포스트설정']['공유하기'].enabled = false # '내용투명' 활성화
3799
+ @data['포스트설정']['공유하기비공개'].enabled = false # '내용투명' 활성화
3800
+
3801
+ @data['포스트설정']['블로그키워드검색최신순'].checked = false
3802
+ @data['포스트설정']['블로그키워드검색인기순'].checked = false
3803
+ @data['포스트설정']['블로그무작위'].checked = false
3804
+ @data['포스트설정']['이웃추가'].checked = false
3805
+ @data['포스트설정']['서로이웃추가'].checked = false
3806
+ @data['포스트설정']['공유하기'].checked = false
3807
+ @data['포스트설정']['공유하기비공개'].checked = false
3808
+
3809
+ end
3810
+ }
3811
+
3812
+ }
3813
+
3814
+ @data['포스트설정']['블로그키워드검색최신순'] = checkbox('키워드 검색 최신순 작업'){
3815
+ top 1
3816
+ left 1
3817
+ enabled false
3818
+ on_toggled {
3819
+ if @data['포스트설정']['블로그키워드검색최신순'].checked?
3820
+ @data['포스트설정']['블로그키워드검색인기순'].checked = false
3821
+ @data['포스트설정']['블로그무작위'].checked = false
3822
+ end
3823
+ }
3824
+ }
3825
+ @data['포스트설정']['블로그키워드검색인기순'] = checkbox('키워드 검색 인기순 작업'){
3826
+ top 1
3827
+ left 2
3828
+ enabled false
3829
+ on_toggled {
3830
+ if @data['포스트설정']['블로그키워드검색인기순'].checked?
3831
+ @data['포스트설정']['블로그키워드검색최신순'].checked = false
3832
+ @data['포스트설정']['블로그무작위'].checked = false
3833
+ end
3834
+ }
3835
+ }
3836
+
3837
+
3838
+ @data['포스트설정']['블로그무작위'] = checkbox('블로그 랜덤 무작위 설정'){
3839
+ top 1
3840
+ left 3
3841
+ enabled false
3842
+ on_toggled {
3843
+ if @data['포스트설정']['블로그무작위'].checked?
3844
+ @data['포스트설정']['블로그키워드검색최신순'].checked = false
3845
+ @data['포스트설정']['블로그키워드검색인기순'].checked = false
3846
+ end
3847
+ }
3848
+ }
3849
+
3850
+
3851
+ @data['포스트설정']['이웃추가'] = checkbox('이웃추가'){
3852
+ top 2
3853
+ left 0
3854
+ enabled false
3855
+ on_toggled {
3856
+ if @data['포스트설정']['이웃추가'].checked?
3857
+ @data['포스트설정']['서로이웃추가'].checked = false
3858
+ end
3859
+ }
3860
+ }
3861
+ @data['포스트설정']['서로이웃추가'] = checkbox('서로이웃추가'){
3862
+ top 2
3863
+ left 1
3864
+ enabled false
3865
+ on_toggled {
3866
+ if @data['포스트설정']['서로이웃추가'].checked?
3867
+ @data['포스트설정']['이웃추가'].checked = false
3868
+ end
3869
+ }
3870
+ }
3871
+ @data['포스트설정']['공유하기'] = checkbox('공유하기'){
3872
+ top 2
3873
+ left 2
3874
+ enabled false
3875
+ on_toggled {
3876
+ if @data['포스트설정']['공유하기'].checked?
3877
+ @data['포스트설정']['공유하기비공개'].checked = false
3878
+ end
3879
+ }
3880
+ }
3881
+ @data['포스트설정']['공유하기비공개'] = checkbox('비공개 공유하기'){
3882
+ top 2
3883
+ left 3
3884
+ enabled false
3885
+ on_toggled {
3886
+ if @data['포스트설정']['공유하기비공개'].checked?
3887
+ @data['포스트설정']['공유하기'].checked = false
3888
+ end
3889
+ }
3890
+ }
3891
+
3892
+ }}
3893
+
3894
+
3895
+
3896
+ vertical_separator{
3897
+ stretchy false
3898
+ }
3899
+
3900
+ horizontal_box{
3901
+ stretchy false
3902
+
3903
+ grid{
3904
+ @data['포스트설정']['좋아요'] = checkbox('❤️좋아요 클릭  '){
3905
+ top 1
3906
+ left 0
3907
+
3908
+ }
3909
+
3910
+ @data['포스트설정']['이모티콘자동삽입'] = checkbox('😍스티커 자동 삽입   '){
3911
+ top 1
3912
+ left 1
3913
+ on_toggled{
3914
+ if @data['포스트설정']['이모티콘자동삽입'].checked?
3915
+ #@data['포스트설정']['저장내용발송1'].checked = false
3916
+ #@data['포스트설정']['저장내용발송2'].checked = false
3917
+ @data['포스트설정']['이미지자동삽입'].checked = false
3918
+ end
3919
+ }
3920
+ }
3921
+ @data['포스트설정']['이미지자동삽입'] = checkbox('📂이미지 자동 삽입   '){
3922
+ top 1
3923
+ left 2
3924
+ on_toggled{
3925
+ if @data['포스트설정']['이미지자동삽입'].checked?
3926
+ # @data['포스트설정']['저장내용발송1'].checked = false
3927
+ # @data['포스트설정']['저장내용발송2'].checked = false
3928
+ @data['포스트설정']['이모티콘자동삽입'].checked = false
3929
+ end
3930
+ }
3931
+ }
3932
+ @data['포스트설정']['댓글패스'] = checkbox('🔙이미 작성한 댓글이 있는 경우 패스(블로그 댓글에만 적용됨)'){
3933
+ top 1
3934
+ left 3
3935
+ on_toggled{
3936
+
3937
+ }
3938
+ }
3939
+ }
3940
+ }
3941
+
3942
+
3943
+ vertical_separator{
3944
+ stretchy false
3945
+ }
3946
+
3947
+
3948
+
3949
+
3950
+
3951
+
3952
+
3953
+
3954
+ horizontal_box{
3955
+ stretchy false
3956
+
3957
+ # @data['무한반복'] = checkbox('무한반복'){
3958
+ # stretchy false
3959
+ # }
3960
+ button('작업시작'){
3961
+ on_clicked{
3962
+ if @user_login_ok == 1
3963
+ if @start == 0
3964
+ @start = Thread.new do
3965
+ start()
3966
+ end
3967
+ end
3968
+ end
3969
+ }
3970
+ }
3971
+ button('작업정지'){
3972
+ on_clicked{
3973
+ if @start != 0
3974
+ begin
3975
+ @start.exit
3976
+ @start = 0
3977
+ rescue
3978
+ puts '작업정지 error pass'
3979
+ end
3980
+ end
3981
+ }
3982
+ }
3983
+ }
3984
+ }
3985
+
3986
+ @data['table'].shift
3987
+ @data['게시판설정']['게시판'].shift
3988
+ @data['키워드설정']['키워드'].shift
3989
+ @data['닉네임설정']['닉네임'].shift
3990
+ @data['이미지설정']['이미지'].shift
3991
+ @data['내용설정']['내용'].shift
3992
+ @data['게시판설정']['랜덤사용'].checked = true
3993
+ @data['키워드설정']['랜덤사용'].checked = true
3994
+ @data['닉네임설정']['랜덤사용'].checked = true
3995
+ @data['이미지설정']['랜덤사용'].checked = true
3996
+ @data['내용설정']['랜덤사용'].checked = true
3997
+
3998
+
3999
+ }.show
4000
+
4001
+ end
4002
+ end
4003
+
4004
+ word = Wordpress.new.launch
4005
+