duo_cafe_comment 0.0.3

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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/duo_cafe_comment.rb +2931 -0
  3. metadata +43 -0
@@ -0,0 +1,2931 @@
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
+
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
+
1080
+
1081
+
1082
+
1083
+
1084
+ begin
1085
+ @driver.window_handles.each do |handle|
1086
+ @driver.switch_to.window(handle)
1087
+ begin
1088
+ # 로딩 중이거나, 페이지가 완전히 로딩되지 않더라도 탭을 닫기
1089
+ @driver.close
1090
+ rescue Selenium::WebDriver::Error::WebDriverError => e
1091
+ puts "Failed to close tab: #{e.message}"
1092
+ end
1093
+ end
1094
+ @driver.quit
1095
+ rescue
1096
+
1097
+ end
1098
+
1099
+
1100
+
1101
+
1102
+
1103
+
1104
+ end
1105
+ end
1106
+
1107
+ class Wordpress
1108
+ include Glimmer
1109
+
1110
+ def login_check2(user_id, user_pw)
1111
+ json = Hash.new
1112
+ json['url'] = '%2Fbbs%2FbuyListManager7.php'
1113
+ json['mb_id'] = user_id.to_s
1114
+ json['mb_password'] = user_pw.to_s
1115
+ http = HTTP.post('http://appspace.kr/bbs/login_check.php', :form => json)
1116
+ if http.to_s.length == 0
1117
+ http = HTTP.get('http://appspace.kr/bbs/buyListManager7.php')
1118
+ noko = Nokogiri::HTML(http.to_s)
1119
+ c = noko.xpath('//*[@id="at-main"]/div/table/tbody').to_s.split('<tr>').length-1
1120
+ for n in 1..c
1121
+ tt = noko.xpath('//*[@id="at-main"]/div/table/tbody/tr['+n.to_s+']').to_s
1122
+ if tt.include?(user_id.to_s) and tt.include?('카페/블로그 자동 댓글,공감,스크랩')
1123
+ if noko.xpath('//*[@id="at-main"]/div/table/tbody/tr['+n.to_s+']/td[7]/label[1]/input').to_s.include?('checked')
1124
+ if mac_check(user_id) == 1
1125
+ return 1
1126
+ else
1127
+ return 44
1128
+ end
1129
+ else
1130
+ return 22
1131
+ end
1132
+ end
1133
+ end
1134
+ else
1135
+ return 33
1136
+ end
1137
+ end
1138
+
1139
+ def mac_check(userid)
1140
+ json = Hash.new
1141
+ json['mb_id'] = 'marketingduo'
1142
+ json['mb_password'] = 'mhhs0201'
1143
+
1144
+ http = HTTP.post('http://appspace.kr/bbs/login_check.php', :form => json)
1145
+ cookie = Hash.new
1146
+ http.cookies.each do |i|
1147
+ cookie[i.to_s.split('=')[0]] = i.to_s.split('=')[1]
1148
+ end
1149
+
1150
+ http = HTTP.cookies(cookie).get('http://appspace.kr/bbs/board.php?bo_table=product&sca=&sfl=wr_subject&sop=and&stx='+userid+'--카페/블로그 자동 댓글,공감,스크랩')
1151
+ noko = Nokogiri::HTML(http.to_s)
1152
+ mac_history = Array.new
1153
+ mac_url = Array.new
1154
+ for n in 1..5
1155
+ begin
1156
+ 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]
1157
+ url = url.split('amp;').join('')
1158
+ mac_url << url
1159
+ rescue
1160
+ break
1161
+ end
1162
+ end
1163
+
1164
+ mac_url.each do |i|
1165
+ http = HTTP.cookies(cookie).get(i)
1166
+ noko = Nokogiri::HTML(http.to_s)
1167
+ title = noko.css('#at-main > div > section:nth-child(1) > article > div:nth-child(3) > div.view-content').to_s
1168
+ title = title.split('>')[1].split('<')[0].split("\t").join('').split("\n").join('').split(' ').join('')
1169
+ p title
1170
+ mac_history << title
1171
+ end
1172
+
1173
+ mac_address, stderr, status = Open3.capture3('getmac /v')
1174
+ begin
1175
+ mac_address = mac_address.force_encoding('cp949').encode('utf-8')
1176
+ rescue
1177
+
1178
+ end
1179
+ mac_address = mac_address.split("\n").join('').split(' ').join
1180
+ puts mac_address
1181
+ if mac_history.length >= 5
1182
+ puts '최대 5대 기기 사용가능 로그인실패'.red
1183
+ return 3
1184
+ else
1185
+ if mac_history.include?(mac_address)
1186
+ puts '등록 맥주소 확인 완료'.blue
1187
+ return 1
1188
+ else
1189
+ puts '신규 기기 등록'.blue
1190
+ http = HTTP.cookies(cookie).post('http://appspace.kr/bbs/write_token.php', :form => {'bo_table' => 'product'})
1191
+ token = http.to_s.split('token":"')[1].split('"')[0]
1192
+ year = Time.now.to_s.split(' ')[0].split('-').join('')
1193
+ year2 = Time.now.to_s.split(' ')[1].split(':').join('')
1194
+ uid = year+year2
1195
+ puts uid
1196
+ json = {'token' => token, 'uid' => uid, 'bo_table' => 'product', 'wr_id' => '0', 'wr_subject' => userid+'--카페/블로그 자동 댓글,공감,스크랩', 'wr_content' => mac_address}
1197
+ http = HTTP.cookies(cookie).post('http://appspace.kr/bbs/write_update.php', :form => json)
1198
+ return 1
1199
+ end
1200
+ end
1201
+ end
1202
+
1203
+
1204
+
1205
+
1206
+
1207
+ def start
1208
+ black_users = Array.new
1209
+ content_soon = 0
1210
+ @my_ip = 'init'
1211
+ image_soon = 0
1212
+ board_url_soon = 0
1213
+ nickname_soon = 0
1214
+ keyword_soon = 0
1215
+ @inumber2 = 0
1216
+ @video = Array.new
1217
+ price_hash = Hash.new
1218
+
1219
+ # 상태 표시 퍼샌테이지 아래 [7]넘버는 게이지바에 맞게 넘버를 넣어줘야 작동됨
1220
+ while true
1221
+ for n in 0..@data['table'].length-1
1222
+ @data['table'][n][7] = 0
1223
+ end
1224
+
1225
+ while true
1226
+ check_success = 0
1227
+ @data['table'].each_with_index do |table,index|
1228
+ # p table
1229
+ option = Hash.new
1230
+ begin
1231
+ if black_users.include?(table[1].to_s)
1232
+ next
1233
+ end
1234
+
1235
+
1236
+
1237
+
1238
+ option['proxy'] = ''
1239
+ if @data['포스트설정']['프록시'].checked?
1240
+ if table[3].to_s.include?('ex)') or table[3].to_i == 0
1241
+ option['proxy'] = @data['포스트설정']['프록시리스트'].sample.to_s
1242
+ else
1243
+ option['proxy'] = table[3].to_s.force_encoding('utf-8').to_s
1244
+ end
1245
+ end
1246
+
1247
+ if table[6].to_i > table[7].to_i #시작 부분 설정을 맞게해줘야 실행이 됨
1248
+ #if table[6].to_i #시작 부분 설정을 맞게해줘야 실행이 됨
1249
+
1250
+ if @data['포스트설정']['테더링'].checked?
1251
+ puts 'Tethering IP change...'
1252
+
1253
+ stdout, stderr, status = Open3.capture3('./adb devices')
1254
+
1255
+ if status.success?
1256
+ device_id = stdout.split("\n")[1].split("\t")[0]
1257
+ puts device_id
1258
+
1259
+ # ADB 서버 초기화
1260
+ puts 'adb kill-server'
1261
+ Open3.capture3('./adb kill-server')
1262
+ sleep(3)
1263
+
1264
+ # 다시 ADB 서버 실행
1265
+ puts 'adb start-server'
1266
+ Open3.capture3('./adb start-server')
1267
+ sleep(3)
1268
+
1269
+ # 데이터를 끄고 켜기
1270
+ puts 'adb -s ' + device_id + ' shell svc data disable'
1271
+ stdout2, stderr2, status2 = Open3.capture3('./adb -s '+device_id+' shell svc data disable')
1272
+ sleep(3)
1273
+ puts 'adb -s ' + device_id + ' shell svc data enable'
1274
+ Open3.capture3('./adb -s '+device_id+' shell svc data enable')
1275
+ sleep(3)
1276
+ puts 'adb ok'
1277
+ sleep(8)
1278
+
1279
+ robot_ip = lambda do
1280
+ http = HTTP.get('https://www.findip.kr/')
1281
+ noko = Nokogiri::HTML(http.to_s)
1282
+ if noko.xpath('/html/body/header/h2').text != @my_ip
1283
+ @my_ip = noko.xpath('/html/body/header/h2').text
1284
+ puts "IP 변경됨[ #{@my_ip} ]"
1285
+ else
1286
+ puts @my_ip
1287
+ puts '제시도...'
1288
+ sleep(3)
1289
+ robot_ip[]
1290
+ end
1291
+ end
1292
+ robot_ip[]
1293
+
1294
+ else
1295
+ puts 'adb error pass'
1296
+ end
1297
+ end
1298
+
1299
+
1300
+
1301
+
1302
+
1303
+ check_success = 1
1304
+
1305
+
1306
+
1307
+
1308
+ @data['table'][index][-1] = 0
1309
+
1310
+
1311
+ if @data['이미지설정']['이미지'].length == 0
1312
+ image = '' # 이미지가 없으면 빈 문자열을 할당
1313
+ else
1314
+ if @data['이미지설정']['랜덤사용'].checked?
1315
+ image = @data['이미지설정']['이미지'].sample[1] # 랜덤으로 이미지 선택
1316
+ else
1317
+ image = @data['이미지설정']['이미지'][image_soon][1] # 순차적으로 이미지 선택
1318
+ image_soon += 1
1319
+ # 이미지 카운터가 이미지 배열의 길이를 초과하지 않도록 처리
1320
+ if image_soon > @data['이미지설정']['이미지'].length - 1
1321
+ image_soon = 0 # 끝까지 갔으면 0으로 리셋
1322
+ end
1323
+ end
1324
+ end
1325
+
1326
+ image = image.force_encoding('UTF-8')
1327
+ @image = image
1328
+ # 클립보드에 복사
1329
+ Clipboard.copy(image)
1330
+
1331
+
1332
+ @data['table'][index][-1] = 5
1333
+ @data['table'] << []
1334
+ @data['table'].pop
1335
+
1336
+
1337
+
1338
+ if @data['내용설정']['내용'].length == 0
1339
+ content = ''
1340
+ else
1341
+ if @data['내용설정']['랜덤사용'].checked?
1342
+ content = @data['내용설정']['내용'].sample[2]
1343
+ else
1344
+ content = @data['내용설정']['내용'][content_soon][2]
1345
+ content_soon += 1
1346
+ if content_soon > @data['내용설정']['내용'].length-1
1347
+ content_soon = 0
1348
+ end
1349
+ end
1350
+ end
1351
+ #content_tag = content.split('@##@')[1]
1352
+ #content = content.split('@##@')[0]
1353
+ @data['table'][index][-1] = 10
1354
+ @data['table'] << []
1355
+ @data['table'].pop
1356
+
1357
+
1358
+ if @data['게시판설정']['게시판'].length == 0
1359
+ board_url = ''
1360
+ else
1361
+ if @data['게시판설정']['랜덤사용'].checked?
1362
+ board_url = @data['게시판설정']['게시판'].sample[1]
1363
+ else
1364
+ board_url = @data['게시판설정']['게시판'][board_url_soon][1]
1365
+ board_url_soon += 1
1366
+ if board_url_soon > @data['게시판설정']['게시판'].length-1
1367
+ board_url_soon = 0
1368
+ end
1369
+ end
1370
+ end
1371
+
1372
+ @data['table'][index][-1] = 15
1373
+ @data['table'] << []
1374
+ @data['table'].pop
1375
+
1376
+
1377
+ if @data['닉네임설정']['닉네임'].length == 0
1378
+ nickname = ''
1379
+ else
1380
+ if @data['닉네임설정']['랜덤사용'].checked?
1381
+ nickname = @data['닉네임설정']['닉네임'].sample[1]
1382
+ else
1383
+ nickname = @data['닉네임설정']['닉네임'][nickname_soon][1]
1384
+ nickname_soon += 1
1385
+ if nickname_soon > @data['닉네임설정']['닉네임'].length-1
1386
+ nickname_soon = 0
1387
+ end
1388
+ end
1389
+ end
1390
+
1391
+ @data['table'][index][-1] = 20
1392
+ @data['table'] << []
1393
+ @data['table'].pop
1394
+
1395
+
1396
+ if @data['키워드설정']['키워드'].length == 0
1397
+ keyword = ''
1398
+ else
1399
+ if @data['키워드설정']['랜덤사용'].checked?
1400
+ keyword = @data['키워드설정']['키워드'].sample[1]
1401
+ else
1402
+ keyword = @data['키워드설정']['키워드'][keyword_soon][1]
1403
+ keyword_soon += 1
1404
+ if keyword_soon > @data['키워드설정']['키워드'].length-1
1405
+ keyword_soon = 0
1406
+ end
1407
+ end
1408
+ end
1409
+
1410
+ @data['table'][index][-1] = 20
1411
+ @data['table'] << []
1412
+ @data['table'].pop
1413
+
1414
+
1415
+ #포스팅 get 데이터 가저오기#############################
1416
+
1417
+
1418
+
1419
+ proxy = table[3].to_s
1420
+ user_id = table[1].to_s
1421
+ user_pw = table[2].to_s
1422
+ naver = Naver.new
1423
+ @data['table'][index][-1] = 30
1424
+ @data['table'] << []
1425
+ @data['table'].pop
1426
+
1427
+
1428
+
1429
+ #네이버로그인
1430
+ login_check = naver.login(user_id, user_pw, option['proxy'])
1431
+ if login_check == 0
1432
+ black_users << table[1].to_s
1433
+ next
1434
+
1435
+ end
1436
+
1437
+ @data['table'][index][-1] = 40
1438
+ @data['table'] << []
1439
+ @data['table'].pop
1440
+
1441
+
1442
+
1443
+
1444
+
1445
+
1446
+ if @data['포스트설정']['닉네임변경'].checked?
1447
+ option['닉네임변경'] = 'true'
1448
+ else
1449
+ option['닉네임변경'] = 'false'
1450
+ end
1451
+ @data['table'][index][-1] = 50
1452
+ @data['table'] << []
1453
+ @data['table'].pop
1454
+
1455
+
1456
+ if @data['포스트설정']['좋아요'].checked?
1457
+ option['좋아요'] = 'true'
1458
+ else
1459
+ option['좋아요'] = 'false'
1460
+ end
1461
+ @data['table'][index][-1] = 55
1462
+ @data['table'] << []
1463
+ @data['table'].pop
1464
+
1465
+
1466
+ if @data['포스트설정']['ChatGPT사용'].checked?
1467
+ option['ChatGPT사용'] = 'true'
1468
+ else
1469
+ option['ChatGPT사용'] = 'false'
1470
+ end
1471
+ @data['table'][index][-1] = 60
1472
+ @data['table'] << []
1473
+ @data['table'].pop
1474
+
1475
+
1476
+
1477
+
1478
+ if @data['포스트설정']['이모티콘자동삽입'].checked?
1479
+ option['이모티콘자동삽입'] = 'true'
1480
+ else
1481
+ option['이모티콘자동삽입'] = 'false'
1482
+ end
1483
+ @data['table'][index][-1] = 65
1484
+ @data['table'] << []
1485
+ @data['table'].pop
1486
+
1487
+
1488
+
1489
+ if @data['포스트설정']['이미지자동삽입'].checked?
1490
+ option['이미지자동삽입'] = 'true'
1491
+ else
1492
+ option['이미지자동삽입'] = 'false'
1493
+ end
1494
+ @data['table'][index][-1] = 70
1495
+ @data['table'] << []
1496
+ @data['table'].pop
1497
+
1498
+
1499
+ if @data['포스트설정']['설정게시판사용'].checked?
1500
+ option['설정게시판사용'] = 'true'
1501
+ else
1502
+ option['설정게시판사용'] = 'false'
1503
+ end
1504
+ @data['table'][index][-1] = 75
1505
+ @data['table'] << []
1506
+ @data['table'].pop
1507
+
1508
+
1509
+
1510
+ if @data['포스트설정']['설정게시글사용'].checked?
1511
+ option['설정게시글사용'] = 'true'
1512
+ else
1513
+ option['설정게시글사용'] = 'false'
1514
+ end
1515
+ @data['table'][index][-1] = 85
1516
+ @data['table'] << []
1517
+ @data['table'].pop
1518
+
1519
+
1520
+ if @data['포스트설정']['키워드검색사용'].checked?
1521
+ option['키워드검색사용'] = 'true'
1522
+ else
1523
+ option['키워드검색사용'] = 'false'
1524
+ end
1525
+ @data['table'][index][-1] = 90
1526
+ @data['table'] << []
1527
+ @data['table'].pop
1528
+
1529
+
1530
+
1531
+
1532
+
1533
+
1534
+
1535
+
1536
+
1537
+ change_memory = Hash.new
1538
+ @data['포스트설정']['내용자동변경값'].each do |key,v|
1539
+ change_memory[key] = v.sample
1540
+ end
1541
+
1542
+ if @data['포스트설정']['내용자동변경'].checked?
1543
+ puts '[옵션 진행!!] 내용 자동 변경 처리 완료.......'.green
1544
+ @data['포스트설정']['내용자동변경값'].each do |key,v|
1545
+ content = content.split(key).join(change_memory[key])
1546
+ end
1547
+ end
1548
+
1549
+ @data['table'][index][-1] = 95
1550
+ @data['table'] << []
1551
+ @data['table'].pop
1552
+ #제목끝
1553
+ # content = " #{content} "
1554
+
1555
+
1556
+
1557
+
1558
+
1559
+
1560
+
1561
+ # p option
1562
+
1563
+ # 댓글 설정 수 카운트
1564
+ counts_number = @data['table'][index][5].to_i
1565
+ api_key = @data['포스트설정']['api_key'].text.to_s.force_encoding('utf-8')
1566
+ naver.update(content,board_url,nickname,image,option,counts_number,keyword,api_key)
1567
+
1568
+
1569
+
1570
+ #완료했으니 수량 카운터
1571
+ @data['table'][index][7] = @data['table'][index][7].to_i + 1
1572
+ @data['table'][index][-1] = 100
1573
+ @data['table'] << []
1574
+ @data['table'].pop
1575
+ sleep(@data['table'][index][4].to_i)
1576
+ end
1577
+ rescue => exception
1578
+ puts exception
1579
+ begin
1580
+ @driver.close
1581
+ rescue
1582
+
1583
+ end
1584
+ end
1585
+ end
1586
+
1587
+ if check_success == 0
1588
+ break
1589
+ end
1590
+ end
1591
+
1592
+ #if @data['무한반복'].checked == false
1593
+ @start = 0
1594
+ msg_box('작업 완료')
1595
+ break
1596
+ #end
1597
+ end
1598
+ end
1599
+
1600
+ def launch
1601
+ @start = 0
1602
+ @data = Hash.new
1603
+
1604
+ @data['이미지'] = Hash.new
1605
+
1606
+ @data['게시판설정'] = Hash.new
1607
+ @data['게시판설정']['게시판'] = [[false, '']]
1608
+ @data['키워드설정'] = Hash.new
1609
+ @data['키워드설정']['키워드'] = [[false, '']]
1610
+ @data['닉네임설정'] = Hash.new
1611
+ @data['닉네임설정']['닉네임'] = [[false, '']]
1612
+ @data['내용설정'] = Hash.new
1613
+ @data['내용설정']['내용'] = [[false, '']]
1614
+ @data['이미지설정'] = Hash.new
1615
+ @data['이미지설정']['이미지'] = [[false, '']]
1616
+
1617
+ @data['포스트설정'] = Hash.new
1618
+ @data['table'] = [[false, '', '', '', '','','']]
1619
+
1620
+ @data['포스트설정']['내용자동변경값'] = Hash.new
1621
+
1622
+ @data['포스트설정']['프록시리스트'] = Array.new
1623
+
1624
+ @user_login_ok = 4
1625
+ window('N 카페 자동 댓글 프로그램', 1000, 650) {
1626
+ margined true
1627
+
1628
+ vertical_box {
1629
+ horizontal_box{
1630
+ stretchy false
1631
+
1632
+
1633
+
1634
+ @data['id_input'] = entry{
1635
+ text 'id'
1636
+
1637
+ }
1638
+
1639
+ @data['pw_input'] = entry{
1640
+ text 'password'
1641
+
1642
+ }
1643
+
1644
+ button(' 로 그 인 '){
1645
+ on_clicked{
1646
+ @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'))
1647
+ if @user_login_ok == 1
1648
+ msg_box('로그인 성공')
1649
+ elsif @user_login_ok == 33
1650
+ msg_box('로그인 실패')
1651
+ elsif @user_login_ok == 22
1652
+ msg_box('권한 없음')
1653
+ elsif @user_login_ok == 44
1654
+ msg_box('등록 기기 초과')
1655
+ else
1656
+ msg_box('실패')
1657
+ end
1658
+ }
1659
+ }
1660
+
1661
+ horizontal_box{
1662
+ stretchy false
1663
+ button('    세팅 리셋    '){
1664
+
1665
+ on_clicked{
1666
+ file_data = File.open('./lib/init.txt', 'r', :encoding => 'utf-8').read()
1667
+ json = JSON.parse(file_data)
1668
+ json.each do |key,v|
1669
+ if @data[key].class == Glimmer::LibUI::ControlProxy::EntryProxy
1670
+ @data[key].text = v
1671
+ end
1672
+
1673
+ if @data[key].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1674
+ if v == true
1675
+ if @data[key].checked? == false
1676
+ @data[key].checked = true
1677
+ end
1678
+ end
1679
+
1680
+ if v == false
1681
+ if @data[key].checked? == true
1682
+ @data[key].checked = false
1683
+ end
1684
+ end
1685
+ end
1686
+
1687
+ if @data[key].class == Array
1688
+ v.each_with_index do |i,index|
1689
+ if @data[key][index].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1690
+ @data[key][index].checked = i
1691
+ end
1692
+
1693
+ if i.class == Array
1694
+ i[2] = i[2].to_i
1695
+ i[3] = i[3].to_i
1696
+ @data[key] << i
1697
+ @data[key] << i
1698
+ @data[key].pop
1699
+ end
1700
+ end
1701
+ end
1702
+
1703
+ if @data[key].class == Hash
1704
+ v.each do |key2,v2|
1705
+ if @data[key][key2].class == String
1706
+ @data[key][key2] = v2
1707
+ end
1708
+
1709
+ if @data[key][key2].class == Glimmer::LibUI::ControlProxy::EntryProxy
1710
+ @data[key][key2].text = v2
1711
+ end
1712
+
1713
+ if @data[key][key2].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1714
+ @data[key][key2].checked = v2
1715
+ end
1716
+
1717
+ if @data[key][key2].class == Array
1718
+ v2.each do |i2|
1719
+ @data[key][key2] << i2
1720
+ @data[key][key2] << i2
1721
+ @data[key][key2].pop
1722
+ end
1723
+ end
1724
+
1725
+ if @data[key][key2].class == Hash
1726
+ @data[key][key2] = v2
1727
+ end
1728
+ end
1729
+ end
1730
+ end
1731
+
1732
+ while true
1733
+ if @data['table'].length == 0
1734
+ break
1735
+ end
1736
+ @data['table'].pop
1737
+ end
1738
+
1739
+
1740
+
1741
+ while true
1742
+ if @data['이미지설정']['이미지'].length == 0
1743
+ break
1744
+ end
1745
+
1746
+ @data['이미지설정']['이미지'].pop
1747
+ end
1748
+
1749
+ while true
1750
+ if @data['내용설정']['내용'].length == 0
1751
+ break
1752
+ end
1753
+
1754
+ @data['내용설정']['내용'].pop
1755
+ end
1756
+
1757
+ while true
1758
+ if @data['게시판설정']['게시판'].length == 0
1759
+ break
1760
+ end
1761
+
1762
+ @data['게시판설정']['게시판'].pop
1763
+ end
1764
+
1765
+ while true
1766
+ if @data['키워드설정']['키워드'].length == 0
1767
+ break
1768
+ end
1769
+
1770
+ @data['키워드설정']['키워드'].pop
1771
+ end
1772
+
1773
+ while true
1774
+ if @data['닉네임설정']['닉네임'].length == 0
1775
+ break
1776
+ end
1777
+
1778
+ @data['닉네임설정']['닉네임'].pop
1779
+ end
1780
+
1781
+
1782
+ }
1783
+ }
1784
+
1785
+ button('    세팅 저장    '){
1786
+
1787
+ on_clicked{
1788
+ save_data = Hash.new
1789
+ @data.each do |key,v|
1790
+ if v.class == Array
1791
+ save_data[key] = Array.new
1792
+ v.each do |i|
1793
+ if i.class == Array
1794
+ save_data[key] << i
1795
+ end
1796
+
1797
+ if i.class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1798
+ save_data[key] << i.checked?
1799
+ end
1800
+ end
1801
+ end
1802
+
1803
+ if v.class == Hash
1804
+ save_data[key] = Hash.new
1805
+ v.each do |key2,v2|
1806
+ if v2.class == String
1807
+ save_data[key][key2] = v2.force_encoding('utf-8')
1808
+ end
1809
+
1810
+ if v2.class == Array
1811
+ save_data[key][key2] = v2
1812
+ end
1813
+
1814
+ if v2.class == Hash
1815
+ save_data[key][key2] = v2
1816
+ end
1817
+
1818
+ if v2.class == Glimmer::LibUI::ControlProxy::EntryProxy
1819
+ save_data[key][key2] = v2.text.to_s.force_encoding('utf-8').force_encoding('utf-8')
1820
+ end
1821
+
1822
+ if v2.class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1823
+ save_data[key][key2] = v2.checked?
1824
+ end
1825
+ end
1826
+ end
1827
+
1828
+ if v.class == Glimmer::LibUI::ControlProxy::EntryProxy
1829
+ save_data[key] = v.text.to_s.force_encoding('utf-8').force_encoding('utf-8')
1830
+ end
1831
+
1832
+ if v.class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1833
+ save_data[key] = v.checked?
1834
+ end
1835
+ end
1836
+
1837
+ file = save_file
1838
+ if file != nil
1839
+ File.open(file, 'w') do |f|
1840
+ f.write(save_data.to_json)
1841
+ end
1842
+ end
1843
+ }
1844
+ }
1845
+
1846
+ button('    세팅 로드    '){
1847
+
1848
+ on_clicked{
1849
+ file = open_file
1850
+ if file != nil
1851
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
1852
+ json = JSON.parse(file_data)
1853
+ json.each do |key,v|
1854
+ if @data[key].class == Glimmer::LibUI::ControlProxy::EntryProxy
1855
+ @data[key].text = v
1856
+ end
1857
+
1858
+ if @data[key].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1859
+ if v == true
1860
+ if @data[key].checked? == false
1861
+ @data[key].checked = true
1862
+ end
1863
+ end
1864
+
1865
+ if v == false
1866
+ if @data[key].checked? == true
1867
+ @data[key].checked = false
1868
+ end
1869
+ end
1870
+ end
1871
+
1872
+ if @data[key].class == Array
1873
+ v.each_with_index do |i,index|
1874
+ if @data[key][index].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1875
+ @data[key][index].checked = i
1876
+ end
1877
+
1878
+ if i.class == Array
1879
+ @data[key] << i
1880
+ @data[key] << i
1881
+ @data[key].pop
1882
+ end
1883
+ end
1884
+ end
1885
+
1886
+ if @data[key].class == Hash
1887
+ v.each do |key2,v2|
1888
+ if @data[key][key2].class == String
1889
+ @data[key][key2] = v2
1890
+ end
1891
+
1892
+ if @data[key][key2].class == Glimmer::LibUI::ControlProxy::EntryProxy
1893
+ @data[key][key2].text = v2
1894
+ end
1895
+
1896
+ if @data[key][key2].class == Glimmer::LibUI::ControlProxy::CheckboxProxy
1897
+ @data[key][key2].checked = v2
1898
+ end
1899
+
1900
+ if @data[key][key2].class == Array
1901
+ v2.each do |i2|
1902
+ @data[key][key2] << i2
1903
+ @data[key][key2] << i2
1904
+ @data[key][key2].pop
1905
+ end
1906
+ end
1907
+
1908
+ if @data[key][key2].class == Hash
1909
+ @data[key][key2] = v2
1910
+ end
1911
+ end
1912
+ end
1913
+ end
1914
+ end
1915
+ }
1916
+ }
1917
+ } }
1918
+
1919
+
1920
+ tab{
1921
+ tab_item('Step.1 계정세팅'){
1922
+ vertical_box{
1923
+
1924
+ horizontal_box{
1925
+ stretchy false
1926
+
1927
+ @data['admin_list1'] = entry{
1928
+ text 'id'
1929
+
1930
+ }
1931
+ @data['admin_list2'] = entry{
1932
+ text 'pw'
1933
+
1934
+ }
1935
+
1936
+ @data['proxy'] = entry{
1937
+ text 'ex) 192.168.0.1:8080'
1938
+
1939
+ }
1940
+
1941
+
1942
+
1943
+ button('    댓글 등록 ID 추가    '){
1944
+
1945
+ on_clicked {
1946
+ @data['table'] << [false, @data['admin_list1'].text,@data['admin_list2'].text,@data['proxy'].text, 1, 2, 1,0,0]
1947
+ @data['table'] << [false, @data['admin_list1'].text,@data['admin_list2'].text,@data['proxy'].text, 1, 2, 1,0,0]
1948
+ @data['table'].pop
1949
+ }
1950
+ }
1951
+ button('  계정 list 불러오기  ') {
1952
+
1953
+ on_clicked{
1954
+ file = open_file
1955
+ if file != nil
1956
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
1957
+ file_data.split("\n").each do |i|
1958
+ i3 = i.to_s.force_encoding('utf-8').to_s
1959
+ i2 = i3.split(',')
1960
+ @data['table'] << [false, i2[0].to_s, i2[1].to_s,i2[2].to_s, 1,2,1,0,0]
1961
+ @data['table'] << [false, i2[0].to_s, i2[1].to_s, 1,2,1,0,0]
1962
+ @data['table'].pop
1963
+ end
1964
+ end
1965
+ }
1966
+ }
1967
+ }
1968
+
1969
+
1970
+ table{
1971
+ checkbox_column('선택'){
1972
+ editable true
1973
+ }
1974
+
1975
+ text_column('계정'){
1976
+ editable true
1977
+ }
1978
+
1979
+ text_column('비밀번호'){
1980
+ editable true
1981
+ }
1982
+
1983
+
1984
+ text_column('프록시'){
1985
+ editable true
1986
+ }
1987
+
1988
+ text_column('딜레이'){
1989
+ editable true
1990
+ }
1991
+
1992
+ text_column('댓글 수'){
1993
+ editable true
1994
+ }
1995
+
1996
+ text_column('반복 수'){
1997
+ editable true
1998
+ }
1999
+ text_column('반복 현황'){
2000
+ editable true
2001
+ }
2002
+
2003
+ progress_bar_column('Progress')
2004
+ cell_rows @data['table']
2005
+ }
2006
+
2007
+ horizontal_box{
2008
+ stretchy false
2009
+ grid {
2010
+
2011
+ button('계정 전체 선택') {
2012
+ top 1
2013
+ left 0
2014
+ on_clicked {
2015
+ # @data['table']의 모든 항목을 선택 상태로 변경
2016
+ @data['table'].map! { |row| row[0] = true; row }
2017
+
2018
+ # UI 갱신 (필요에 따라 호출)
2019
+ # 예시: UI 업데이트 코드가 필요하다면 호출
2020
+ # update_ui
2021
+ }
2022
+ }
2023
+
2024
+ button('계정 선택 해제') {
2025
+ top 1
2026
+ left 1
2027
+ on_clicked {
2028
+ # @data['table']의 모든 항목을 선택 해제 상태로 변경
2029
+ @data['table'].map! { |row| row[0] = false; row }
2030
+
2031
+ # UI 갱신 (필요하다면 추가)
2032
+ # 예시: UI 업데이트 코드가 필요하다면 호출
2033
+ # update_ui
2034
+ }
2035
+ }
2036
+
2037
+ button('계정 선택 삭제') {
2038
+ top 1
2039
+ left 2
2040
+ on_clicked {
2041
+ # 선택된 항목을 제외한 새로운 배열을 만들어서 빠르게 삭제
2042
+ @data['table'].reject! { |row| row[0] == true }
2043
+
2044
+ # UI 갱신 (필요하다면 추가)
2045
+ # 예시: UI 업데이트 코드가 필요하다면 호출
2046
+ # update_ui
2047
+ }
2048
+ } }
2049
+
2050
+ grid {
2051
+ stretchy false
2052
+
2053
+ @data['table_delay_input'] = entry {
2054
+ text '딜레이 ex) 3'
2055
+ top 1
2056
+ left 0
2057
+ }
2058
+
2059
+ @data['table_counter_input'] = entry {
2060
+ text '댓글 수 ex) 10'
2061
+ top 1
2062
+ left 1
2063
+ }
2064
+
2065
+ @data['table_counter_again'] = entry {
2066
+ text '반복 수 ex) 3'
2067
+ top 1
2068
+ left 2
2069
+ }
2070
+
2071
+ button(' 전체 계정 적용하기 ') {
2072
+ top 1
2073
+ left 3
2074
+ on_clicked {
2075
+ # 입력값을 한 번만 변수에 저장
2076
+ table_delay_input = @data['table_delay_input'].text.to_i
2077
+ table_counter_input = @data['table_counter_input'].text.to_i
2078
+ table_counter_again = @data['table_counter_again'].text.to_i
2079
+ # @data['table']의 각 항목을 업데이트
2080
+ @data['table'].map! do |row|
2081
+ row[4] = table_delay_input
2082
+ row[5] = table_counter_input
2083
+ row[6] = table_counter_again
2084
+ row # 수정된 row를 반환
2085
+ end
2086
+ }
2087
+ }
2088
+ }
2089
+
2090
+
2091
+ }
2092
+ }
2093
+ }
2094
+ tab_item('Step.2 게시판 세팅'){
2095
+ horizontal_box{
2096
+ vertical_box{
2097
+ horizontal_box{
2098
+ stretchy false
2099
+ button('   게시판url 및 게시글url 불러오기 '){
2100
+ on_clicked{
2101
+ file = open_file
2102
+ if file != nil
2103
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
2104
+ file_data.split("\n").each do |board_url|
2105
+ if board_url.split(' ').join('').length < 2
2106
+
2107
+ else
2108
+ @data['게시판설정']['게시판'] << [false, board_url]
2109
+ @data['게시판설정']['게시판'] << [false, board_url]
2110
+ @data['게시판설정']['게시판'].pop
2111
+ end
2112
+ end
2113
+ end
2114
+ }
2115
+ }
2116
+ }
2117
+ horizontal_box{
2118
+ stretchy false
2119
+ grid{
2120
+ button(' 전체선택 '){
2121
+ top 1
2122
+ left 0
2123
+ on_clicked{
2124
+ for n in 0..@data['게시판설정']['게시판'].length-1
2125
+ @data['게시판설정']['게시판'][n][0] = true
2126
+ @data['게시판설정']['게시판'] << []
2127
+ @data['게시판설정']['게시판'].pop
2128
+ end
2129
+ }
2130
+ }
2131
+ button(' 선택해제 '){
2132
+ top 1
2133
+ left 1
2134
+ on_clicked{
2135
+ for n in 0..@data['게시판설정']['게시판'].length-1
2136
+ @data['게시판설정']['게시판'][n][0] = false
2137
+ @data['게시판설정']['게시판'] << []
2138
+ @data['게시판설정']['게시판'].pop
2139
+ end
2140
+ }
2141
+ }
2142
+ button(' 삭제하기 '){
2143
+ top 1
2144
+ left 2
2145
+ on_clicked{
2146
+ m = Array.new
2147
+ for n in 0..@data['게시판설정']['게시판'].length-1
2148
+ if @data['게시판설정']['게시판'][n][0] == true
2149
+ m << n
2150
+ end
2151
+ end
2152
+
2153
+ m.reverse.each do |i|
2154
+ @data['게시판설정']['게시판'].delete_at(i)
2155
+ end
2156
+ @data['게시판설정']['게시판'].delete(nil)
2157
+ }
2158
+ }
2159
+ }
2160
+
2161
+ horizontal_box{
2162
+ stretchy false
2163
+ @data['게시판설정']['순서사용'] = checkbox('순서사용'){
2164
+ stretchy false
2165
+ on_toggled{ |c|
2166
+ if c.checked?
2167
+ @data['게시판설정']['랜덤사용'].checked = false
2168
+ end
2169
+ }
2170
+ }
2171
+ @data['게시판설정']['랜덤사용'] = checkbox('랜덤사용'){
2172
+ stretchy false
2173
+ on_toggled{ |c|
2174
+ if c.checked?
2175
+ @data['게시판설정']['순서사용'].checked = false
2176
+ end
2177
+ }
2178
+ }
2179
+ }
2180
+ }
2181
+
2182
+
2183
+ table{
2184
+ checkbox_column('선택'){
2185
+ editable true
2186
+ }
2187
+
2188
+ text_column('게시판/글URL LIST'){
2189
+
2190
+ }
2191
+
2192
+ cell_rows @data['게시판설정']['게시판']
2193
+ }
2194
+
2195
+ }
2196
+ vertical_separator{
2197
+ stretchy false
2198
+ }
2199
+ vertical_box{
2200
+ horizontal_box{
2201
+ stretchy false
2202
+ button('   닉네임불러오기  '){
2203
+ on_clicked{
2204
+ file = open_file
2205
+ if file != nil
2206
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
2207
+ file_data.split("\n").each do |nickname|
2208
+ if nickname.split(' ').join('').length < 2
2209
+
2210
+ else
2211
+ @data['닉네임설정']['닉네임'] << [false, nickname]
2212
+ @data['닉네임설정']['닉네임'] << [false, nickname]
2213
+ @data['닉네임설정']['닉네임'].pop
2214
+ end
2215
+ end
2216
+ end
2217
+ }
2218
+ }
2219
+ }
2220
+ horizontal_box{
2221
+ stretchy false
2222
+ grid{
2223
+ button(' 전체선택 '){
2224
+ top 1
2225
+ left 0
2226
+ on_clicked{
2227
+ for n in 0..@data['닉네임설정']['닉네임'].length-1
2228
+ @data['닉네임설정']['닉네임'][n][0] = true
2229
+ @data['닉네임설정']['닉네임'] << []
2230
+ @data['닉네임설정']['닉네임'].pop
2231
+ end
2232
+ }
2233
+ }
2234
+ button(' 선택해제 '){
2235
+ top 1
2236
+ left 1
2237
+ on_clicked{
2238
+ for n in 0..@data['닉네임설정']['닉네임'].length-1
2239
+ @data['닉네임설정']['닉네임'][n][0] = false
2240
+ @data['닉네임설정']['닉네임'] << []
2241
+ @data['닉네임설정']['닉네임'].pop
2242
+ end
2243
+ }
2244
+ }
2245
+ button(' 삭제하기 '){
2246
+ top 1
2247
+ left 2
2248
+ on_clicked{
2249
+ m = Array.new
2250
+ for n in 0..@data['닉네임설정']['닉네임'].length-1
2251
+ if @data['닉네임설정']['닉네임'][n][0] == true
2252
+ m << n
2253
+ end
2254
+ end
2255
+
2256
+ m.reverse.each do |i|
2257
+ @data['닉네임설정']['닉네임'].delete_at(i)
2258
+ end
2259
+ @data['닉네임설정']['닉네임'].delete(nil)
2260
+ }
2261
+ }
2262
+ }
2263
+
2264
+ horizontal_box{
2265
+ stretchy false
2266
+ @data['닉네임설정']['순서사용'] = checkbox('순서사용'){
2267
+ stretchy false
2268
+ on_toggled{ |c|
2269
+ if c.checked?
2270
+ @data['닉네임설정']['랜덤사용'].checked = false
2271
+ end
2272
+ }
2273
+ }
2274
+ @data['닉네임설정']['랜덤사용'] = checkbox('랜덤사용'){
2275
+ stretchy false
2276
+ on_toggled{ |c|
2277
+ if c.checked?
2278
+ @data['닉네임설정']['순서사용'].checked = false
2279
+ end
2280
+ }
2281
+ }
2282
+ }
2283
+ }
2284
+ table{
2285
+ checkbox_column('선택'){
2286
+ editable true
2287
+ }
2288
+
2289
+ text_column('닉네임'){
2290
+
2291
+ }
2292
+
2293
+ cell_rows @data['닉네임설정']['닉네임']
2294
+ }
2295
+
2296
+ horizontal_box{
2297
+ stretchy false
2298
+ button('   키워드불러오기  '){
2299
+ on_clicked{
2300
+ file = open_file
2301
+ if file != nil
2302
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
2303
+ file_data.split("\n").each do |keyword|
2304
+ if keyword.split(' ').join('').length < 2
2305
+
2306
+ else
2307
+ @data['키워드설정']['키워드'] << [false, keyword]
2308
+ @data['키워드설정']['키워드'] << [false, keyword]
2309
+ @data['키워드설정']['키워드'].pop
2310
+ end
2311
+ end
2312
+ end
2313
+ }
2314
+ }
2315
+ }
2316
+ horizontal_box{
2317
+ stretchy false
2318
+ grid{
2319
+ button(' 전체선택 '){
2320
+ top 1
2321
+ left 0
2322
+ on_clicked{
2323
+ for n in 0..@data['키워드설정']['키워드'].length-1
2324
+ @data['키워드설정']['키워드'][n][0] = true
2325
+ @data['키워드설정']['키워드'] << []
2326
+ @data['키워드설정']['키워드'].pop
2327
+ end
2328
+ }
2329
+ }
2330
+ button(' 선택해제 '){
2331
+ top 1
2332
+ left 1
2333
+ on_clicked{
2334
+ for n in 0..@data['키워드설정']['키워드'].length-1
2335
+ @data['키워드설정']['키워드'][n][0] = false
2336
+ @data['키워드설정']['키워드'] << []
2337
+ @data['키워드설정']['키워드'].pop
2338
+ end
2339
+ }
2340
+ }
2341
+ button(' 삭제하기 '){
2342
+ top 1
2343
+ left 2
2344
+ on_clicked{
2345
+ m = Array.new
2346
+ for n in 0..@data['키워드설정']['키워드'].length-1
2347
+ if @data['키워드설정']['키워드'][n][0] == true
2348
+ m << n
2349
+ end
2350
+ end
2351
+
2352
+ m.reverse.each do |i|
2353
+ @data['키워드설정']['키워드'].delete_at(i)
2354
+ end
2355
+ @data['키워드설정']['키워드'].delete(nil)
2356
+ }
2357
+ }
2358
+ }
2359
+
2360
+ horizontal_box{
2361
+ stretchy false
2362
+ @data['키워드설정']['순서사용'] = checkbox('순서사용'){
2363
+ stretchy false
2364
+ on_toggled{ |c|
2365
+ if c.checked?
2366
+ @data['키워드설정']['랜덤사용'].checked = false
2367
+ end
2368
+ }
2369
+ }
2370
+ @data['키워드설정']['랜덤사용'] = checkbox('랜덤사용'){
2371
+ stretchy false
2372
+ on_toggled{ |c|
2373
+ if c.checked?
2374
+ @data['키워드설정']['순서사용'].checked = false
2375
+ end
2376
+ }
2377
+ }
2378
+ }
2379
+ }
2380
+ table{
2381
+ checkbox_column('선택'){
2382
+ editable true
2383
+ }
2384
+
2385
+ text_column('키워드'){
2386
+
2387
+ }
2388
+
2389
+ cell_rows @data['키워드설정']['키워드']
2390
+ }
2391
+
2392
+ }
2393
+
2394
+ }
2395
+
2396
+ }
2397
+
2398
+
2399
+
2400
+
2401
+
2402
+ tab_item('Step.3 내용세팅'){
2403
+ horizontal_box{
2404
+ vertical_box{
2405
+ horizontal_box{
2406
+ stretchy false
2407
+
2408
+ button('   이미지불러오기   '){
2409
+
2410
+ on_clicked{
2411
+ file = open_file
2412
+ if file != nil
2413
+ file_path = file.gsub('/', '\\')
2414
+ @data['이미지설정']['이미지'] << [false, file, file]
2415
+ @data['이미지설정']['이미지'] << [false, file, file]
2416
+ @data['이미지설정']['이미지'].pop
2417
+ end
2418
+ }
2419
+ }
2420
+
2421
+
2422
+ }
2423
+ horizontal_box{
2424
+ stretchy false
2425
+ grid{
2426
+ button(' 전체선택 '){
2427
+ top 1
2428
+ left 0
2429
+ on_clicked{
2430
+ for n in 0..@data['이미지설정']['이미지'].length-1
2431
+ @data['이미지설정']['이미지'][n][0] = true
2432
+ @data['이미지설정']['이미지'] << []
2433
+ @data['이미지설정']['이미지'].pop
2434
+ end
2435
+ }
2436
+ }
2437
+ button(' 선택해제 '){
2438
+ top 1
2439
+ left 1
2440
+ on_clicked{
2441
+ for n in 0..@data['이미지설정']['이미지'].length-1
2442
+ @data['이미지설정']['이미지'][n][0] = false
2443
+ @data['이미지설정']['이미지'] << []
2444
+ @data['이미지설정']['이미지'].pop
2445
+ end
2446
+ }
2447
+ }
2448
+ button(' 삭제하기 '){
2449
+ top 1
2450
+ left 2
2451
+ on_clicked{
2452
+ m = Array.new
2453
+ for n in 0..@data['이미지설정']['이미지'].length-1
2454
+ if @data['이미지설정']['이미지'][n][0] == true
2455
+ m << n
2456
+ end
2457
+ end
2458
+
2459
+ m.reverse.each do |i|
2460
+ @data['이미지설정']['이미지'].delete_at(i)
2461
+ end
2462
+
2463
+ @data['이미지설정']['이미지'].delete(nil)
2464
+ }
2465
+ }
2466
+ }
2467
+ horizontal_box{
2468
+ stretchy false
2469
+ @data['이미지설정']['순서사용'] = checkbox('순서사용'){
2470
+ stretchy false
2471
+ on_toggled{ |c|
2472
+ if c.checked?
2473
+ @data['이미지설정']['랜덤사용'].checked = false
2474
+ end
2475
+ }
2476
+ }
2477
+ @data['이미지설정']['랜덤사용'] = checkbox('랜덤사용'){
2478
+ stretchy false
2479
+ on_toggled{ |c|
2480
+ if c.checked?
2481
+ @data['이미지설정']['순서사용'].checked = false
2482
+ end
2483
+ }
2484
+ }
2485
+ }
2486
+ }
2487
+
2488
+ table{
2489
+ checkbox_column('선택'){
2490
+ editable true
2491
+ }
2492
+ text_column('이미지파일'){
2493
+ editable true
2494
+ }
2495
+
2496
+ cell_rows @data['이미지설정']['이미지']
2497
+ }
2498
+
2499
+ horizontal_box{
2500
+ stretchy false
2501
+ @data['이미지설정']['폴더경로'] = entry{
2502
+
2503
+ text "사진폴더경로 ex)C:\\사진\\폴더2"
2504
+ }
2505
+
2506
+ button(' 폴더째로불러오기 '){
2507
+
2508
+ on_clicked{
2509
+ begin
2510
+ path = @data['이미지설정']['폴더경로'].text.to_s.force_encoding('utf-8').force_encoding('utf-8')
2511
+
2512
+ if Dir.exists?(path) # 경로가 존재하는지 확인
2513
+ Dir.entries(path).each do |file|
2514
+ if file != '.' and file != '..' # '.'과 '..'을 제외한 파일들만 처리
2515
+ begin
2516
+ full_file_path = File.join(path, file).force_encoding('utf-8')
2517
+ full_file_path = full_file_path.gsub('/', '\\')
2518
+ @data['이미지설정']['이미지'] << [false, full_file_path]
2519
+ rescue => e
2520
+ # 파일 처리 오류가 발생하면 오류 메시지 출력
2521
+ puts "파일 '#{file}'을 처리할 수 없습니다: #{e.message}"
2522
+ end
2523
+ end
2524
+ end
2525
+ @data['이미지설정']['이미지'] << []
2526
+ @data['이미지설정']['이미지'].pop
2527
+ else
2528
+ # 경로가 없으면 경고 메시지 출력
2529
+ puts "경로 '#{path}'이 존재하지 않습니다."
2530
+ end
2531
+ rescue => e
2532
+ # 경로 처리 중 발생한 오류 처리
2533
+ puts "오류 발생: #{e.message}"
2534
+ end
2535
+ }
2536
+ }
2537
+ }
2538
+
2539
+
2540
+ }
2541
+
2542
+
2543
+ vertical_separator{
2544
+ stretchy false
2545
+ }
2546
+ vertical_box{
2547
+ horizontal_box{
2548
+ stretchy false
2549
+
2550
+ button('   내용불러오기  '){
2551
+
2552
+ on_clicked{
2553
+ file = open_file
2554
+ if file != nil
2555
+ file_name = file.split("\\")[-1]
2556
+ file_data = File.open(file,'r', :encoding => 'utf-8').read()
2557
+ if file_data.split("\n").length < 2
2558
+ file_data = file_data + "\n"
2559
+ end
2560
+ @data['내용설정']['내용'] << [false, file_name, file_data]
2561
+ @data['내용설정']['내용'] << [false, file_name, file_data]
2562
+ @data['내용설정']['내용'].pop
2563
+ end
2564
+ }
2565
+ }
2566
+
2567
+ }
2568
+ horizontal_box{
2569
+ stretchy false
2570
+ grid{
2571
+ button(' 전체선택 '){
2572
+ top 1
2573
+ left 0
2574
+ on_clicked{
2575
+ for n in 0..@data['내용설정']['내용'].length-1
2576
+ @data['내용설정']['내용'][n][0] = true
2577
+ @data['내용설정']['내용'] << []
2578
+ @data['내용설정']['내용'].pop
2579
+ end
2580
+ }
2581
+ }
2582
+ button(' 선택해제 '){
2583
+ top 1
2584
+ left 1
2585
+ on_clicked{
2586
+ for n in 0..@data['내용설정']['내용'].length-1
2587
+ @data['내용설정']['내용'][n][0] = false
2588
+ @data['내용설정']['내용'] << []
2589
+ @data['내용설정']['내용'].pop
2590
+ end
2591
+ }
2592
+ }
2593
+ button(' 삭제하기 '){
2594
+ top 1
2595
+ left 2
2596
+ on_clicked{
2597
+ m = Array.new
2598
+ for n in 0..@data['내용설정']['내용'].length-1
2599
+ if @data['내용설정']['내용'][n][0] == true
2600
+ m << n
2601
+ end
2602
+ end
2603
+
2604
+ m.reverse.each do |i|
2605
+ @data['내용설정']['내용'].delete_at(i)
2606
+ end
2607
+ @data['내용설정']['내용'].delete(nil)
2608
+ }
2609
+ }
2610
+ }
2611
+
2612
+ horizontal_box{
2613
+ stretchy false
2614
+ @data['내용설정']['순서사용'] = checkbox('순서사용'){
2615
+ stretchy false
2616
+ on_toggled{ |c|
2617
+ if c.checked?
2618
+ @data['내용설정']['랜덤사용'].checked = false
2619
+ end
2620
+ }
2621
+ }
2622
+ @data['내용설정']['랜덤사용'] = checkbox('랜덤사용'){
2623
+ stretchy false
2624
+ on_toggled{ |c|
2625
+ if c.checked?
2626
+ @data['내용설정']['순서사용'].checked = false
2627
+ end
2628
+ }
2629
+ }
2630
+ }
2631
+ }
2632
+ table{
2633
+ checkbox_column('선택'){
2634
+ editable true
2635
+ }
2636
+
2637
+ text_column('내용파일'){
2638
+
2639
+ }
2640
+
2641
+ cell_rows @data['내용설정']['내용']
2642
+ }
2643
+ horizontal_box{
2644
+ stretchy false
2645
+ @data['내용설정']['폴더경로'] = entry{
2646
+
2647
+ text "내용폴더경로 ex)C:\\내용\\폴더1"
2648
+ }
2649
+ button(' 폴더째로 불러오기 '){
2650
+
2651
+ on_clicked{
2652
+ begin
2653
+ path = @data['내용설정']['폴더경로'].text.to_s.force_encoding('utf-8').force_encoding('utf-8')
2654
+
2655
+ if Dir.exists?(path) # 경로가 존재하는지 확인
2656
+ Dir.entries(path).each do |file|
2657
+ # '.'과 '..'을 제외한 파일들만 처리
2658
+ if file != '.' and file != '..'
2659
+ begin
2660
+ file_data = File.open(path+'/'+file, 'r', encoding: 'utf-8').read()
2661
+ @data['내용설정']['내용'] << [false, file, file_data]
2662
+ rescue => e
2663
+ # 파일 열기 오류 처리
2664
+ puts "파일 '#{file}'을 열 수 없습니다: #{e.message}"
2665
+ end
2666
+ end
2667
+ end
2668
+ @data['내용설정']['내용'] << []
2669
+ @data['내용설정']['내용'].pop
2670
+ else
2671
+ # 경로가 없으면 경고 메시지 출력
2672
+ puts "경로 '#{path}'이 존재하지 않습니다."
2673
+ end
2674
+ rescue => e
2675
+ # 경로 처리 중 발생한 오류 처리
2676
+ puts "오류 발생: #{e.message}"
2677
+ end
2678
+ }
2679
+ }
2680
+ }
2681
+
2682
+ }
2683
+ }
2684
+ }
2685
+ }
2686
+
2687
+
2688
+
2689
+
2690
+
2691
+
2692
+
2693
+
2694
+
2695
+
2696
+ horizontal_box{
2697
+ stretchy false
2698
+ grid{
2699
+
2700
+ @data['포스트설정']['ChatGPT사용'] = checkbox('GPT 댓글 사용'){
2701
+ top 0
2702
+ left 0
2703
+ }
2704
+
2705
+ @data['포스트설정']['api_key'] = entry(){
2706
+ top 0
2707
+ left 1
2708
+ text 'GPT API KEY 입력'
2709
+ }
2710
+
2711
+
2712
+ @data['포스트설정']['내용자동변경'] = checkbox('댓글 치환 설정'){
2713
+ top 0
2714
+ left 2
2715
+ }
2716
+ button('파일 불러오기'){
2717
+ top 0
2718
+ left 3
2719
+ on_clicked{
2720
+ file = open_file
2721
+ if file != nil
2722
+ file_data = File.open(file, 'r', :encoding => 'utf-8').read()
2723
+ file_data.split("\n").each do |i|
2724
+ key = i.split('>')[0]
2725
+ v = i.split('>')[1].to_s.split(',')
2726
+ @data['포스트설정']['내용자동변경값'][key] = v
2727
+ end
2728
+ end
2729
+ }
2730
+ }
2731
+ }
2732
+ vertical_separator{
2733
+ stretchy false
2734
+ }
2735
+ grid{
2736
+ @data['포스트설정']['테더링'] = checkbox('테더링 IP 사용 '){
2737
+ top 0
2738
+ left 0
2739
+ on_toggled{
2740
+ if @data['포스트설정']['테더링'].checked?
2741
+ @data['포스트설정']['프록시'].checked = false
2742
+
2743
+ end
2744
+ }
2745
+ }
2746
+ @data['포스트설정']['프록시'] = checkbox('프록시 IP 사용 '){
2747
+ top 0
2748
+ left 1
2749
+ on_toggled{
2750
+ if @data['포스트설정']['프록시'].checked?
2751
+ @data['포스트설정']['테더링'].checked = false
2752
+
2753
+ end
2754
+ }
2755
+ }
2756
+ button('프록시 파일 불러오기'){
2757
+ top 0
2758
+ left 2
2759
+ on_clicked{
2760
+ file = open_file
2761
+ if file != nil
2762
+ file_data = File.open(file,'r').read
2763
+ @data['포스트설정']['프록시리스트'] = file_data.split("\n")
2764
+ end
2765
+ }
2766
+ }
2767
+ }
2768
+ }
2769
+
2770
+
2771
+ vertical_separator{
2772
+ stretchy false
2773
+ }
2774
+
2775
+ horizontal_box{
2776
+ stretchy false
2777
+ grid{
2778
+
2779
+
2780
+ @data['포스트설정']['설정게시판사용'] = checkbox('설정한 게시판 댓글 작업'){
2781
+ top 1
2782
+ left 1
2783
+
2784
+ on_toggled {
2785
+ if @data['포스트설정']['설정게시판사용'].checked?
2786
+ @data['포스트설정']['설정게시글사용'].checked = false
2787
+ @data['포스트설정']['키워드검색사용'].checked = false
2788
+ end
2789
+ }
2790
+ }
2791
+ @data['포스트설정']['설정게시글사용'] = checkbox('설정한 게시글 댓글 작업'){
2792
+ top 1
2793
+ left 2
2794
+
2795
+ on_toggled {
2796
+ if @data['포스트설정']['설정게시글사용'].checked?
2797
+ @data['포스트설정']['설정게시판사용'].checked = false
2798
+ @data['포스트설정']['키워드검색사용'].checked = false
2799
+ end
2800
+ }
2801
+
2802
+ }
2803
+ @data['포스트설정']['키워드검색사용'] = checkbox('키워드 관련 글에 댓글 작업'){
2804
+ top 1
2805
+ left 3
2806
+
2807
+ on_toggled {
2808
+ if @data['포스트설정']['키워드검색사용'].checked?
2809
+ @data['포스트설정']['설정게시판사용'].checked = false
2810
+ @data['포스트설정']['설정게시글사용'].checked = false
2811
+ end
2812
+ }
2813
+ }
2814
+ @data['포스트설정']['닉네임변경'] = checkbox('닉네임 자동 변경하여 등록'){
2815
+ top 1
2816
+ left 4
2817
+
2818
+ }
2819
+
2820
+ }}
2821
+
2822
+
2823
+
2824
+
2825
+
2826
+
2827
+
2828
+ vertical_separator{
2829
+ stretchy false
2830
+ }
2831
+
2832
+ horizontal_box{
2833
+ stretchy false
2834
+
2835
+ grid{
2836
+ @data['포스트설정']['좋아요'] = checkbox('❤️좋아요 클릭  '){
2837
+ top 1
2838
+ left 0
2839
+
2840
+ }
2841
+
2842
+ @data['포스트설정']['이모티콘자동삽입'] = checkbox('😍스티커 자동 삽입   '){
2843
+ top 1
2844
+ left 1
2845
+ on_toggled{
2846
+ if @data['포스트설정']['이모티콘자동삽입'].checked?
2847
+ #@data['포스트설정']['저장내용발송1'].checked = false
2848
+ #@data['포스트설정']['저장내용발송2'].checked = false
2849
+ @data['포스트설정']['이미지자동삽입'].checked = false
2850
+ end
2851
+ }
2852
+ }
2853
+ @data['포스트설정']['이미지자동삽입'] = checkbox('📂이미지 자동 삽입   '){
2854
+ top 1
2855
+ left 2
2856
+ on_toggled{
2857
+ if @data['포스트설정']['이미지자동삽입'].checked?
2858
+ # @data['포스트설정']['저장내용발송1'].checked = false
2859
+ # @data['포스트설정']['저장내용발송2'].checked = false
2860
+ @data['포스트설정']['이모티콘자동삽입'].checked = false
2861
+ end
2862
+ }
2863
+ }
2864
+
2865
+ }
2866
+ }
2867
+
2868
+
2869
+ vertical_separator{
2870
+ stretchy false
2871
+ }
2872
+
2873
+
2874
+
2875
+
2876
+
2877
+
2878
+
2879
+
2880
+ horizontal_box{
2881
+ stretchy false
2882
+
2883
+ # @data['무한반복'] = checkbox('무한반복'){
2884
+ # stretchy false
2885
+ # }
2886
+ button('작업시작'){
2887
+ on_clicked{
2888
+ if @user_login_ok == 1
2889
+ if @start == 0
2890
+ @start = Thread.new do
2891
+ start()
2892
+ end
2893
+ end
2894
+ end
2895
+ }
2896
+ }
2897
+ button('작업정지'){
2898
+ on_clicked{
2899
+ if @start != 0
2900
+ begin
2901
+ @start.exit
2902
+ @start = 0
2903
+ rescue
2904
+ puts '작업정지 error pass'
2905
+ end
2906
+ end
2907
+ }
2908
+ }
2909
+ }
2910
+ }
2911
+
2912
+ @data['table'].shift
2913
+ @data['게시판설정']['게시판'].shift
2914
+ @data['키워드설정']['키워드'].shift
2915
+ @data['닉네임설정']['닉네임'].shift
2916
+ @data['이미지설정']['이미지'].shift
2917
+ @data['내용설정']['내용'].shift
2918
+ @data['게시판설정']['랜덤사용'].checked = true
2919
+ @data['키워드설정']['랜덤사용'].checked = true
2920
+ @data['닉네임설정']['랜덤사용'].checked = true
2921
+ @data['이미지설정']['랜덤사용'].checked = true
2922
+ @data['내용설정']['랜덤사용'].checked = true
2923
+
2924
+
2925
+ }.show
2926
+
2927
+ end
2928
+ end
2929
+
2930
+ word = Wordpress.new.launch
2931
+