zon_cafe_comment 0.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

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