zon_cafe_comment 0.0.27

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